G.Chiozzi
22/02/96
Extended CCS is a library written in C++ on top of CCS. It contains functions and simple classes and requires a minimal knowledge of C++ syntax.
It runs only on Workstation.
Purpose of the library is:
The library is not (and does not want to be) a complete C++ replacement of CCS.
Only the commonly used parts of CCS are integrated in ECCS.
In the Makefile:
In the code:
#include "ECCS.h" int main(int, char *argv[]) { ccsCOMPL_STAT stat; stat = ccsInit(argv[0]); eccsErrLog(stat,"Error in Init "); ..... application code ..... stat = ccsExit(); eccsErrLog(stat,"Error in ccsExit"); }
#include "msg.h" ... ccsERROR error; msgCMD command; ccsENVNAME destEnv; ccsPROCNAME destProc; char cmdpar[] = "my cmd buffer"; ... ... strcpy((char *)destProc, argv[1]); strcpy((char *)destEnv, argv[2]); strcpy((char *)command,argv[3]); if (msgSendCommand (command, 0, destEnv, destProc, cmdpar,strlen(cmdpar) +1, 0, &error) == FAILURE) ... error processing ... else ... normal processing ...
#include "msgMESSAGE.h" ... msgMESSAGE msg; msg.Procname(argv[1]) .Destenv(argv[2]) .Command(argv[3]) .Buffer("my cmd buffer"); if (msg.SendCommand() == FAILURE) ... error processing ... else ... normal processing ...
class msgMESSAGE: public msgRAW_MESSAGE { public: msgMESSAGE(); msgMESSAGE(const msgHEADER *msg); msgMESSAGE(const msgMESSAGE &source); ccsCOMPL_STAT Parse(const msgHEADER *msg); ccsCOMPL_STAT Receive(msgTIMEOUT timeout = msgNO_TIMEOUT, const msgRECEIVEFILTER *filter = NULL); ccsCOMPL_STAT SendCommand(); ccsCOMPL_STAT SendCommand(msgCHECKFLAG flag); ccsCOMPL_STAT SendReply(); ccsCOMPL_STAT SendReply(const char *newBuffer, msgLENGTH newBuflen=0, vltLOGICAL lastReply=ccsTRUE); ccsCOMPL_STAT SendReply(const ccsERROR &errmsg); /* Methods to access safely the values of parameters */ vltUINT8 Type() const; msgMESSAGE &Type(vltUINT8 newType); const char *Command() const; msgMESSAGE &Command(const msgCMD newCommand); msgCMDID CommandId() const; msgMESSAGE &CommandId(msgCMDID newCommandId); const char *Destenv() const; msgMESSAGE &Destenv(const ccsENVNAME newDestenv); const char *Destproc() const; msgMESSAGE &Destproc(const ccsPROCNAME newDestProc); const msgPROCESSID &OrgId() const; msgMESSAGE &OrgId(const msgPROCESSID &newOrgId); vltLOGICAL LastReply() const; msgMESSAGE &LastReply(vltLOGICAL newLastReply); const char *Buffer() const; msgLENGTH Buflen() const; msgMESSAGE &Buffer(const char *newBuffer, msgLENGTH newBuflen=0); ccsERROR &Errmsg(); msgMESSAGE &Errmsg(const ccsERROR &newErrmsg); msgCHECKFLAG Check() const; msgMESSAGE &Check(msgCHECKFLAG flag); msgMESSAGE &operator =(const msgMESSAGE &source); static ccsCOMPL_STAT GlobalCheckOn(msgCHECKFLAG flag); static ccsCOMPL_STAT GlobalCheckOff(); }
// Declare the message variable msgMESSAGE myMessage; // Receive the command (by default with no timeout and no filtering) myMessage.Receive(); // Check for the command if( strcmp(myMessage.Command(), "MYCMD) != 0) return; // Send the last reply back to the sender of the message // setting at the same time the message buffer to be send myMessage.SendReply("This is my reply");
// Declare the message variable msgMESSAGE myMessage; // Set the command parameters myMessage.Command("MYCMD"); myMessage.Destenv("wte16"); myMessage.Procname("MYPROC"); myMessage.Buffer("Data sent"); // Send the command myMessage.SendCommand(); // Receive the reply int flag = ccsFALSE; while(flag == ccsFALSE) { // (checking of the specific reply is not shown) myMessage.Receive(); flag = myMessage.LastReply(); printf("Reply buffer: %s\n", myMessage.Buffer()); }
int main(int argc, char *argv[]) { dbSYMADDRESS pointName; dbATTRIBUTE attrName; dbTYPE dataType[dbMAX_FIELD_CNT]; vltINT32 value; vltINT32 actual; vltUINT16 recordCnt; dbATTRTYPE attrType; ccsERROR error; ccsInit(argv[0],0,NULL,NULL,&error); dbOpen(ccsLOCAL_ENV,&error); strcpy((char *) pointName,":PARAMS:SCALARS"); strcpy((char *) attrName,"scalar_int32"); if ( dbReadSymbolic(pointName,attrName,dataType,(char*)&value, sizeof(value), &actual,&recordCnt,&attrType,&error)== FAILURE ){} value = value + 5; if ( dbWriteSymbolic(pointName,attrName,dataType, (char*)&value, sizeof(value), &actual,recordCnt,attrType,&error) == FAILURE ) { } if ( dbReadSymbolic(pointName,attrName,dataType, (char*)&value, sizeof(value), &actual,&recordCnt,&attrType,&error)== FAILURE ) { } ccsExit(&error); return 0; }
Using dbRead() and dbWrite():
int main(int, char *argv[]) { ccsInit(argv[0]); dbOpen(); vltINT32 value; if( dbRead(&value,":PARAMS:SCALARS.scalar_int32") ) {} value = value + 5; if( dbWrite(&value,":PARAMS:SCALARS.scalar_int32") ) {} if( dbRead(&value,":PARAMS:SCALARS.scalar_int32") ) {} ccsExit(); return 0; }
Using eccsDB_ATTR classes:
int main(int, char *argv[]) { ccsInit(argv[0]); dbOpen(); eccsDB_INT32 value(":PARAMS:SCALARS.scalar_int32"); value = (vltINT32)value + 5; ccsExit(); return 0; }
Basic data types:
Database vectors:
Database tables:
Tables are implemented using a template class since it is not possible to provide pre-defined classes:
The record definition class MY_TABLE_RECORD must be a subclass of eccsDB_TABLE_RECORD
#include "eccsDB_VECTOR.h" int main(int, char *argv[]) { ccsCOMPL_STAT stat,st; stat = ccsInit(argv[0]); stat = dbOpen(); vltINT32 recordCnt; vltINT32 i; eccsDB_VECTOR_vltINT32 vector(":PARAMS:VECTORS.vector_int32"); recordCnt = vector.RecordCnt(); vltINT32 *array = new vltINT32[recordCnt]; st = vector.GetValue(array); st = vector.SetValue(array); // Testing subscript operator for(i =0; i<recordCnt; i++) { vector[i] = recordCnt-i; cout << " " << (vltINT32)vector[i]; } for(i =0; i<recordCnt; i++) { array[i] = vector[i]; cout << " " << array[i]; } stat = dbExit(); }
#include "eccsDB_TABLE.h" // user provided TABLE class for db table TABLES.full_table class TABLE : public eccsDB_TABLE_RECORD { public: vltLOGICAL logical; vltINT8 int8; vltUINT32 uint32; ccsCOMPL_STAT Unpack( void *buffer ) { memcpy( &logical, buffer,sizeof(vltLOGICAL)); buffer += sizeof(vltLOGICAL); memcpy( &int8, buffer,sizeof(vltINT8) ); buffer += sizeof(vltINT8); memcpy( &uint32, buffer,sizeof(vltUINT32) ); return(SUCCESS); } ccsCOMPL_STAT Pack( void *buffer ) { int size; dbFillBuf( (char**)&buffer, (char*)&logical ,&size, dbLOGICAL); dbFillBuf( (char**)&buffer, (char*)&int8 ,&size, dbINT8); dbFillBuf( (char**)&buffer, (char*)&uint32 ,&size, dbUINT32); return(SUCCESS); } }; int main(int, char *argv[]) { ccsCOMPL_STAT stat,st; stat = ccsInit(argv[0]); stat = dbOpen(); vltINT32 recordCnt; // Define a TABLE eccsDB_TABLE<TABLE> table("<alias>TABLES.full_table"); if ( table.ErrStatus() == FAILURE ) { } // Get the number of records in the array recordCnt = table.RecordCnt(); // Allocate the memory array TABLE *table_array = new TABLE[recordCnt]; //Read all table st = table.GetValue(table_array); // Modify values in memory for ( i=0;i<recordCnt;i++) { table_array[i].logical=TRUE; table_array[i].int8 = i; table_array[i].uint32 = i; } // Rewrite whole table with changes st = table.SetValue(table_array); // Read one by one table_array[i] = table[i]; stat = dbExit(); } /* end main() */
#include "eccsDB_TABLE.h" class simREPLY_TABLE : public eccsDB_TABLE_RECORD { public: vltBYTES8 command; vltBYTES256 reply; ccsCOMPL_STAT Unpack( void *buffer ) { memcpy( &command, buffer,sizeof(command) ); buffer = buffer+sizeof(command); memcpy( &reply, buffer,sizeof(reply)); return(SUCCESS); } ccsCOMPL_STAT Pack( void *buffer ) { int size; dbFillBuf( (char**)&buffer, (char*)&command ,&size, dbBYTES8); dbFillBuf( (char**)&buffer, (char*)&reply ,&size, dbBYTES256); return(SUCCESS); } void Print() { cout << "Command: " << command << " - Reply: " << reply; cout << endl; } }; int main(int, char *argv[]) { /************/ /* Init */ /************/ ccsCOMPL_STAT stat,st; stat = ccsInit(argv[0]); stat = dbOpen(); vltINT32 recordCnt; // Define a TABLE simREPLY_TABLE testRec; eccsDB_TABLE<simREPLY_TABLE> table("<alias>eccsTest:tab.replies"); if ( table.ErrStatus() == FAILURE ) { } // Get the number of records in the array recordCnt = table.RecordCnt(); // Allocate the memory array simREPLY_TABLE *table_array = new simREPLY_TABLE[recordCnt]; /* Read random values and print contents */ cout << "Read values by contents: " << endl; testRec = table["COMMENT"]; testRec.Print(); testRec = table["SETUP"]; testRec.Print(); stat = dbExit(); } // __o0o__
The implementation of the eccsERROR class provides the following advantages:
- Any time an instance of eccsERROR is deleted (or exit out of scope), it is automatically checked and the stack is closed if it contains errors.
- The defaults error stack is automatically closed when the application exits.
struct eccsERROR: public ccsERROR { eccsERROR(); ~eccsERROR(); ccsCOMPL_STAT Add(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, ...); ccsCOMPL_STAT Add_v(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, va_list va_parList); ccsCOMPL_STAT SysAdd(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, char *sysModule=modRTAP, ...); ccsCOMPL_STAT SysAdd_v(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, char *sysModule, va_list va_parList); ccsCOMPL_STAT Close(); ccsCOMPL_STAT Display(vltLOGICAL syncFlag=FALSE); ccsCOMPL_STAT Print(); ccsCOMPL_STAT Reset(); eccsERROR &operator =(const ccsERROR &e); /* This static section is used to handle default eccs error stack */ static void DefErrorStack(eccsERROR *err = NULL); };
// ======================================================== // Calling an ECCS function and handling errors with the // default error stack ccsCOMPL_STAT status; status = ccsInit(argv[0]); if(status == FAILURE) { // Notice that the stack is closed automatically on exit // and I do not need to close it explicitly stdErr->Add(....parms....); // This line is equivalent to: // errAdd(...params....); // uses stdErr by default exit(1); } // ============================================================ // Calling a standard CCS function and handling errors with the // default error stack ccsCOMPL_STAT status; status = dbMultiRead(listid,stdErr); if(status == FAILURE) { stdErr->Add(....parms....); } // ============================================================
All the classes that want to provide error handling must be derived from the class eccsERROR_CLASS.
class eccsERROR_CLASS { public: eccsERROR_CLASS(eccsERROR *s = stdErr); ccsCOMPL_STAT ErrStatus(); eccsERROR &ErrStack(); ccsCOMPL_STAT ErrStackClose(); ccsCOMPL_STAT ErrStackReset(); ccsCOMPL_STAT ObjStatus(); operator ccsCOMPL_STAT(); operator eccsERROR &(); protected: eccsERROR_CLASS &ErrStatus(ccsCOMPL_STAT s); eccsERROR_CLASS &ErrReset(); eccsERROR_CLASS &ObjStatus(ccsCOMPL_STAT s); eccsERROR_CLASS &operator =(const ccsCOMPL_STAT s); ccsCOMPL_STAT ErrAdd(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, ...); ccsCOMPL_STAT ErrAdd_v(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, va_list va_parList); ccsCOMPL_STAT ErrSysAdd(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, char *sysModule=modRTAP, ...); ccsCOMPL_STAT ErrSysAdd_v(ccsMODULEID moduleId, vltINT16 errorNumber, ccsLOC_ID locId, char *sysModule, va_list va_parList); };
class eccsDB_ATTR : public eccsERROR_CLASS { public: eccsDB_ATTR(const dbSYMADDRESS pointName); eccsDB_ATTR(const eccsDB_ATTR &attr); virtual ~eccsDB_ATTR(); virtual ccsCOMPL_STAT GetValue(void *buffer); virtual ccsCOMPL_STAT SetValue(void *buffer); virtual ccsCOMPL_STAT DbRead(void *buffer); }; ccsCOMPL_STAT eccsDB_ATTR::GetValue(void *buffer) { ccsCOMPL_STAT stat = SUCCESS; // Always call ErrReset() first, except in constructor, destructor // and special cases with nested functions ErrReset(); stat = DbRead(buffer); if(stat == FAILURE) { ErrAdd("eccs",eccsERR_READATTR,__FILE_LINE__,symAddr,dbEMPTY); return stat; } return stat; } /* eccsDB_ATTR::GetValue() */
Using error handling features:
eccsDB_ATTR attribute("<alias>TABLES.full_table"); if ( attribute.ErrStatus() == FAILURE ) { cout << "failure Invalid table" << endl; exit(1); } attribute.GetValue(buffer); if ( attribute.ErrStatus() == FAILURE ) { attribute.ErrStack().Add(....) } attribute.GetValue(buffer); if ( attribute.ErrStatus() == FAILURE ) { // The error is recovered attribute.ErrStackReset(); } // Store somewhere an error stack (for example to send // an error reply) eccsERROR errStack = attribute.ErrStack();
This presentation has shown only some of the most important aspects of the library.
The bigger benefits come using this library in congiunction with the evh library
For more details look at: