// // File: hdbClass.cpp // // Legal Notice: This file is part of the HadronZoo C++ Class Library. Copyright 2025 HadronZoo Project (http://www.hadronzoo.com) // // The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free // Software Foundation, either version 3 of the License, or any later version. // // The HadronZoo C++ Class Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR // A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses. //
// // Implimentation of the HadronZoo Proprietary Database Suite //
#include <iostream> #include <fstream> #include <cstdio>
#include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h>
#include "hzBasedefs.h" #include "hzString.h" #include "hzChars.h" #include "hzChain.h" #include "hzDate.h" #include "hzTextproc.h" #include "hzCodec.h" #include "hzDocument.h" #include "hzDirectory.h" #include "hzDatabase.h" #include "hzDelta.h" #include "hzProcess.h"
using namespace std ;
/* ** Variables */
// Group 1 Datatyeps: C++ Fundamental global const hdbCpptype* datatype_DIGEST ; // MD5 hash value global const hdbCpptype* datatype_DOUBLE ; // 64 bit floating point value global const hdbCpptype* datatype_INT64 ; // 64-bit Signed integer global const hdbCpptype* datatype_INT32 ; // 32-bit Signed integer global const hdbCpptype* datatype_INT16 ; // 16-bit Signed integer global const hdbCpptype* datatype_BYTE ; // 8-bit Signed integer global const hdbCpptype* datatype_UINT64 ; // 64-bit Positive integer global const hdbCpptype* datatype_UINT32 ; // 32-bit Positive integer global const hdbCpptype* datatype_UINT16 ; // 16-bit Positive integer global const hdbCpptype* datatype_UBYTE ; // 8-bit Positive integer global const hdbCpptype* datatype_BOOL ; // either true or false
// Group 2 Datatypes: HadronZoo Defined types (fixed size) global const hdbHzotype* datatype_DOMAIN ; // Internet Domain global const hdbHzotype* datatype_EMADDR ; // Email Address global const hdbHzotype* datatype_URL ; // Universal Resource Locator global const hdbHzotype* datatype_PHONE ; // Phone number (limited aphabet, standard form, likely to be unique to data object) global const hdbHzotype* datatype_IPADDR ; // IP Address global const hdbHzotype* datatype_TIME ; // No of seconds since midnight (4 bytes) global const hdbHzotype* datatype_SDATE ; // No of days since Jan 1st year 0000 global const hdbHzotype* datatype_XDATE ; // Full date & time global const hdbHzotype* datatype_STRING ; // Any string, treated as a single value global const hdbHzotype* datatype_TEXT ; // Any string, treated as a series of words, stored on disk, frequent change global const hdbHzotype* datatype_BINARY ; // File assummed to be un-indexable (eg image). Stored on disk, infrequent change. global const hdbHzotype* datatype_TXTDOC ; // Document from which text can be extracted/indexed. Stored on disk, infrequent change.
extern hzDeltaClient* _hzGlobal_DeltaClient ; // Total current delta clients
/* ** Init Sequence Functions */
const char* _hdb_showinitstate (hdbIniStat nState) { static const char* _istates[] = { "HDB_CLASS_INIT_NONE", "HDB_CLASS_INIT_PROG", "HDB_CLASS_INIT_DONE", "HDB_REPOS_INIT_PROG", "HDB_REPOS_INIT_DONE", "HDB_REPOS_OPEN", "HDB_REPOS_INIT_UNDEF", "" } ;
if (nState == HDB_CLASS_INIT_NONE) return _istates[0] ; if (nState == HDB_CLASS_INIT_PROG) return _istates[1] ; if (nState == HDB_CLASS_INIT_DONE) return _istates[2] ; if (nState == HDB_REPOS_INIT_PROG) return _istates[3] ; if (nState == HDB_REPOS_INIT_DONE) return _istates[4] ; if (nState == HDB_REPOS_OPEN) return _istates[5] ;
return _istates[6] ; }
void _hdb_ck_initstate (const hzString& objName, hdbIniStat eActual, hdbIniStat eExpect) { // Exit on cases of wrong initialization
if (eActual == eExpect) return ;
hzexit(E_INITFAIL, "Target DB entity [%s] Actual init state %s. Expected %s\n", *objName, _hdb_showinitstate(eActual), _hdb_showinitstate(eExpect)) ; }
/* ** hdbEnum Functions */
hzEcode hdbEnum::AddItem (const hzString& strValue) { // Add a string value to the enumerated set of strings using the default value system.
uint32_t strNo ; // String number
if (!strValue) return E_ARGUMENT ;
// strNo = _hzGlobal_ReposStrings->Locate(*strValue) ; // if (!strNo) // strNo = _hzGlobal_ReposStrings->Insert(strValue) ; strNo = m_Numbers.Count() ;
m_Numbers.Add(strNo) ; m_Strings.Add(strValue) ; return E_OK ; }
hzEcode hdbEnum::AddItem (const hzString& strValue, uint32_t numValue) { // Add a string value to the enumerated set of strings but with a specified value.
uint32_t strNo ; // String number
if (!strValue) return E_ARGUMENT ;
// strNo = _hzGlobal_ReposStrings->Locate(*strValue) ; // if (!strNo) // strNo = _hzGlobal_ReposStrings->Insert(strValue) ; strNo = m_Numbers.Count() ;
m_Numbers.Add(strNo) ; m_Strings.Add(strValue) ; return E_OK ; }
/* ** hdbMember Functions */
hdbMember::hdbMember (void) { m_pClass = 0 ; m_pType = 0 ; m_pSpec = 0 ; m_MemberUID = 0 ; m_popCtl = HDB_MBR_POP_UNSPECIFIED ; m_nPosn = 0 ; m_nOsetStd = -1 ; m_nOsetAux = -1 ; m_sizeCore = 0 ; m_sizeAux = 0 ; m_sizeDatum = 0 ; }
hzEcode hdbMember::Init (const hdbClass* pClass, const hdbDatatype* pType, const hzString& name, uint32_t nPosn, hdbPopCtl popCtl) { // Initialize the data object class member with name and data type // // Arguments: 1) pClass Data class this member belongs to // 2) type HadronZoo data type // 3) name Member name // 4) minPop Minimum number of values the member may have in a real class instance (for repository inserts) // 5) maxPop Maximum number of values // 6) nPosn Member position // // Returns: E_ARGUMENT If the class, data type, or member name has not been supplied // E_SETONCE If we are attempting to rename the member // E_OK If operation was successful
_hzfunc("hdbClass::Member::Init") ;
const hdbEnum* pEnum ; // The actual defined enum (for multi-value enum members only) hzEcode rc = E_OK ; // Return code
// No member name? if (!pClass) return E_ARGUMENT ; if (!pType) return E_ARGUMENT ; if (!name) return E_ARGUMENT ;
// Member already Init? if (m_Name) return E_SETONCE ;
m_pClass = pClass ; m_Name = name ; m_pType = pType ; m_popCtl = popCtl ; m_nPosn = nPosn ;
// Set value size according to type and expected population if (Singular()) { switch (pType->Basetype()) { case BASETYPE_DIGEST: m_sizeDatum = 16 ; break ;
case BASETYPE_PHONE: case BASETYPE_XDATE: case BASETYPE_DOUBLE: case BASETYPE_UINT64: case BASETYPE_INT64: m_sizeDatum = 8 ; break ;
case BASETYPE_BINARY: case BASETYPE_TXTDOC: m_sizeCore = m_sizeDatum = 4 ; m_sizeAux = 8 ; break ;
case BASETYPE_UINT32: case BASETYPE_INT32: case BASETYPE_TIME: case BASETYPE_SDATE: case BASETYPE_STRING: case BASETYPE_DOMAIN: case BASETYPE_EMADDR: case BASETYPE_URL: case BASETYPE_IPADDR: case BASETYPE_TEXT: case BASETYPE_APPDEF: m_sizeDatum = 4 ; break ;
case BASETYPE_UINT16: case BASETYPE_INT16: if (Multiple()) rc = hzerr(E_TYPE, "UINT16/INT16 cannot be multiple value") ; m_sizeDatum = 2 ; break ;
case BASETYPE_ENUM: m_sizeDatum = m_sizeCore = 1 ; break ;
case BASETYPE_BYTE: case BASETYPE_UBYTE: m_sizeDatum = 1 ; break ;
case BASETYPE_BOOL: case BASETYPE_TBOOL: m_sizeDatum = 0 ; if (Multiple()) rc = hzerr(E_TYPE, "BOOL/TBOOL cannot be multiple value") ; break ;
default: rc = hzerr(E_TYPE, "Data type %s cannot be singular", Basetype2Txt(pType->Basetype())) ; break ; } } else { // Multiple - so less applicable data types switch (pType->Basetype()) { case BASETYPE_CLASS: m_sizeDatum = m_sizeCore = 8 ; break ;
case BASETYPE_ENUM: pEnum = dynamic_cast<const hdbEnum*>(m_pType) ; if (!pEnum) return hzerr(E_TYPE, "ENUM type but no enum found") ;
m_sizeCore = (pEnum->Count()/8) ; m_sizeCore += pEnum->Count()%8 ? 1 : 0 ; m_sizeDatum = m_sizeCore ; break ;
default: rc = hzerr(E_TYPE, "Data type %s cannot be multiple value", Basetype2Txt(pType->Basetype())) ; break ; } }
if (rc != E_OK) return rc ;
if (Singular()) m_sizeCore = m_sizeDatum ; else m_sizeCore = 8 ;
return E_OK ; }
hzEcode hdbMember::SetSpec (const hdsFldspec* pSpec) const { // Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation. // // Argument: pSpec The supplied Dissemino field spec // // Returns: E_ARGUMENT If no field spec is supplied // E_DUPLICATE If the field spec has already been set // E_OK Operation successful
if (!pSpec) return E_ARGUMENT ; if (m_pSpec) return E_DUPLICATE ;
m_pSpec = pSpec ; return E_OK ; }
hzEcode hdbMember::_setId (uint32_t mbrId) const { // Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation. // // Argument: pSpec The supplied Dissemino field spec // // Returns: E_ARGUMENT If no field spec is supplied // E_DUPLICATE If the field spec has already been set // E_OK Operation successful
if (!mbrId) return E_ARGUMENT ; if (m_MemberUID) return E_DUPLICATE ;
m_MemberUID = mbrId ; return E_OK ; }
hzEcode hdbMember::_setOset (int32_t nOset) const { // Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation. // // Argument: pSpec The supplied Dissemino field spec // // Returns: E_OK Operation always successful
m_nOsetStd = nOset ; return E_OK ; }
hzEcode hdbMember::_setAux (int32_t nAux) const { // Set Field Specification for the member. Relevant only to webapp forms. Not relevant to HDB operation. // // Argument: pSpec The supplied Dissemino field spec // // Returns: E_OK Operation always successful
m_nOsetAux = nAux ; return E_OK ; }
/* ** hdbClass Functions */
hdbClass::hdbClass (hdbADP& adp, hdbClsDgn designation) { // Data class constructor. Note the expectation that the data class will belong to a pre-existing ADP
m_pADP = &adp ; m_arrMembers.SetDefault((hdbMember*)0) ; m_eClassInit = HDB_CLASS_INIT_NONE ; m_eDesignation = designation ; m_nCoreLen = 0 ; m_nLitmusBits = 0 ; m_nLitmusSize = 0 ; m_ClassUID = 0 ; m_nBinaries = 0 ; m_nArrays = 0 ; m_Basetype = BASETYPE_CLASS ; }
hdbClass::~hdbClass (void) { _clear() ; }
void hdbClass::_clear (void) { // Private function to clear data object class descriptor. Note this is always assumed to be successful // // Arguments: None // Returns: None
_hzfunc("hdbClass::_clear") ;
hdbMember* pMbr ; // Member pointer uint32_t x ; // Member iterator
// We only need this because the hzArray is of pointers
for (x = 0 ; x < m_arrMembers.Count() ; x++) { pMbr = m_arrMembers[x] ; if (pMbr) delete pMbr ; }
m_mapMembers.Clear() ; m_arrMembers.Clear() ; }
hzEcode hdbClass::_setId (uint32_t nId) const { // Set class UID. // // Argument: nId The supplied Dissemino field spec // // Returns: E_ARGUMENT If no field spec is supplied // E_DUPLICATE If the field spec has already been set // E_OK Operation successful
if (!nId) return E_ARGUMENT ; if (m_ClassUID) return E_DUPLICATE ;
hzChain desc ; // For formulating class description (used as delta file header)
m_ClassUID = nId ; DescClass(desc, 0) ; m_Desc = desc ;
return E_OK ; }
hzEcode hdbClass::InitStart (const hzString& className) { // Init Start function. This must be called only on a hdbClass instance that is not initialized and which is not in the process of being // initialized. // // Arguments: 1) className The data class name // // Returns: E_ARGUMENT No row class object named // E_INITFAIL Function called out of sequence: Must be first called and not repeated. // E_MEMORY Insufficient memory // E_OK Operation successful.
_hzfunc("hdbClass::InitStart") ;
// No Application Delta Profile? if (!m_pADP) return hzerr(E_NOINIT, "No Host ADP Found") ;
// No class name supplied? if (!className) return hzerr(E_ARGUMENT, "No name supplied") ;
// Data class already exists? if (m_pADP->GetPureClass(className)) return hzerr(E_DUPLICATE, "hdbClass %s already exists", *className) ;
// Data class init already in progress? if (m_eClassInit != HDB_CLASS_INIT_NONE) return hzerr(E_INITFAIL, "Function called out of sequence: Must be first called and not repeated") ;
m_Typename = className ; m_eClassInit = HDB_CLASS_INIT_PROG ;
return E_OK ; }
hzEcode hdbClass::InitMember (const hzString& mbrName, const hdbDatatype* pType, hdbPopCtl popCtl) { // Adds a member to the data class // // Arguments: 1) mbrName Member name // 2) type The external data type // 3) popCtl Population restraints // // Returns: E_ARGUMENT If no member name is supplied // E_DUPLICATE If a member of the supplied name already exists // E_NOINIT If the InitStart() function has not yet been called // E_SEQUENCE If the InitDone() function has been called // E_OK If the member is successfully added // // Note: This function will terminate execution if the member could not be allocated.
_hzfunc("hdbClass::InitMember(1)") ;
const hdbClass* pSub ; // Sub-class if applicable hdbMember* pMbr ; // The column
hzString S ; // Temp string hzEcode rc ; // Return code
//if (m_eClassInit < 1 || m_eClassInit > 2) if (m_eClassInit != HDB_CLASS_INIT_PROG) return hzerr(E_INITFAIL, "Init state %d Called out of sequence (must be after InitStart() and before InitDone()", m_eClassInit) ;
// No Application Delta Profile? if (!m_pADP) return hzerr(E_NOINIT, "No Host ADP Found") ;
// No member name supplied? if (!mbrName) return hzerr(E_ARGUMENT, "No member name supplied") ;
// No member data type supplied? if (!pType) return hzerr(E_ARGUMENT, "No member data type supplies for %s", *mbrName) ;
// Data class member already exists? if (GetMember(mbrName)) return hzerr(E_INITDUP, "Member (%s) already defined", *mbrName) ;
pMbr = new hdbMember() ; if (!pMbr) return hzerr(E_MEMORY, "Member allocation") ;
// Set up member rc = pMbr->Init(this, pType, mbrName, m_arrMembers.Count(), popCtl) ; if (rc != E_OK) return hzerr(rc, "Please examine arguments for column [%s]", *mbrName) ;
m_mapMembers.Insert(mbrName, pMbr) ;
// Assign member ID m_pADP->RegisterMember(pMbr) ;
// Put the member in the map and of columns m_mapMembers.Insert(mbrName, pMbr) ; m_arrMembers.Add(pMbr) ;
threadLog("Added member %s (of %d) to class %s\n", *mbrName, MbrCount(), txtType()) ;
// If member is a sub-class then put this in the m_mapSubs and all its subs if (pMbr->IsClass()) { pSub = (const hdbClass*) pMbr->Datatype() ; m_pADP->NoteSub(strType(), pSub) ; }
if (pMbr->Basetype() == BASETYPE_BINARY || pMbr->Basetype() == BASETYPE_TXTDOC) m_nBinaries++ ; if (pMbr->Multiple()) m_nArrays++ ;
m_eClassInit = HDB_CLASS_INIT_PROG ; return E_OK ; }
hzEcode hdbClass::InitMember (const hzString& mbrName, const hzString& typeName, hdbPopCtl popCtl) { _hzfunc("hdbClass::InitMember(2)") ;
const hdbDatatype* pDT ; // Data type
if (m_eClassInit != HDB_CLASS_INIT_PROG) return hzerr(E_INITFAIL, "Init state %d Called out of sequence (must be after InitStart() and before InitDone()", m_eClassInit) ; if (!m_pADP) return hzerr(E_NOINIT, "No Host ADP Found") ;
pDT = m_pADP->GetDatatype(typeName) ;
if (!pDT) return hzerr(E_NOTFOUND, "No such data type as %s", *typeName) ;
return InitMember(mbrName, pDT, popCtl) ; }
hzEcode hdbClass::InitDone (void) { // Complete the initialization sequence. // // This is a mainly a matter of calculating how member space within hdbObject will be arranged. Members are assigned space that depends on the datatype and max population, and // they are given relative positions that ensure the correct byte alignment. To this end the members are first sorted by datum size ... // // Arguments: None // // Returns: E_SEQUENCE If this function is not called after a successful InitStart() and InitMember() // E_OK If this function terminates an open initialization sequence
_hzfunc("hdbClass::InitDone") ;
const hdbMember* pMbr ; // Member pointer uint32_t mbrNo ; // Member number uint32_t nSofar ; // For adding up total core space needed by all members
// Check init sequence if (m_eClassInit != HDB_CLASS_INIT_PROG) return hzerr(E_SEQUENCE, "Called out of sequence (must be after InitStart() and at least one call to InitMember()") ;
// Allocate member space within hdbObject core. Start with 16-byte entities if any, then 8, then 4. Leave ENUM till last as a special case. nSofar = 0 ; //m_nNonBool = 0 ;
// Allocate 16-byte slots for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++) { pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_ENUM) continue ; if (pMbr->SizeCore() < 16) continue ;
pMbr->_setOset(nSofar) ; nSofar += 16 ; }
// Allocate 8-byte slots, including the aux slot for BINARY/TXTDOC members for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++) { pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_ENUM) continue ;
if (pMbr->Basetype() == BASETYPE_BINARY || pMbr->Basetype() == BASETYPE_TXTDOC) { pMbr->_setAux(nSofar) ; nSofar += 8 ; continue ; }
if (pMbr->SizeCore() != 8) continue ;
pMbr->_setOset(nSofar) ; nSofar += 8 ; }
// Allocate 4-byte slots for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++) { pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_BINARY || pMbr->Basetype() == BASETYPE_TXTDOC) { // Allocate space for binary datum id pMbr->_setOset(nSofar) ; nSofar += 4 ; continue ; }
if (pMbr->Basetype() == BASETYPE_ENUM) continue ; if (pMbr->SizeCore() != 4) continue ;
pMbr->_setOset(nSofar) ; nSofar += 4 ; }
// 2-byte allocations for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++) { pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_ENUM) continue ; if (pMbr->SizeCore() != 2) continue ;
pMbr->_setOset(nSofar) ; nSofar += 2 ; }
// Enums for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++) { pMbr = m_arrMembers[mbrNo] ; if (pMbr->Basetype() != BASETYPE_ENUM) continue ;
pMbr->_setOset(nSofar) ; nSofar += pMbr->SizeCore() ; }
// Bools for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++) { pMbr = m_arrMembers[mbrNo] ;
if (pMbr->Basetype() == BASETYPE_BOOL) continue ;
if (pMbr->Basetype() == BASETYPE_TBOOL) { //pMbr->_setOset(nSofar) ; //nSofar += 1 ; m_nLitmusBits++ ; continue ; }
//m_nNonBool++ ; }
// Core len is total core size m_nLitmusBits += m_arrMembers.Count() ; m_nLitmusSize = m_nLitmusBits/8 ; if (m_nLitmusBits%8) m_nLitmusSize++ ; m_nCoreLen = nSofar ;
// Report class form for (mbrNo = 0 ; mbrNo < m_arrMembers.Count() ; mbrNo++) { pMbr = m_arrMembers[mbrNo] ; threadLog("Mbr %u %s: Posn %u Datum %u Core %u oset %d aux %d\n", mbrNo, pMbr->txtName(), pMbr->Posn(), pMbr->SizeDatum(), pMbr->SizeCore(), pMbr->OsetStd(), pMbr->OsetAux()) ; } threadLog("Class %s complete, core len %u\n", txtName(), m_nCoreLen) ;
// Move to Register Class // hzChain desc ; // DescClass(desc, 0) ; // m_Desc = desc ;
// Indicate that class init is complete m_eClassInit = HDB_CLASS_INIT_DONE ; return E_OK ; }
bool hdbClass::operator== (const hdbClass& op) const { // Test for equality between hdbClass instances (this row has same columns and column settings as the operand) // // Arguments: 1) op The operand data class
_hzfunc("hdbClass::operator==") ;
const hdbMember* pMA ; // Member pointer for this class const hdbMember* pMB ; // Member pointer for other class uint32_t nIndex ; // Member iterator
if (MbrCount() != op.MbrCount()) return false ;
for (nIndex = 0 ; nIndex < m_arrMembers.Count() ; nIndex++) { pMA = m_arrMembers[nIndex] ; pMB = op.m_arrMembers[nIndex] ;
if (pMA != pMB) return false ; }
return true ; }
/* ** SECTION 5: Application Delta Profile */
void hdbClass::DescClass (hzChain& Z, uint32_t nIndent) const { // Export Class Description // // Export XML fragment describing the data class to the supplied chain. Note that as the class description is expected to be part of an ADP, the supplied chain is not cleared // by this function. // // Arguments: 1) Z The chain to aggregate the class description to // 2) nIndent The number of leading tabs to apply to each line // // Returns: None
_hzfunc("hdbClass::DescClass") ;
const hdbDatatype* pType ; // Member data type const hdbClass* pSubClass ; // Sub-class where member is BASETYPE_CLASS const hdbMember* pMbr ; // Member pointer
uint32_t mbrNo ; // Member iterator uint32_t n ; // Indent counter
for (n = nIndent ; n > 0 ; n--) Z.AddByte(CHAR_TAB) ;
switch (m_eDesignation) { case HDB_CLASS_DESIG_SYS: Z.Printf("<class id=\"%d\" desig=\"sys\" name=\"%s\">\n", m_ClassUID, txtType()) ; break ; case HDB_CLASS_DESIG_USR: Z.Printf("<class id=\"%d\" desig=\"usr\" name=\"%s\">\n", m_ClassUID, txtType()) ; break ; case HDB_CLASS_DESIG_CFG: Z.Printf("<class id=\"%d\" desig=\"cfg\" name=\"%s\">\n", m_ClassUID, txtType()) ; break ; }
for (mbrNo = 0 ; mbrNo < MbrCount() ; mbrNo++) { pMbr = GetMember(mbrNo) ;
for (n = nIndent ; n > 0 ; n--) Z.AddByte(CHAR_TAB) ;
pType = pMbr->Datatype() ;
if (!pType) { Z.Printf("\t<member posn=\"%d\" uid=\"%d\" popCtl=\"%s\" datatype=\"INVALID_DATA_TYPE\" name=\"%s\"/>\n", pMbr->Posn(), pMbr->DeltaId(), PopCtl2Txt(pMbr->PopCtl()), pMbr->txtName()) ; continue ; }
if (!pMbr->IsClass()) { Z.Printf("\t<member posn=\"%d\" uid=\"%d\" popCtl=\"%s\" datatype=\"%s\" name=\"%s\"/>\n", pMbr->Posn(), pMbr->DeltaId(), PopCtl2Txt(pMbr->PopCtl()), pType->txtType(), pMbr->txtName()) ; continue ; }
if (pMbr->Basetype() == BASETYPE_CLASS) { Z.Printf("\t<member posn=\"%d\" uid=\"%d\" popCtl=\"%s\" subclass=\"%s\" name=\"%s\">\n", pMbr->Posn(), pMbr->DeltaId(), PopCtl2Txt(pMbr->PopCtl()), pType->txtType(), pMbr->txtName()) ;
pSubClass = (hdbClass*) pMbr->Datatype() ; pSubClass->DescClass(Z, nIndent + 1) ;
for (n = nIndent ; n > 0 ; n--) Z.AddByte(CHAR_TAB) ; Z << "\t</member>\n" ; continue ; } }
for (n = nIndent ; n > 0 ; n--) Z.AddByte(CHAR_TAB) ; Z << "</class>\n" ; }
hzEcode hdbClass::DescCheck (hzChain& report, hzChain& desc) const { // Check Class Description // // With the class initialized, it is possible to check that a class description in a delta or other repository file, matches the class. The description is // supplied as a hzChain which is obtained by reading the file or file header. This function loads the hzChain into an XML document and then extracts tags // describing the class and its members. // // Write out XML fragment describing the data class to the supplied chain. Note that as the class description is likely to be part of an Application Delta // Profile, the supplied chain is not pre-cleared by this function. // // Arguments: 1) report To report errors // 2) desc The supplied description // // Returns: E_FORMAT If there are ANY descrepancies (details in report) // E_OK If the description matches the class // // Read a <class> tag on behalf of the hdbADProfile::Import function.
_hzfunc("hdbClass::DescCheck") ;
const hdbDatatype* pType ; // Data type
hzDocXml doc ; // XML document hzXmlNode* pRoot ; // XML root node hzXmlNode* pN2 ; // Second level node hzAttrset ai ; // Attribute iterator hzString cname ; // Class name hzString str_id ; // Member id hzString str_uid ; // Member uid hzString str_min ; // Member minPop hzString str_max ; // Member minPop hzString str_typ ; // Member data type hzString str_sub ; // Member sub class hzString str_nam ; // Member name hzEcode rc = E_OK ; // Return code int16_t n ; // Integer test value
// Load description into XML doc rc = doc.Load(desc) ; if (rc != E_OK) { report << "Could not load XML document with supplied description\n" ; return E_SYNTAX ; }
pRoot = doc.GetRoot() ; if (!pRoot) { report << "No XML root found in supplied description\n" ; return E_SYNTAX ; }
if (!pRoot->NameEQ("class")) { report << "Expected first tag of <class>\n" ; return E_SYNTAX ; }
// Obtain <class> attributes str_id = cname = (char*) 0 ;
for (ai = pRoot ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("id")) str_id = ai.Value() ; else if (ai.NameEQ("name")) cname = ai.Value() ; else { rc = E_SYNTAX ; report.Printf("Line %d: <class> bad param %s=%s\n", pRoot->Line(), ai.Name(), ai.Value()) ; break ; } }
// Check class name and id if (!cname) report << "No class name supplied\n" ; else { if (cname != m_Typename) report.Printf("Name mismatch. Class actual name is %s. Description names class as %s.\n", *m_Typename, *cname) ; }
if (!str_id) report << "No class id supplied\n" ; else { if (!IsInteger(n, *str_id)) report.Printf("Illegal Class ID: Must be integer. (%s)\n", *str_id) ; if (n != m_ClassUID) report.Printf("Class Delta ID mismatch. Class actual %d: Description id is %s\n", m_ClassUID, *str_id) ; }
// Read in members for (pN2 = pRoot->GetFirstChild() ; pN2 ; pN2 = pN2->Sibling()) { if (!pN2->NameEQ("member")) { report.Printf("<class> only <member> allowed. %s unexpected\n", pN2->txtName()) ; continue ; }
str_id = str_uid = str_min = str_max = str_typ = str_sub = str_nam = (char*) 0 ;
// Read in member parameters for (ai = pN2 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("posn")) str_id = ai.Value() ; else if (ai.NameEQ("uid")) str_uid = ai.Value() ; else if (ai.NameEQ("min")) str_min = ai.Value() ; else if (ai.NameEQ("max")) str_max = ai.Value() ; else if (ai.NameEQ("datatype")) str_typ = ai.Value() ; else if (ai.NameEQ("subclass")) str_sub = ai.Value() ; else if (ai.NameEQ("name")) str_nam = ai.Value() ; else report.Printf("Line %d: <member> bad param %s=%s\n", pN2->Line(), ai.Name(), ai.Value()) ; }
if (!str_id) report.Printf("No member position suplied (line %d)\n", pN2->Line()) ; if (!str_uid) report.Printf("No member UID suplied (line %d)\n", pN2->Line()) ; if (!str_min) report.Printf("No member min pop suplied (line %d)\n", pN2->Line()) ; if (!str_max) report.Printf("No member max pop suplied (line %d)\n", pN2->Line()) ; if (!str_nam) report.Printf("No member name suplied (line %d)\n", pN2->Line()) ;
if (!IsInteger(n, *str_id)) report.Printf("Illegal member position: Must be integer 0+ (line %d)\n", pN2->Line()) ; if (!IsInteger(n, *str_uid)) report.Printf("Illegal member ID: Must be integer 0+ (line %d)\n", pN2->Line()) ; if (!IsInteger(n, *str_min)) report.Printf("Illegal member min-POP: Must be integer 0+ (line %d)\n", pN2->Line()) ; if (!IsInteger(n, *str_max)) report.Printf("Illegal member max-POP: Must be integer 0+ (line %d)\n", pN2->Line()) ;
if (!str_typ) str_typ = str_sub ;
pType = m_pADP->GetDatatype(str_typ) ; if (!pType) report.Printf("<member> No such data type or sub-class as %s\n", pN2->Line(), *str_typ) ; }
if (report.Size()) return E_FORMAT ; return E_OK ; }
void hdbObjRepos::DescRepos (hzChain& Z, uint32_t nIndent) const { // Export Repository Description // // Write out XML fragment describing the data repository to the supplied chain. Note that as the class description is likely to be part of an Application // Delta Profile, the supplied chain is not pre-cleared by this function. // // Arguments: 1) Z The chain to aggregate the class description to // 2) nIndent The number of leading tabs to apply to each line // // Returns: None
_hzfunc("hdbObjRepos::DescRepos") ; }
hzEcode hdbADP::Export (void) { // Export the Application Delta Profile (ADP) // // The current ADP for any application using the HadronZoo Database Suite (HDB), will be in a file 'appname.adp' in the /etc/hzDelta.d directory.
_hzfunc("hdbADP::Export") ;
hzMapS <uint32_t,const hdbClass*> classesById ; // For ordering classes by ID
ofstream os ; // Output stream ifstream is ; // Input stream for previous ADP if applicable hzChain Z ; // For building the ADP hzChain Y ; // Previous ADP const hdbEnum* pEnum ; // Data enum const hdbClass* pClass ; // Data class hzString fname ; // Filename hzString bkfile ; // Filename uint32_t nC ; // Data class iterator hzEcode rc = E_OK ; // Return code
fname = "/etc/hzDelta.d/" + m_appName + ".adp" ; bkfile = "/etc/hzDelta.d/" + m_appName + ".bak" ;
threadLog("Exporting ADP to %s\n", *fname) ;
if (TestFile(*fname) == E_OK) { is.open(*fname) ; Y << is ; is.close() ; }
Z.Printf("<AppDeltaProfile app=\"%s\">\n", *m_appName) ;
for (nC = 0 ; nC < m_mapEnums.Count() ; nC++) { pEnum = m_mapEnums.GetObj(nC) ;
Z.Printf("\t<enum name=\"%s\"/>\n", pEnum->txtType()) ; }
for (nC = 0 ; nC < m_mapClasses.Count() ; nC++) { pClass = m_mapClasses.GetObj(nC) ;
classesById.Insert(pClass->ClassId(), pClass) ; }
for (nC = 0 ; nC < classesById.Count() ; nC++) { pClass = classesById.GetObj(nC) ;
pClass->DescClass(Z, 1) ; }
Z << "</AppDeltaProfile>\n" ;
if (Y.Size()) { if (Y == Z) { threadLog("ADP is an exact match\n") ; return E_OK ; } threadLog("Backing up ADP\n") ; Filecopy(*bkfile, *fname) ; }
threadLog("Exporting current ADP\n") ; os.open(*fname) ; os << Z ; os.close() ;
return rc ; }
hzEcode hdbADP::_rdClass (hzXmlNode* pN) { // Read a <class> tag on behalf of the hdbADProfile::Import function.
_hzfunc("hdbADProfile::_readClass") ;
const hdbDatatype* pType ; // Data type
hdbClass* pClass ; // Data class hzXmlNode* pN2 ; // Second level node hzAttrset ai ; // Attribute iterator hzString cname ; // Class name hzString desig ; // Class designation hzString str_id ; // Member id hzString str_uid ; // Member uid hzString str_pop ; // Member population control as string hzString str_typ ; // Member data type hzString str_sub ; // Member sub class hzString str_nam ; // Member name hdbPopCtl popCtl ; // Member population control as enum hzEcode rc = E_OK ; // Return code
if (!pN->NameEQ("class")) return E_SYNTAX ;
str_id = cname = (char*) 0 ;
for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("id")) str_id = ai.Value() ; else if (ai.NameEQ("desig")) desig = ai.Value() ; else if (ai.NameEQ("name")) cname = ai.Value() ; else { rc = E_SYNTAX ; threadLog("Line %d: <class> bad param %s=%s\n", pN->Line(), ai.Name(), ai.Value()) ; break ; } }
if (!cname) return hzerr(E_ARGUMENT, "No class name supplied") ; if (!desig) return hzerr(E_ARGUMENT, "No class designation supplied") ;
if (desig == "sys") pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; else if (desig == "usr") pClass = new hdbClass(*this, HDB_CLASS_DESIG_USR) ; else if (desig == "cfg") pClass = new hdbClass(*this, HDB_CLASS_DESIG_CFG) ; else return hzerr(E_ARGUMENT, "Invalid class designation supplied (%s). Must be sys|usr|cfg") ;
pClass->InitStart(cname) ;
threadLog("Reading class %s\n", *cname) ; m_mapDatatypes.Insert(cname, pClass) ; m_mapClasses.Insert(cname, pClass) ;
// Read in member parameters for (pN2 = pN->GetFirstChild() ; pN2 ; pN2 = pN2->Sibling()) { if (!pN2->NameEQ("member")) { rc = E_SYNTAX ; threadLog("Line %d: <class> only <member> allowed. %s unexpected\n", pN2->Line(), pN2->txtName()) ; break ; }
str_id = str_uid = str_pop = str_typ = str_sub = str_nam = (char*) 0 ;
for (ai = pN2 ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("posn")) str_id = ai.Value() ; else if (ai.NameEQ("uid")) str_uid = ai.Value() ; else if (ai.NameEQ("pop")) str_pop = ai.Value() ; else if (ai.NameEQ("datatype")) str_typ = ai.Value() ; else if (ai.NameEQ("subclass")) str_sub = ai.Value() ; else if (ai.NameEQ("name")) str_nam = ai.Value() ; else { rc = E_SYNTAX ; threadLog("Line %d: <member> bad param %s=%s\n", pN2->Line(), ai.Name(), ai.Value()) ; break ; } }
if (!str_typ) str_typ = str_sub ;
pType = m_mapDatatypes[str_typ] ; if (!pType) { rc = E_NOTFOUND ; threadLog("Line %d: <member> No such data type as %s\n", pN2->Line(), *str_typ) ; break ; }
if (str_pop == "SingleOptional") popCtl = HDB_MBR_POP_SINGLE_OPTIONAL ; else if (str_pop == "SingleCompulsory") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ; else if (str_pop == "ArrayOptional") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ; else if (str_pop == "ArrayCompulsory") popCtl = HDB_MBR_POP_SINGLE_COMPULSORY ; else { rc = E_SYNTAX ; threadLog("Line %d: Population control must be either SingleOptional, SingleCompulsory, ArrayOptional or ArrayCompulsory. %s not accepted\n", *str_pop) ; }
pClass->InitMember(str_nam, pType, popCtl) ; }
pClass->InitDone() ;
return rc ; }
hzEcode hdbADP::Import (const hzString& appName) { // Import the Application Delta Profile (ADP), of the named application. // // The current ADP for any application using the HadronZoo Database Suite (HDB), will be in a file 'appname.adp' in the /etc/hzDelta.d directory.
_hzfunc("hdbADP::Import") ;
hzArray <hzString> ar ; // Enum values
ifstream is ; // Input stream for previous ADP if applicable hzDocXml docADP ; // XML document hzChain Z ; // For building the ADP hzChain Y ; // Previous ADP hzXmlNode* pRoot ; // Document root node hzXmlNode* pN ; // First level node hzAttrset ai ; // Attribute iterator hdbEnum* pEnum ; // Data enum hzString fname ; // Filename hzString bkfile ; // Filename hzString cname ; // Class name hzString str_id ; // Member id hzString str_uid ; // Member uid hzString str_min ; // Member minPop hzString str_max ; // Member minPop hzString str_typ ; // Member data type hzString str_sub ; // Member sub class hzString str_nam ; // Member name hzString S ; // Temp string (enum values) uint32_t n ; // Enum value iterator hzEcode rc = E_OK ; // Return code
fname = "/etc/hzDelta.d/" + appName + ".adp" ;
if (TestFile(*fname) == E_OK) { is.open(*fname) ; Y << is ; is.close() ; }
rc = docADP.Load(*fname) ; if (rc != E_OK) { threadLog("Could not load ADP document (%s)\n", *fname) ; threadLog(docADP.Error()) ; return rc ; }
pRoot = docADP.GetRoot() ; if (!pRoot) { threadLog("ADP document (%s) has no route\n", *fname) ; return E_NOINIT ; }
for (pN = pRoot->GetFirstChild() ; pN ; pN = pN->Sibling()) { if (pN->NameEQ("enum")) { for (ai = pN ; ai.Valid() ; ai.Advance()) { if (ai.NameEQ("name")) str_nam = ai.Value() ; else { rc = E_SYNTAX ; threadLog("Line %d: <enum> bad param %s=%s\n", pN->Line(), ai.Name(), ai.Value()) ; break ; } }
pEnum = new hdbEnum() ; pEnum->SetTypename(str_nam) ;
// Add to data types m_mapDatatypes.Insert(str_nam, pEnum) ; m_mapEnums.Insert(str_nam, pEnum) ;
SplitCSV(ar, pN->m_fixContent) ;
for (n = 0 ; n < ar.Count() ; n++) { S = ar[n] ;
// if (S.Length() > pEnum->m_nMax) // pEnum->m_nMax = S.Length() ;
//pEnum->m_Numbers.Add(strNo) ; pEnum->AddItem(S) ; } } else if (pN->NameEQ("class")) { rc = _rdClass(pN) ; if (rc != E_OK) break ; } }
return rc ; }
hzEcode hdbADP::InitStandard (const hzString& appName) { // Add the fundamental C++ and the HadronZoo in-built data types to the global map of datatypes _hzGlobal_Datatypes. // // Arguments: None // // Returns: E_SEQUENCE If this function has already been called // E_OK Otherwise.
_hzfunc("hdbADP::InitStandard") ;
hdbCpptype* ct ; // Pointer to Cpp data type hdbHzotype* ht ; // Pointer to Cpp data type
if (!this) Fatal("No ADP Instance") ; if (m_appName) Fatal("This function has already been called setting app name to ") ; if (!appName) return hzerr(E_ARGUMENT, "No application name supplied") ; m_appName = appName ;
// Group 1: C++ Fundamental types datatype_DIGEST = ct = new hdbCpptype() ; ct->SetTypename("hashMD5"); ct->SetBasetype(BASETYPE_DIGEST); m_mapDatatypes.Insert(ct->strType(), ct); datatype_DOUBLE = ct = new hdbCpptype() ; ct->SetTypename("double"); ct->SetBasetype(BASETYPE_DOUBLE); m_mapDatatypes.Insert(ct->strType(), ct); datatype_INT64 = ct = new hdbCpptype() ; ct->SetTypename("int64"); ct->SetBasetype(BASETYPE_INT64); m_mapDatatypes.Insert(ct->strType(), ct); datatype_INT32 = ct = new hdbCpptype() ; ct->SetTypename("int32"); ct->SetBasetype(BASETYPE_INT32); m_mapDatatypes.Insert(ct->strType(), ct); datatype_INT16 = ct = new hdbCpptype() ; ct->SetTypename("int16"); ct->SetBasetype(BASETYPE_INT16); m_mapDatatypes.Insert(ct->strType(), ct); datatype_BYTE = ct = new hdbCpptype() ; ct->SetTypename("byte"); ct->SetBasetype(BASETYPE_BYTE); m_mapDatatypes.Insert(ct->strType(), ct); datatype_UINT64 = ct = new hdbCpptype() ; ct->SetTypename("uint64"); ct->SetBasetype(BASETYPE_UINT64); m_mapDatatypes.Insert(ct->strType(), ct); datatype_UINT32 = ct = new hdbCpptype() ; ct->SetTypename("uint32"); ct->SetBasetype(BASETYPE_UINT32); m_mapDatatypes.Insert(ct->strType(), ct); datatype_UINT16 = ct = new hdbCpptype() ; ct->SetTypename("uint16"); ct->SetBasetype(BASETYPE_UINT16); m_mapDatatypes.Insert(ct->strType(), ct); datatype_UBYTE = ct = new hdbCpptype() ; ct->SetTypename("ubyte"); ct->SetBasetype(BASETYPE_UBYTE); m_mapDatatypes.Insert(ct->strType(), ct); datatype_BOOL = ct = new hdbCpptype() ; ct->SetTypename("bool"); ct->SetBasetype(BASETYPE_BOOL); m_mapDatatypes.Insert(ct->strType(), ct);
// Group 2: HadronZoo in-built datatype_DOMAIN = ht = new hdbHzotype() ; ht->SetTypename("domain"); ht->SetBasetype(BASETYPE_DOMAIN); m_mapDatatypes.Insert(ht->strType(), ht); datatype_EMADDR = ht = new hdbHzotype() ; ht->SetTypename("emaddr"); ht->SetBasetype(BASETYPE_EMADDR); m_mapDatatypes.Insert(ht->strType(), ht); datatype_URL = ht = new hdbHzotype() ; ht->SetTypename("url"); ht->SetBasetype(BASETYPE_URL); m_mapDatatypes.Insert(ht->strType(), ht); datatype_IPADDR = ht = new hdbHzotype() ; ht->SetTypename("ipaddr"); ht->SetBasetype(BASETYPE_IPADDR); m_mapDatatypes.Insert(ht->strType(), ht); datatype_TIME = ht = new hdbHzotype() ; ht->SetTypename("time"); ht->SetBasetype(BASETYPE_TIME); m_mapDatatypes.Insert(ht->strType(), ht); datatype_SDATE = ht = new hdbHzotype() ; ht->SetTypename("sdate"); ht->SetBasetype(BASETYPE_SDATE); m_mapDatatypes.Insert(ht->strType(), ht); datatype_XDATE = ht = new hdbHzotype() ; ht->SetTypename("xdate"); ht->SetBasetype(BASETYPE_XDATE); m_mapDatatypes.Insert(ht->strType(), ht); datatype_STRING = ht = new hdbHzotype() ; ht->SetTypename("string"); ht->SetBasetype(BASETYPE_STRING); m_mapDatatypes.Insert(ht->strType(), ht); datatype_TEXT = ht = new hdbHzotype() ; ht->SetTypename("text"); ht->SetBasetype(BASETYPE_TEXT); m_mapDatatypes.Insert(ht->strType(), ht); datatype_BINARY = ht = new hdbHzotype() ; ht->SetTypename("binary"); ht->SetBasetype(BASETYPE_BINARY); m_mapDatatypes.Insert(ht->strType(), ht); datatype_TXTDOC = ht = new hdbHzotype() ; ht->SetTypename("txtdoc"); ht->SetBasetype(BASETYPE_TXTDOC); m_mapDatatypes.Insert(ht->strType(), ht);
return E_OK ; }
hzEcode hdbADP::InitSubscribers (const hzString& dataDir) { // Create the subscriber data class and repository
_hzfunc("hdbADP::InitSubscribers") ;
//hdbObjRepos* pRepos ; // Subscriber repository pointer hzString S ; // Temporary string hzEcode rc = E_OK ; // Return code
if (!this) hzexit(E_CORRUPT, "No ADP instance") ;
if (m_pClassSubscriber) rc = hzerr(E_DUPLICATE, "Subscriber class already declared") ;
S = "subscriber" ; if (m_mapRepositories.Exists(S)) rc = hzerr(E_DUPLICATE, "This function has already been called") ;
if (!dataDir) rc = hzerr(E_ARGUMENT, "No application data directory") ;
if (rc != E_OK) return rc ;
// Allocate and initialize subscriber class m_pClassSubscriber = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = m_pClassSubscriber->InitStart(S) ;
if (rc == E_OK) { S = "username" ; rc = m_pClassSubscriber->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { S = "userpass" ; rc = m_pClassSubscriber->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { S = "userEmail" ; rc = m_pClassSubscriber->InitMember(S, datatype_EMADDR, HDB_MBR_POP_SINGLE_OPTIONAL) ; } if (rc == E_OK) { S = "userUID" ; rc = m_pClassSubscriber->InitMember(S, datatype_UINT32, HDB_MBR_POP_SINGLE_OPTIONAL) ; } if (rc == E_OK) { S = "userType" ; rc = m_pClassSubscriber->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_OPTIONAL) ; }
if (rc == E_OK) { rc = m_pClassSubscriber->InitDone() ;
// Obtain member pointers m_pMbr_Subscriber_username = m_pClassSubscriber->GetMember(0) ; m_pMbr_Subscriber_userpass = m_pClassSubscriber->GetMember(1) ; m_pMbr_Subscriber_email = m_pClassSubscriber->GetMember(2) ; m_pMbr_Subscriber_UID = m_pClassSubscriber->GetMember(3) ; m_pMbr_Subscriber_type = m_pClassSubscriber->GetMember(4) ; }
// Resister subscriber class if (rc == E_OK) rc = RegisterDataClass(m_pClassSubscriber) ;
if (rc != E_OK) hzexit(rc, "Could not init subsriber class") ;
// Create and initialize susscriber repository m_pReposSubscriber = new hdbObjRepos(*this) ; if (!m_pReposSubscriber) hzexit(E_MEMORY, "No subsciber cache allocated") ;
rc = m_pReposSubscriber->InitStart(m_pClassSubscriber, m_pClassSubscriber->strName(), dataDir, HDB_REPOS_CACHE) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos") ;
//S = "username" ; rc = m_pReposSubscriber->InitMbrIndex(m_pMbr_Subscriber_username, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
rc = m_pReposSubscriber->InitDone() ; if (rc != E_OK) hzexit(rc, "Could not complete subsriber repos initialization") ;
// Resister subscriber repository rc = m_mapRepositories.Insert(m_pReposSubscriber->strName(), m_pReposSubscriber) ; /* if (rc == E_OK) { m_pMbr_Subscriber_username = m_pClassSubscriber->GetMember(0) ; m_pMbr_Subscriber_userpass = m_pClassSubscriber->GetMember(1) ; m_pMbr_Subscriber_email = m_pClassSubscriber->GetMember(2) ; m_pMbr_Subscriber_UID = m_pClassSubscriber->GetMember(3) ; m_pMbr_Subscriber_type = m_pClassSubscriber->GetMember(4) ; } */
return rc ; }
hzEcode hdbADP::InitSiteIndex (const hzString& dataDir) { // The site index is an optional free text index for webapps that comes as standard. If deployed, it maps each word found within webapp page and article content, to the set of // pages and articles in which the word appears. It is implemented directly as a hdbIndexText instance, without involving a data class or a data class repository.
_hzfunc("hdbADP::InitSiteIndex") ;
hdbClass* pClass ; // Subscriber class pointer hdbObjRepos* pRepos ; // Subscriber repository pointer hzString S ; // Temporary string hzEcode rc ; // Return code
if (!this) hzexit(E_CORRUPT, "No ADP instance") ; if (m_pSiteindex) return hzerr(E_SEQUENCE, "This function has already been called") ; if (!dataDir) return hzerr(E_ARGUMENT, "No application data directory") ;
S = "siteindex" ; m_pSiteindex = new hdbIndexText() ;
// Allocate and initialize subscriber class pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = pClass->InitStart(S) ;
if (rc == E_OK) { S = "pageUrl" ; rc = pClass->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { S = "PageTitle" ; rc = pClass->InitMember(S, datatype_STRING, HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { rc = pClass->InitDone() ; }
// Resister subscriber class if (rc == E_OK) rc = RegisterDataClass(pClass) ;
if (rc != E_OK) hzexit(rc, "Could not init subsriber class") ;
// Create and initialize susscriber repository pRepos = new hdbObjRepos(*this) ; if (!pRepos) hzexit(E_MEMORY, "No subsciber cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos") ;
S = "pageUrl" ; rc = pRepos->InitMbrIndex(S, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ; if (rc != E_OK) hzexit(rc, "Could not complete subsriber repos initialization") ; threadLog("Complete subsriber repos initialization") ;
// Resister subscriber repository rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ; threadLog("Subscriber Repos Reg complete\n") ; return rc ; }
#if 0 hzEcode hdbADP::InitSearch (void) { // Create the search data class
_hzfunc("hdbADP::InitSearch") ;
static bool bBeenHere = false ; // Set once run
hdbClass* pClass ; // Subscriber class pointer hzString S ; // Temporary string hzEcode rc ; // Return code
if (bBeenHere) return hzerr(E_SEQUENCE, "This function has already been called") ; bBeenHere = true ;
// Allocate and initialize subscriber class S = "sitesrch" ; pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = pClass->InitStart(S) ;
if (rc == E_OK) { S = "criteria" ; rc = pClass->InitMember(S, datatype_STRING, 1, 1) ; } if (rc == E_OK) rc = pClass->InitDone() ;
// Resister subscriber class if (rc == E_OK) rc = RegisterDataClass(pClass) ;
if (rc != E_OK) hzexit(rc, "Could not init sitesrch class") ; return E_OK ; } #endif
hzEcode hdbADP::InitFinancials (const hzString& dataDir) { _hzfunc("hdbADP::InitFinancials") ;
hdbEnum* pEnum ; // Enum pointer hdbClass* pClass ; // Data class pointer hdbObjRepos* pRepos ; // Repository pointer hzString cname ; // Current data class name hzString mname ; // Current member name hzEcode rc ; // Return code
cname = "Currency" ; if (m_mapRepositories.Exists(cname)) return hzerr(E_SEQUENCE, "This function has already been called") ;
if (!dataDir) return hzerr(E_ARGUMENT, "No application data directory") ;
// Setup the 'Account Type' enum mname = "enumAccType" ; pEnum = new hdbEnum() ; pEnum->SetTypename(mname) ;
pEnum->AddItem("ACC_NULL", 0x0000) ; pEnum->AddItem("ACC_ASSET", 0x0001) ; pEnum->AddItem("ACC_BANK", 0x0002) ; pEnum->AddItem("ACC_CASH", 0x0004) ; pEnum->AddItem("ACC_DIRECTOR", 0x0008) ; pEnum->AddItem("ACC_FOREX", 0x0010) ; pEnum->AddItem("ACC_GOV", 0x0020) ; pEnum->AddItem("ACC_SHARE", 0x0040) ; pEnum->AddItem("ACC_STOCK", 0x0080) ; pEnum->AddItem("ACC_TRADE", 0x0100) ;
RegisterDataEnum(pEnum) ;
/* ** Currencies */
// Set up Currency data class pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Name" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Symbol" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ; if (rc == E_OK) rc = RegisterDataClass(pClass) ;
// Create and initialize Currency repository pRepos = new hdbObjRepos(*this) ; if (!pRepos) hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos") ;
mname = "Name" ; rc = pRepos->InitMbrIndex(mname, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ; if (rc != E_OK) hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ; pRepos->Open() ;
/* ** Categories */
// Set up Currency data class cname = "Category" ; pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Code" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Desc" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ; if (rc == E_OK) rc = RegisterDataClass(pClass) ;
// Create and initialize Currency repository pRepos = new hdbObjRepos(*this) ; if (!pRepos) hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos") ;
mname = "Code" ; rc = pRepos->InitMbrIndex(mname, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ; if (rc != E_OK) hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ; pRepos->Open() ;
/* ** Accounts */
// Set up Account data class cname = "Account" ; pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Opened" ; rc = pClass->InitMember(mname, "sdate", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Closed" ; rc = pClass->InitMember(mname, "sdate", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Currency" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Code" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Desc" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "InitBal" ; rc = pClass->InitMember(mname, "int32", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Type" ; rc = pClass->InitMember(mname, "enumAccType", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ; if (rc == E_OK) RegisterDataClass(pClass) ;
// Create and initialize Account repository pRepos = new hdbObjRepos(*this) ; if (!pRepos) hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos") ;
mname = "Code" ; rc = pRepos->InitMbrIndex(mname, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ; if (rc != E_OK) hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ; pRepos->Open() ;
/* ** Transactions */
// Set up Transaction data class cname = "Transaction" ; pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = pClass->InitStart(cname) ;
if (rc == E_OK) { mname = "Date" ; rc = pClass->InitMember(mname, "sdate", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Currency" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Category" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "From" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "To" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Desc" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Note" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Qty" ; rc = pClass->InitMember(mname, "string", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Value" ; rc = pClass->InitMember(mname, "int32", HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) { mname = "Type" ; rc = pClass->InitMember(mname, "int32", HDB_MBR_POP_SINGLE_COMPULSORY) ; }
rc = pClass->InitDone() ; if (rc == E_OK) RegisterDataClass(pClass) ;
// Create and initialize Transaction repository pRepos = new hdbObjRepos(*this) ; if (!pRepos) hzexit(E_MEMORY, "No Currency cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos") ;
mname = "Date" ; rc = pRepos->InitMbrIndex(mname, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
mname = "From" ; rc = pRepos->InitMbrIndex(mname, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ; if (rc != E_OK) hzexit(rc, "Could not complete subsriber repos initialization") ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ; pRepos->Open() ;
return rc ; }
hzEcode hdbADP::InitBlockedIPs (const hzString& dataDir) { // Create the Blocked-IP data class and repository
_hzfunc("hdbADP::InitBlockedIPs") ;
static bool bBeenHere = false ; // Set once run
hdbClass* pClass ; // Subscriber class pointer hdbObjRepos* pRepos ; // Subscriber repository pointer hzString S ; // Temporary string hzEcode rc ; // Return code
if (bBeenHere) return hzerr(E_SEQUENCE, "This function has already been called") ; bBeenHere = true ;
if (!dataDir) return hzerr(E_ARGUMENT, "No application data directory") ;
// Allocate and initialize subscriber class S = "blockedIP" ; pClass = new hdbClass(*this, HDB_CLASS_DESIG_SYS) ; rc = pClass->InitStart(S) ;
if (rc == E_OK) { S = "ipa" ; rc = pClass->InitMember(S, datatype_IPADDR, HDB_MBR_POP_SINGLE_COMPULSORY) ; } if (rc == E_OK) rc = pClass->InitDone() ;
// Resister subscriber class if (rc == E_OK) RegisterDataClass(pClass) ;
if (rc != E_OK) hzexit(rc, "Could not init blockedIP class") ;
// Create and initialize susscriber repository pRepos = new hdbObjRepos(*this) ; if (!pRepos) hzexit(E_MEMORY, "No blockedIP cache allocated") ;
rc = pRepos->InitStart(pClass, pClass->strType(), dataDir, HDB_REPOS_CACHE) ; if (rc != E_OK) hzexit(rc, "Could not init blockedIP repos") ;
S = "ipa" ; rc = pRepos->InitMbrIndex(S, true) ; if (rc != E_OK) hzexit(rc, "Could not init subsriber repos index") ;
rc = pRepos->InitDone() ; if (rc != E_OK) hzexit(rc, "Could not complete subsriber repos initialization") ;
// Resister subscriber repository rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ; return rc ; }
void hdbADP::Report (hzChain& Z) { // Write out ADP // // Diagnostics // // Argument: Z Output chain // // Returns: None
_hzfunc("hdbADP::Report") ;
const hdbDatatype* pDT ; // Data type const hdbClass* pClass ; // Data class const hdbMember* pMbr ; // Data class member hdbEnum* pSlct ; // Data enum
uint32_t x ; // General iterator uint32_t y ; // General iterator
Z.Printf("APPLICATION DELTA PROFILE\n") ;
// Z.Printf("User Categories\n") ; // for (x = 0 ; x < m_UserTypes.Count() ; x++) // { ut = m_UserTypes.GetObj(x) ; Z.Printf(" -- %s\n", *ut.m_Refname) ; }
Z.Printf("Data types\n") ; Z.Printf(" -- Validation formats\n") ; for (x = 0 ; x < m_mapDatatypes.Count() ; x++) { pDT = m_mapDatatypes.GetObj(x) ;
if (pDT->Basetype() != BASETYPE_APPDEF) continue ;
Z.Printf("\t -- %s\n", pDT->txtType()) ; }
Z.Printf(" -- Selectors\n") ; for (x = 0 ; x < m_mapDatatypes.Count() ; x++) { pDT = m_mapDatatypes.GetObj(x) ;
if (pDT->Basetype() != BASETYPE_ENUM) continue ;
pSlct = (hdbEnum*) pDT ; Z.Printf("\t -- %s\n", pSlct->txtType()) ; }
Z.Printf(" -- Clases\n") ; for (x = 0 ; x < m_mapClasses.Count() ; x++) { pClass = m_mapClasses.GetObj(x) ; Z.Printf("\t -- %s\n", pClass->txtType()) ;
for (y = 0 ; y < pClass->MbrCount() ; y++) { pMbr = pClass->GetMember(y) ; Z.Printf("\t\t -- %s [%s]\n", pMbr->txtName(), Basetype2Txt(pMbr->Basetype())) ; } }
Z.Printf(" -- Class Delta ID assignments\n") ; for (x = 0 ; x < m_mapClsCtxDtId.Count() ; x++) { y = m_mapClsCtxDtId.GetKey(x) ; pClass = m_mapClsCtxDtId.GetObj(x) ;
Z.Printf("\t\t -- [%d] %s\n", y, pClass->txtType()) ; } }
hzEcode hdbADP::RegisterDataClass (const hdbClass* pClass) { // Insert a new data class into the ADP. This may only be done during initialization. // // Argument: pClass The data class to be inserted
_hzfunc("hdbADP::RegisterDataClass") ;
if (!this) hzexit(E_CORRUPT, "No ADP instance") ;
// No data class? if (!pClass) return E_ARGUMENT ;
// Unnamed data class? if (!pClass->strType()) return E_NOINIT ;
// Data class already has delta id? if (pClass->ClassId()) return hzerr(E_DUPLICATE, "Data class %s already registered with id %d", pClass->txtType(), pClass->ClassId()) ;
// Data type already registered? if (m_mapDatatypes.Exists(pClass->strType())) return hzerr(E_DUPLICATE, "Data type %s already registered. Cannot admit class of this name", pClass->txtType()) ;
// Allocate the class id switch (pClass->Designation()) { case HDB_CLASS_DESIG_SYS: if (pClass->strType() == "subscriber") pClass->_setId(HZ_ADP_CLS_SUBSCRIBER) ; else if (pClass->strType() == "siteindex") pClass->_setId(HZ_ADP_CLS_SITEINDEX) ; else if (pClass->strType() == "FinCurrency") pClass->_setId(HZ_ADP_CLS_FIN_CRCY) ; else if (pClass->strType() == "FinCategory") pClass->_setId(HZ_ADP_CLS_FIN_CAT) ; else if (pClass->strType() == "FinAccount") pClass->_setId(HZ_ADP_CLS_FIN_ACC) ; else if (pClass->strType() == "FinTransaction") pClass->_setId(HZ_ADP_CLS_FIN_TRNS) ; else { hzerr(E_BADVALUE, "Unrecognized System Class (%s)", pClass->txtType()) ; return E_BADVALUE ; } break ;
case HDB_CLASS_DESIG_USR: pClass->_setId(m_nsqClsUsr++) ; break ;
case HDB_CLASS_DESIG_CFG: pClass->_setId(m_nsqClsCfg++) ; break ; }
if (!pClass->ClassId()) return hzerr(E_NOINIT, "Data class %s did not aquire a delta id", pClass->txtType()) ;
// Insert data class into ADP map of datatypes m_mapDatatypes.Insert(pClass->strType(), pClass) ; m_mapClasses.Insert(pClass->strType(), pClass) ; m_mapClsCtxName.Insert(pClass->strType(), pClass->ClassId()) ; //m_mapClasses.Count()) ; m_mapClsCtxDtId.Insert(pClass->ClassId(), pClass) ; threadLog("Inserted %s\n", *pClass->strType()) ;
return E_OK ; }
hzEcode hdbADP::RegisterComposite (hzString& context, const hdbClass* pClass) { // Insert a new data class context into the ADP. This may only be done during initialization. // // Argument: pClass The data class to be inserted
_hzfunc("hdbADP::RegisterComposite") ;
if (!context || !pClass) return E_ARGUMENT ;
m_mapClsCtxName.Insert(context, m_nsqClsCtx) ; m_mapClsCtxDtId.Insert(m_nsqClsCtx, pClass) ; m_nsqClsCtx++ ;
return E_OK ; }
hzEcode hdbADP::RegisterMember (const hdbMember* pMbr) { _hzfunc("hdbADP::RegisterMember") ;
const hdbClass* pClass ; // Data class of member uint32_t mbrId ; // Member ID to be
pClass = pMbr->Class() ; if (!pClass) hzexit(E_NOINIT, "Member not initialized to its host data class") ;
// Assign member ID switch (pClass->Designation()) { case HDB_CLASS_DESIG_SYS: mbrId = m_nsqMbrSys++ ; break ; case HDB_CLASS_DESIG_USR: mbrId = m_nsqMbrUsr++ ; break ; case HDB_CLASS_DESIG_CFG: mbrId = m_nsqMbrCfg++ ; break ; } m_mapMembers.Insert(mbrId, pMbr) ;
pMbr->_setId(mbrId) ; return E_OK ; }
hzEcode hdbADP::RegisterDataEnum (const hdbEnum* pEnum) { // Insert a new data enum into the ADP. This may only be done during initialization. //
_hzfunc("hdbADP::RegisterDataEnum") ;
if (!pEnum) return E_ARGUMENT ;
if (!pEnum->strType()) return E_NOINIT ;
m_mapDatatypes.Insert(pEnum->strType(), pEnum) ; m_mapEnums.Insert(pEnum->strType(), pEnum) ;
return E_OK ; }
hzEcode hdbADP::RegisterRegexType (const hdbRgxtype* pRgx) { _hzfunc("hdbADP::RegisterRegexType") ;
if (!pRgx) return E_ARGUMENT ; if (!pRgx->strType()) return E_NOINIT ;
return m_mapDatatypes.Insert(pRgx->strType(), pRgx) ; }
hzEcode hdbADP::RegisterObjRepos (hdbObjRepos* pRepos) { _hzfunc("hdbADP::RegisterObjRepos") ;
hzEcode rc ; // Return code
if (!pRepos) return E_ARGUMENT ; if (!pRepos->strName()) return E_NOINIT ;
if (m_mapRepositories.Exists(pRepos->strName())) return hzerr(E_DUPLICATE, "Repository [%s] already exists", pRepos->txtName()) ;
rc = m_mapRepositories.Insert(pRepos->strName(), pRepos) ; if (rc != E_OK) return hzerr(rc, "Repository [%s] Register FAIL", pRepos->txtName()) ; return rc ;
}
#if 0 hzEcode hdbADP::RegisterDataCron (hdbBinCron* pRepos) { if (!pRepos) return E_ARGUMENT ; if (!pRepos->Name()) return E_NOINIT ;
return m_mapBinDataCrons.Insert(pRepos->Name(), pRepos) ; }
hzEcode hdbADP::RegisterDataStore (hdbBinStore* pRepos) { if (!pRepos) return E_ARGUMENT ; if (!pRepos->m_Name) return E_NOINIT ;
return m_mapBinDataStores.Insert(pRepos->m_Name, pRepos) ; } #endif
hzEcode hdbADP::RegisterBinRepos (hdbBinRepos* pRepos) { _hzfunc("hdbADP::RegisterBinRepos") ;
if (!pRepos) return E_ARGUMENT ; if (!pRepos->txtName()) return E_NOINIT ;
return m_mapBinRepos.Insert(pRepos->strName(), pRepos) ; }
bool hdbADP::IsSubClass (const hdbClass* pMain, const hdbClass* pSub) { // Determine if the second data class is a sub-class of the first // // Arguments: 1) pMain The main class // 2) pSub The test class // // Returns: True If the test class is a sub-class of the main class // False Otherwise
_hzfunc("hdbADP::IsSubClass") ;
uint32_t val_Lo ; // First item uint32_t val_Hi ; // Last item
val_Lo = m_mapSubs.First(pMain->strType()) ; if (val_Lo >= 0) { val_Hi = m_mapSubs.Last(pMain->strType()) ;
for (; val_Lo <= val_Hi ; val_Lo++) { if (pSub == m_mapSubs.GetObj(val_Lo)) return true ; } }
return false ; }