diff options
Diffstat (limited to 'reladminif')
49 files changed, 13195 insertions, 0 deletions
diff --git a/reladminif/Makefile.am b/reladminif/Makefile.am new file mode 100644 index 0000000..07a6e99 --- /dev/null +++ b/reladminif/Makefile.am @@ -0,0 +1,68 @@ +# -*-Makefile-*- (for Emacs) +# +# This file is part of rasdaman community. +# +# Rasdaman community is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Rasdaman community 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +# +# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +# rasdaman GmbH. +# +# For more information please see <http://www.rasdaman.org> +# or contact Peter Baumann via <baumann@rasdaman.com>. +# +# MAKEFILE FOR: +# reladminif +# +# +# COMMENTS: +# - stagerif not used +# +################################################################## + +AM_CXXFLAGS=@BASEDBCXXFLAGS@ +AM_LDFLAGS=@BASEDBLDFLAGS@ + +.SUFFIXES= .@EMBEDDEDSQLEXT@ .@EMBEDDEDSQLOUT@ +.@EMBEDDEDSQLEXT@.@EMBEDDEDSQLOUT@: + $(EMBEDDEDSQLPRECOMPILER) $@ $< + + +noinst_LIBRARIES=libreladminif.a +libreladminif_a_SOURCES=adminifcommon.cc adminif.hh databaseifcommon.cc databaseif.hh \ + transactionifcommon.cc transactionif.hh sqlerror.hh \ + oidifcommon.cc oidif.hh dbobject.cc dbobject.hh \ + dbnamedobject.cc dbnamedobject.hh eoid.cc eoid.hh \ + dbref.cc dbref.hh objectbrokercommon.cc objectbroker.hh \ + dbobjectiterator.cc dbobjectiterator.hh \ + externs.h lists.h binaryrepresentation.hh destroyable.hh \ + sqlglobals.h dbobjectiditerator.hh +EXTRA_libreladminif_a_SOURCES=adminif.pgc databaseif.pgc transactionif.pgc \ + sqlerror.pgc oidif.pgc objectbroker.pgc \ + dbobjectiditerator.cc + +libreladminif_a_LIBADD= adminif.$(OBJEXT) databaseif.$(OBJEXT) transactionif.$(OBJEXT) \ + sqlerror.$(OBJEXT) oidif.$(OBJEXT) objectbroker.$(OBJEXT) +libreladminif_a_DEPENDENCIES= adminif.$(OBJEXT) databaseif.$(OBJEXT) transactionif.$(OBJEXT) \ + sqlerror.$(OBJEXT) oidif.$(OBJEXT) objectbroker.$(OBJEXT) + + +BUILT_SOURCES= adminif.@EMBEDDEDSQLOUT@ databaseif.@EMBEDDEDSQLOUT@ transactionif.@EMBEDDEDSQLOUT@ \ + sqlerror.@EMBEDDEDSQLOUT@ oidif.@EMBEDDEDSQLOUT@ objectbroker.@EMBEDDEDSQLOUT@ + + +CLEANFILES= adminif.@EMBEDDEDSQLOUT@ databaseif.@EMBEDDEDSQLOUT@ transactionif.@EMBEDDEDSQLOUT@ \ + sqlerror.@EMBEDDEDSQLOUT@ oidif.@EMBEDDEDSQLOUT@ objectbroker.@EMBEDDEDSQLOUT@ \ + client.bm client.dbg client.log ir.out + + diff --git a/reladminif/adminif.hh b/reladminif/adminif.hh new file mode 100644 index 0000000..6d4024b --- /dev/null +++ b/reladminif/adminif.hh @@ -0,0 +1,174 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _ADMINIF_HH_ +#define _ADMINIF_HH_ + +/************************************************************************ + * += * + * PURPOSE: + * + * + * COMMENTS: + * + ***********************************************************************/ + +class AdminIf; +class DatabaseIf; + +class r_Error; + +#include <iostream> +#include "lists.h" + +class AdminIf; + +//@ManMemo: Module: {\bf reladminif}. + +/*@Doc: +An AdminIf instance has to be obtained, before any work with the base +DBMS can be done. Only one instance can exist at any time. The class +follows the singleton design pattern (Gamma et. al. p. 127ff.). + +{\bf Functionality} + +At the moment, AdminIf is responsible for the state of a transaction. +persistent objects rely on this class to decide if they should write +changes back into the db. It also carries a list of compressed tiles. +Before a session is opened, no persistence capable classes can be used (e.g. +\Ref{BLOBTile})! Remember to also create a \Ref{DatabaseIf} instance +before using a persistence capable class. + +{\bf Example} + +{\tt AdminIf* myAdmin = AdminIf::instance();} + +... + +{\tt delete myAdmin;} + +*/ + +const int SYSTEMNAME_MAXLEN=256; + +class AdminIf + { + public: + static AdminIf* instance(); + /*@Doc: + satic function used to access instance of AdminIf and start session. + */ + + static DatabaseIf* getCurrentDatabaseIf(); + /*@Doc: + static function used to access the current databaseif object + */ + + static void setCurrentDatabaseIf(DatabaseIf* db); + /*@Doc: + static function used to store the current databaseif object in AdminIf + this function should only be called by DatabaseIf, DatabasIf + is responsible for setting the databaseif object to + NULL at destruction time. + */ + + ~AdminIf(); + /*@Doc: + issues a ROLLBACK WORK RELEASE + deinitializes the ObjectBroker + deinitializes benchmark timers + */ + + static char* getSystemName(); + /*@Doc: + returns Oracle on oracle + */ + + static void setReadOnlyTA(bool newReadOnlyTA); + /*@Doc: + sets readOnlyTA, should only be used by \Ref{TransactionIf} + */ + + static bool isReadOnlyTA(); + /*@Doc: + checks for read only TA. + */ + + static bool isAborted(); + /*@Doc: + used by DBObject::validate() to determine if it should execute the persistency functions + */ + + static void setAborted(bool newAborted); + /*@Doc: + used by transactionif to set the aborted status of the transaction + */ + + protected: + AdminIf() throw (r_Error); + /*@Doc: + constructor, can not be used from outside. + initializes the objectbroker + does a CONNECT, when successful sets validConnection to true else false, + then a ROLLBACK WORK RELEASE + throws exception if connection fails + */ + + private: + static AdminIf* myInstance; + /*@Doc: + pointer to instance (just needed for Singleton pattern). + */ + + static DatabaseIf* myDatabaseIf; + /*@Doc: + pointer to the current DatabaseIf object + */ + + static bool validConnection; + /*@Doc: + flag for error when opening session: false if error. + */ + + static bool readOnlyTA; + /*@Doc: + flag for read only transactions + */ + + static const char dbmsName[SYSTEMNAME_MAXLEN]; + /*@Doc: + holds the specific name of dbms + */ + + static char systemName[SYSTEMNAME_MAXLEN]; + /*@Doc: + Store the dbms name using dbmsName + */ + + static bool _isAborted; + /*@Doc: + flag for aborted transactions + */ + }; + +#endif diff --git a/reladminif/adminif.pgc b/reladminif/adminif.pgc new file mode 100644 index 0000000..5e1a03d --- /dev/null +++ b/reladminif/adminif.pgc @@ -0,0 +1,90 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * implements adminif interface using the PostgreSQL DBMS. + * + * + * COMMENTS: + * none + * + ***********************************************************************/ + +static const char rcsid[] = "@(#)reladminif,AdminIf: $Id: adminif.ec,v 1.6 2003/12/27 23:11:43 rasdev Exp $"; + +#include "debug-srv.hh" +#include "sqlerror.hh" + +// general embedded SQL related definitions +EXEC SQL include sqlglobals.h; + +#include "adminif.hh" +#include "raslib/rmdebug.hh" +#include "objectbroker.hh" + +extern char globalConnectId[256]; +const char AdminIf::dbmsName[SYSTEMNAME_MAXLEN]="PostgreSQL"; + +AdminIf::AdminIf() throw (r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "AdminIf()"); + ENTER( "AdminIf::AdminIf" ); + + EXEC SQL BEGIN DECLARE SECTION; + char id[STRING_MAXLEN]; + EXEC SQL END DECLARE SECTION; + + strncpy((char *)&id, globalConnectId, sizeof(id)-1); + + TALK( "EXEC SQL CONNECT TO " << id ); + EXEC SQL CONNECT TO :id; + + if (check("AdminIf Connect\0")) + { + validConnection = false; + TALK( "connect unsuccessful; wrong connect string?" ); + cout << "Error: connect unsuccessful; wrong connect string '" << globalConnectId << "' ?" << endl; + throw r_Error( 830 ); + } + else + { + validConnection = true; + TALK( "connect ok" ); + } + + TALK( "EXEC SQL ROLLBACK WORK" ); + EXEC SQL ROLLBACK WORK; + +#ifndef FASTCONNECT + TALK( "EXEC SQL DISCONNECT CURRENT" ); + EXEC SQL DISCONNECT CURRENT; +#endif + + ObjectBroker::init(); + + LEAVE( "AdminIf::AdminIf, SQLCODE=" << SQLCODE ); + RMDBGEXIT(4, RMDebug::module_adminif, "Adminif", "AdminIf() " << validConnection); +} + diff --git a/reladminif/adminifcommon.cc b/reladminif/adminifcommon.cc new file mode 100644 index 0000000..f4409e3 --- /dev/null +++ b/reladminif/adminifcommon.cc @@ -0,0 +1,163 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * Code with embedded SQL for relational DBMS + * + * + * COMMENTS: + * none + * + ***********************************************************************/ + +#include <string.h> +#if defined(DECALPHA) || defined(LINUX) || defined(AIX) || defined(SOLARIS) +//#include <algorith.h> +//#elif defined(LINUX) || defined(AIX) || defined(SOLARIS) +#include <algorithm> +#endif + +#include "raslib/error.hh" +#include "adminif.hh" + +#include "raslib/rmdebug.hh" +#include "sqlerror.hh" +#include "objectbroker.hh" + +#include "externs.h" + +// defined in rasserver.cc +extern char globalConnectId[256]; + +AdminIf* AdminIf::myInstance = NULL; + +bool AdminIf::validConnection = false; + +bool AdminIf::readOnlyTA = false; + +DatabaseIf* AdminIf::myDatabaseIf = NULL; + +char AdminIf::systemName[SYSTEMNAME_MAXLEN]; + +bool AdminIf::_isAborted = false; + +bool +AdminIf::isAborted() + { + RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "isAborted()"); + bool retval=false; + +#ifdef READ_ONLY_RMAN + retval=true; +#else + retval=_isAborted; +#endif + RMDBGEXIT(4, RMDebug::module_adminif, "AdminIf", "isAborted() " << retval); + return retval; + } + +void +AdminIf::setAborted(bool newAborted) + { + RMDBGONCE(4, RMDebug::module_adminif, "AdminIf", "setAborted(" << newAborted << ") " << _isAborted); + _isAborted = newAborted; + } + +DatabaseIf* +AdminIf::getCurrentDatabaseIf() + { + RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "getCurrentDatabaseIf() " << myDatabaseIf); + return myDatabaseIf; + } + +void +AdminIf::setCurrentDatabaseIf(DatabaseIf* db) + { + RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "setCurrentDatabaseIf(" << db << ") " << myDatabaseIf); + myDatabaseIf = db; + } + +AdminIf* +AdminIf::instance() + { + RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "instance() " << myInstance); + AdminIf* retval=NULL; + + strcpy((char*)&systemName, dbmsName); + if(!myInstance) + { + myInstance = new AdminIf(); + } + if(validConnection) + retval=myInstance; + + RMDBGEXIT(4, RMDebug::module_adminif, "Adminif", "instance() " << retval); + return retval; + } + +AdminIf::~AdminIf() + { + RMDBGENTER(4, RMDebug::module_adminif, "Adminif", "~AdminIf()"); + + myInstance = NULL; + ObjectBroker::deinit(); + +#ifdef RMANBENCHMARK + DBObject::readTimer.setOutput(0); + + DBObject::updateTimer.setOutput(0); + + DBObject::deleteTimer.setOutput(0); + + DBObject::insertTimer.setOutput(0); + + OId::oidAlloc.setOutput(0); + + OId::oidResolve.setOutput(0); +#endif + RMDBGEXIT(4, RMDebug::module_adminif, "Adminif", "~AdminIf()"); + } + +void +AdminIf::setReadOnlyTA(bool newReadOnlyTA) + { + RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "setReadOnlyTA(" << newReadOnlyTA << ")" << readOnlyTA); + readOnlyTA = newReadOnlyTA; + } + +bool +AdminIf::isReadOnlyTA() + { + RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "isReadOnlyTA()" << readOnlyTA); + return readOnlyTA; + } + +char* +AdminIf::getSystemName() + { + RMDBGONCE(4, RMDebug::module_adminif, "Adminif", "getSystemName()" <<systemName); + return systemName; + } + diff --git a/reladminif/binaryrepresentation.hh b/reladminif/binaryrepresentation.hh new file mode 100644 index 0000000..d2e3f0f --- /dev/null +++ b/reladminif/binaryrepresentation.hh @@ -0,0 +1,31 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +class BinaryRepresentation + { + public: + char* binaryName; + char* binaryData; + size_t binaryLength; + static const char* fileTag; + }; + diff --git a/reladminif/databaseif.hh b/reladminif/databaseif.hh new file mode 100644 index 0000000..f8b8954 --- /dev/null +++ b/reladminif/databaseif.hh @@ -0,0 +1,222 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _DATABASEIF_HH_ +#define _DATABASEIF_HH_ + +/************************************************************************ + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ***********************************************************************/ + +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: +With a DatabaseIf instance a database can be opened or closed. There +is also functionality for creating and deleting DBs. A +database has to be open, before persistence capable classes can be +used (see also \Ref{AdminIf}). + +{\bf Example} + +{\tt DatabaseIf database;} + +{\tt database.open( "myDatabase" )} + +... + +{\tt database.close();} +*/ + +class DatabaseIf; +class TransactionIf; + +#include <iostream> +using std::cout; +using std::endl; +using std::ostream; + +#include "raslib/error.hh" + +class DatabaseIf + { + public: + friend std::ostream& operator<< (std::ostream& stream, DatabaseIf& db); + /*@Doc: + prints the status of the database (connected, online, offline, name) + */ + + /// opens database with name {\tt dbName}. + void open( const char* dbName ) throw(r_Error); + /*@Doc: + Precondition: not opened, not connected, db exists + Postcondition: open, not connected, db exists + If last opened database was not closed (throw r_Error::r_Error_DatabaseOpen)), + If database does not exist (throw r_Error::r_Error_DatabaseUnknown). + In the current implementation this value is returned, when dbName is not RASBASE, + regardles if the db exists or not. + */ + + void close(); + /*@Doc: + Precondition: open, not connected, db exists + Postcondition: not open, not connected, db exists + closes currently opened database. only frees name and sets connected/opened to false. + */ + + static void createDB( const char* dbName, const char* schemaName, const char* volumeName=0 ) throw(r_Error); + /*@Doc: + Precondition: not open, not connected, db does not exist + Postcondition: not open, not connected, db exists + creates a new database. schemaName and volumeName are ignored. + only successful if dbName is RASBASE + */ + + static void destroyDB(const char* dbName) throw(r_Error); + /*@Doc: + Precondition: not open, not connected, db exists + Postcondition: not open, not connected, db does not exist + destroys an existing database with name {\tt dbName}. + Database must not be open in order to be destroyed. + A transaction must not be opened. + Returns -1 if database does not exist. + */ + + + void garbage(); + /*@Doc: + this method does not do anything + */ + + const char* getName() const; + /*@Doc: + returns a pointer to the name of the db. + */ + + DatabaseIf(); + /*@Doc: + constructor. Initializes opened, myName and connected to 0 + */ + + bool isConnected() const; + /*@Doc: + true when there has been an EXEC SQL CONNECT + */ + + bool isOpen() const; + /*@Doc: + true when it was opened by a transaction + */ + + ~DatabaseIf(); + /*@Doc: + executes a baseDBMSClose() if it is still connected. + */ + + static bool databaseExists(const char* dbname) throw (r_Error); + /*@Doc: + Precondition: none checked. db must be open and connected. + Postcondition: none + basedbms error thrown. + checks if a database has been created. + */ + + static bool isConsistent() throw (r_Error); + /*@Doc: + Precondition: none checked. db must be open and connected. + Postcondition: none + basedbms error thrown if something really bad happens. + checks if counters are ok. + */ + + protected: + friend class TransactionIf; + + void baseDBMSOpen() throw (r_Error); + /*@Doc: + Precondition: current database = 0 + Postcondition: current database = this + issues a CONNECT. + sets the DatabaseIf object in AdminIf to this. + */ + + void baseDBMSClose(); + /*@Doc: + Precondition: current database = this + Postcondition: current database = 0 + issues a ROLLBACK WORK RELEASE in oracle. + issues a DISCONNECT in db2. + sets the DatabaseIf object in AdminIf to 0, if it was the same. + */ + + static void connect() throw (r_Error); + /*@Doc: + Precondition: none checked. + Postcondition: none. + issues a CONNECT. + throws r_Error if there is a problem during connection. + */ + + static void disconnect() throw (r_Error); + /*@Doc: + Precondition: none checked. + Postcondition: none. + issues a CONNECT. + throws r_Error if there is a problem during disconnection. + */ + + void checkCompatibility() throw (r_Error); + /*@Doc: + Precondition: none checked. + Postcondition: none. + throws r_Error if the current rasdaman system does not match the database. + */ + + private: + bool opened; + /*@Doc: + TRUE only if database is open. + */ + + char* myName; + /*@Doc: + Valid only if opened. + */ + + bool connected; + /*@Doc: + TRUE only if database connection exists ; ) + */ + + static const char* DefaultDatabaseName; + /*@Doc: + only one database is supported. any database name given is compared to this string. + access to the db is only granted if the name of the database is the same as this string. + */ + + }; + +#endif diff --git a/reladminif/databaseif.pgc b/reladminif/databaseif.pgc new file mode 100644 index 0000000..cec18c5 --- /dev/null +++ b/reladminif/databaseif.pgc @@ -0,0 +1,1382 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +// This is -*- C++ -*- +/************************************************************************* + * + * + * PURPOSE: + * Code with embedded SQL for PostgreSQL DBMS + * + * + * COMMENTS: + * - need connection via ECPG and libqg, use non-public interface to + * obtain libpq style connection ptr from ECPG structure + * - global variable globalConnectId used for DB server identification, maybe better as constructor parameter + * - dbName parameter not evaluated + * - PG: no CLUSTER index available + * - PG: index always in same schema as table + * - replaced "if ((SQLCODE != SQLOK) && (SQLCODE != SQLNULLFETCHED))" + * by "if (SQLCODE < 0 || SQLCODE == SQLNODATAFOUND)" + * - databaseExists() not used + * - attribute name 'OId' -> 'UOId' (for UDFs), 'OId' -> 'Id' (for IXs) + * to avoid PG name clash with attr type + * - except for RAS_COUNTERS, "no data" means no error, but that we need to initialize the empty table + * + ***********************************************************************/ + +static const char rcsid[] = "@(#)reladminif,DatabaseIf: $Id: databaseif.ec,v 1.9 2003/12/27 23:11:43 rasdev Exp $"; + +#include "debug/debug.hh" + +// general embedded SQL related definitions +EXEC SQL include sqlglobals.h; + +// SQL error codes: +EXEC SQL include "externs.h" + +// PG stuff +#include "libpq-fe.h" // C interface to PgSQL +// libq-style connection ptr taken from ECPG connect (needed for libq functions): +// (currently used by relblobif/blobtile.pgc) +PGconn *pgConn = NULL; + +// we use a non-public interface to obtain the connection ptr +// defs are taken from PG's /src/interfaces/ecpg/ecpglib/extern.h +// --- START non-public PG +struct ECPGtype_information_cache +{ + struct ECPGtype_information_cache *next; + int oid; + bool isarray; +}; + +struct connection +{ + char *name; + PGconn *conn; // changed name to avoid component name clash of gcc3 -- PB 2005-feb-08 + bool committed; + int autocommit; + struct ECPGtype_information_cache *cache_head; + struct connection *next; +}; + + +// need to safeguard this from C++ name mangling -- PB 2005-feb-09 +//#ifdef __cplusplus +//extern "C" { +//#endif +// struct connection *ECPGget_connection(const char *); +//#ifdef __cplusplus +//} +//#endif + +// --- END non-public PG + +#include "databaseif.hh" +#include "raslib/rmdebug.hh" +#include "sqlerror.hh" +#include "oidif.hh" +#include "adminif.hh" + +extern char globalConnectId[256]; +// size of ARCHITECTURE attribute in RAS_ADMIN: +#define SIZE_ARCH_RASADMIN 20 + + +void +DatabaseIf::disconnect() throw (r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "disconnect()"); + ENTER( "DatabaseIf::disconnect" ); + + TALK( "EXEC SQL ROLLBACK WORK" ); + EXEC SQL ROLLBACK WORK; + // 'ok' or 'no begin work issued' (which happens at a close database) + if (SQLCODE != SQLOK && SQLCODE != -255) + { + check("DatabaseIf::disconnect() ROLLBACK\0"); + TALK( "Error while issuing ROLLBACK"); + RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "error occured while issuing a ROLLBACK"); + } + +#ifndef FASTCONNECT + TALK( "EXEC SQL DISCONNECT CURRENT" ); + EXEC SQL DISCONNECT CURRENT; + if (SQLCODE != SQLOK) + { + check("DatabaseIf::disconnect() DISCONNECT\0"); + TALK( "Error while issuing DISCONNECT"); + RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "error occured while issuing a DISCONNECT"); + } + pgConn = NULL; +#endif + + LEAVE( "DatabaseIf::disconnect, SQLCODE=" << SQLCODE ); + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "disconnect() SQLCODE=" << SQLCODE); +} + +void +DatabaseIf::connect() throw (r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "connect()"); + ENTER( "DatabaseIf::connect" ); + +#ifndef FASTCONNECT + + EXEC SQL BEGIN DECLARE SECTION; + char id[STRING_MAXLEN]; + EXEC SQL END DECLARE SECTION; + + + strcpy((char *)&id, globalConnectId); + TALK( "EXEC SQL CONNECT TO " << id ); + EXEC SQL CONNECT TO :id AS rasdaConn; // "AS" param must be same as down in ECPGget_connection() + if (SQLCODE != SQLOK) + { + check("DatabaseIf::connect() CONNECT"); + RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "connect() SQLCODE=" << SQLCODE); + TALK( "error in connect, SQLCODE=" << SQLCODE ); + generateException(); + } + char newConnectId[256]; + sprintf(newConnectId, "dbname='%s'", id); + pgConn = PQconnectdb(newConnectId); + if (pgConn == NULL || PQstatus(pgConn) == CONNECTION_BAD) { + RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "Error: cannot obtain libpq connection" ); + TALK( "Error: cannot obtain libpq connection" ); + generateException(); + } + + /* + + // get connection ptr for libpq based access + struct connection *interimConn = NULL; + interimConn = ECPGget_connection( "rasdaConn" ); // param must be same as up in CONNECT ... AS + if (interimConn == NULL || interimConn->conn == NULL) + { + } + pgConn = interimConn->conn;*/ + +#endif + + LEAVE( "DatabaseIf::connect, SQLCODE=" << SQLCODE ); + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "connect()"); +} + +void +DatabaseIf::checkCompatibility() throw (r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "checkCompatibility()"); + ENTER( "DatabaseIf::checkCompatibility" ); + + EXEC SQL BEGIN DECLARE SECTION; + long rasver1; // rasdaman version as stored in db + long schemaver1; // schema version as stored in db + char* arch1[SIZE_ARCH_RASADMIN]; // used for reading architecture from db + char *myArchitecture = RASARCHITECTURE; // used for architecture selection + EXEC SQL END DECLARE SECTION; + + TALK( "EXEC SQL SELECT ServerVersion, IFVersion INTO :rasver1, :schemaver1 FROM RAS_ADMIN WHERE Architecture = " << myArchitecture ); + EXEC SQL SELECT + ServerVersion, IFVersion + INTO + :rasver1, :schemaver1 + FROM + RAS_ADMIN + WHERE + Architecture = :myArchitecture; + TALK( "-> rasver1=" << rasver1 << ", schemaver1=" << schemaver1 ); + if (SQLCODE != SQLOK) + { + check("DatabaseIf::baseDBMSOpen() check schema\0"); + // this error is not supported by PG -- PB 2005-jan-07 + // if (SQLCODE == SQLTABLEUNKNOWN)... + + if (SQLCODE == SQLNODATAFOUND) + { + RMInit::logOut << "The Database is incompatible with the current RasServer." << std::endl \ + << "Database has no entry for the current platform." << std::endl \ + << "You are using rasserver:" << std::endl \ + << "\tversion " << RMANVERSION << std::endl \ + << "\tschema " << RASSCHEMAVERSION << std::endl \ + << "\tplatform " << RASARCHITECTURE << std::endl; + EXEC SQL DECLARE admincursor CURSOR FOR + SELECT + ServerVersion, IFVersion, Architecture + FROM + RAS_ADMIN; + EXEC SQL OPEN admincursor; + do + { + (void) memset( arch1, '\0', (size_t) sizeof(arch1) ); // just to make sure string is terminated + EXEC SQL FETCH admincursor INTO :rasver1, :schemaver1, :arch1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("DatabaseIf::checkCompatibility()\0"); + RMInit::logOut << "DBMS Error occured during compatibility check." << std::endl \ + << "Please see Debug Log for additional information." << std::endl; + EXEC SQL CLOSE admincursor; + generateException(); + } + break; + } + RMInit::logOut << "Found database entries for rasserver:" << std::endl \ + << "\tversion " << rasver1 << std::endl \ + << "\tschema " << schemaver1 << std::endl \ + << "\tplatform " << arch1 << std::endl << std::endl \ + << "Please see Migration Documentation." << std::endl; + } while (true); + + EXEC SQL CLOSE admincursor; + throw r_Error(DATABASE_INCOMPATIBLE); + } + else + { + RMInit::logOut << "DBMS Error occured during compatibility check." << std::endl \ + << "Please see Debug Log for additional information." << std::endl; + generateException(); + } + } + else + { + if (schemaver1 != RASSCHEMAVERSION) + { + RMInit::logOut << "The Database is incompatible with the current RasServer." << std::endl \ + << "The database was generated with:" << std::endl \ + << "\tversion " << rasver1 << std::endl \ + << "\tschema " << schemaver1 << std::endl \ + << "\tplatform " << arch1 << std::endl << std::endl \ + << "You are using rasserver:" << std::endl \ + << "\tversion " << RMANVERSION << std::endl \ + << "\tschema " << RASSCHEMAVERSION << std::endl \ + << "\tplatform " << RASARCHITECTURE << std::endl \ + << "Please see Migration Documentation." << std::endl; + throw r_Error(DATABASE_INCOMPATIBLE); + } +#if 0 // do not check against release, v6 has same schema as v5! -- PB 2005-sep-18 + // check only against major release number -- PB 2003-sep-08 + if (rasver1/1000 != RMANVERSION/1000) + { + RMInit::logOut << "The Database is incompatible with the current RasServer." << std::endl \ + << "The database was generated with:" << std::endl \ + << "\tversion " << rasver1 << std::endl \ + << "\tschema " << schemaver1 << std::endl \ + << "\tplatform " << arch1 << std::endl << std::endl \ + << "You are using rasserver:" << std::endl \ + << "\tversion " << RMANVERSION << std::endl \ + << "\tschema " << RASSCHEMAVERSION << std::endl \ + << "\tplatform " << RASARCHITECTURE << std::endl \ + << "Please see Migration Documentation." << std::endl; + throw r_Error(DATABASE_INCOMPATIBLE); + } +#endif // 0 + } + + LEAVE( "DatabaseIf::checkCompatibility" ); + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "checkComptatibility()"); +} + +bool +DatabaseIf::isConsistent() throw (r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "isConsistent()"); + ENTER( "DatabaseIf::isConsistent" ); + + bool retval=true; + + EXEC SQL BEGIN DECLARE SECTION; + long nextoid; + long checkoid; // was: double -- PB 2005-jul-12 + short oidind; + char name2[255]; // must be able to hold counterNames elements, see oidif.cc + EXEC SQL END DECLARE SECTION; + nextoid = 0; + checkoid = 0; + oidind = 0; + + (void) strncpy( name2, (char*) OId::counterNames[OId::DBMINTERVALOID], (size_t) sizeof(name2) ); + TALK( "EXEC SQL SELECT NextValue INTO :nextoid FROM RAS_COUNTERS WHERE CounterName = " << name2 ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM + RAS_COUNTERS + WHERE + CounterName = :name2; + TALK( "-> nextoid=" << nextoid ); + if (check("DatabaseIf::isConsistent() SELECT DBMINTERVALOID")) + generateException(); + + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(DomainId) INTO :checkoid INDICATOR :oidind + // FROM RAS_DOMAINS; + checkoid = 0; + TALK( "SELECT DomainId..." ); + EXEC SQL SELECT DomainId INTO :checkoid INDICATOR :oidind + FROM RAS_DOMAINS + ORDER BY DomainId DESC LIMIT 1; + TALK( "-> SQLCODE=" << SQLCODE ); + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(DomainId)"); + generateException(); + } + if ((checkoid > nextoid) && (oidind == 0)) + { + RMInit::logOut << "The administrative tables for Domain Data is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_DOMAINS : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::MDDOID], (size_t) sizeof(name2) ); + TALK( "SELECT NextValue FROM RAS_COUNTERS..." ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT MDDOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(MDDId) INTO :checkoid INDICATOR :oidind + // FROM RAS_MDDOBJECTS; + checkoid = 0; + TALK( "SELECT MDDId FROM RAS_MDDOBJECTS..." ); + EXEC SQL SELECT MDDId INTO :checkoid INDICATOR :oidind + FROM RAS_MDDOBJECTS + ORDER BY MDDId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(MDDId)"); + generateException(); + } + + if ((checkoid > nextoid) && (oidind == 0)) + { + RMInit::logOut << "The administrative tables for MDD Objects is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_MDDOBJECTS : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::MDDCOLLOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT MDDCollOId")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(MDDCollId) INTO :checkoid INDICATOR :oidind + // FROM RAS_MDDCOLLNAMES; + checkoid = 0; + TALK( "SELECT MDDCollId FROM RAS_MDDCOLLNAMES..." ); + EXEC SQL SELECT MDDCollId INTO :checkoid INDICATOR :oidind + FROM RAS_MDDCOLLNAMES + ORDER BY MDDCollId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(MDDCollId)"); + generateException(); + } + + if ((checkoid > nextoid) && (oidind == 0)) + { + RMInit::logOut << "The administrative tables for MDD Collections is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_MDDCOLLNAMES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::MDDTYPEOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT MDDTYPEOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(MDDTypeOId) INTO :checkoid INDICATOR :oidind + // FROM RAS_MDDTYPES; + checkoid = 0; + TALK( "SELECT MDDTypeOId FROM RAS_MDDTYPES..." ); + EXEC SQL SELECT MDDTypeOId INTO :checkoid INDICATOR :oidind + FROM RAS_MDDTYPES + ORDER BY MDDTypeOId DESC LIMIT 1; + TALK( "SELECT MDDTypeOId FROM RAS_MDDTYPES..." ); + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(MDDTypeOId)"); + generateException(); + } + + if (checkoid > nextoid) + { + RMInit::logOut << "The administrative tables for MDDTypes is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_MDDTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::MDDBASETYPEOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT MDDBASETYPEOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(MDDBaseTypeOId) INTO :checkoid INDICATOR :oidind + // FROM RAS_MDDBASETYPES; + checkoid = 0; + TALK( "SELECT MDDBaseTypeOId FROM RAS_MDDBASETYPES..." ); + EXEC SQL SELECT MDDBaseTypeOId INTO :checkoid INDICATOR :oidind + FROM RAS_MDDBASETYPES + ORDER BY MDDBaseTypeOId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(MDDBaseTypeOId)"); + generateException(); + } + + if (checkoid > nextoid) + { + RMInit::logOut << "The administrative tables for MDDBaseTypes is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_MDDBASETYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::MDDDIMTYPEOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT MDDDIMTYPEOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(MDDDimTypeOId) INTO :checkoid INDICATOR :oidind + // FROM RAS_MDDDIMTYPES; + checkoid = 0; + TALK( "SELECT MDDDimTypeOId FROM RAS_MDDDIMTYPES..." ); + EXEC SQL SELECT MDDDimTypeOId INTO :checkoid INDICATOR :oidind + FROM RAS_MDDDIMTYPES + ORDER BY MDDDimTypeOId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(MDDDimTypeOId)"); + generateException(); + } + + if (checkoid > nextoid) + { + RMInit::logOut << "The administrative tables for MDDDimensionTypes is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_MDDDIMTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::MDDDOMTYPEOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT MDDDOMTYPEOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(MDDDomTypeOId) INTO :checkoid INDICATOR :oidind + // FROM RAS_MDDDOMTYPES; + checkoid = 0; + TALK( "SELECT MDDDomTypeOId FROM RAS_MDDDOMTYPES..." ); + EXEC SQL SELECT MDDDomTypeOId INTO :checkoid INDICATOR :oidind + FROM RAS_MDDDOMTYPES + ORDER BY MDDDomTypeOId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(MDDDomTypeId)"); + generateException(); + } + + if (checkoid > nextoid) + { + RMInit::logOut << "The administrative tables for MDDDomainTypes is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_MDDDOMTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::STRUCTTYPEOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT STRUCTTYPEOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(BaseTypeId) INTO :checkoid INDICATOR :oidind + // FROM RAS_BASETYPENAMES; + checkoid = 0; + TALK( "SELECT BaseTypeId FROM RAS_BASETYPENAMES..." ); + EXEC SQL SELECT BaseTypeId INTO :checkoid INDICATOR :oidind + FROM RAS_BASETYPENAMES + ORDER BY BaseTypeId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(BaseTypeId)"); + generateException(); + } + + if ((checkoid > nextoid) && (oidind == 0)) + { + RMInit::logOut << "The administrative tables for StructTypes is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_BASETYPENAMES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::SETTYPEOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT SETTYPEOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(SetTypeId) INTO :checkoid INDICATOR :oidind + // FROM RAS_SETTYPES; + checkoid = 0; + TALK( "SELECT SetTypeId FROM RAS_SETTYPES..." ); + EXEC SQL SELECT SetTypeId INTO :checkoid INDICATOR :oidind + FROM RAS_SETTYPES + ORDER BY SetTypeId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(SetTypeId)"); + generateException(); + } + + if ((checkoid > nextoid) && (oidind == 0)) + { + RMInit::logOut << "The administrative tables for MDDTypes is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_SETTYPES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::BLOBOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT BLOBOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(BlobId) INTO :checkoid INDICATOR :oidind + // FROM RAS_TILES; + checkoid = 0; + TALK( "SELECT BlobId FROM RAS_TILES..." ); + EXEC SQL SELECT BlobId INTO :checkoid INDICATOR :oidind + FROM RAS_TILES + ORDER BY BlobId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(BlobId)"); + generateException(); + } + + if ((checkoid > nextoid) && (oidind == 0)) + { + RMInit::logOut << "The administrative tables for BLOB Data is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_TILES : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::MDDHIERIXOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT MDDHIERIXOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(MDDObjIxOId) INTO :checkoid INDICATOR :oidind + // FROM RAS_HIERIX; + checkoid = 0; + TALK( "SELECT MDDObjIxOId FROM RAS_HIERIX..." ); + EXEC SQL SELECT MDDObjIxOId INTO :checkoid INDICATOR :oidind + FROM RAS_HIERIX + ORDER BY MDDObjIxOId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(MDDObjIxOId)"); + generateException(); + } + + if (checkoid > (nextoid * 512 + OId::MDDHIERIXOID)) + { + RMInit::logOut << "The administrative tables for hierarchical MDD indexes is inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_HIERIX : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << " real " << (nextoid * 512 + OId::MDDHIERIXOID) << std::endl; + retval=false; + } + checkoid = 0; + nextoid=0; + oidind=0; + } + + if(retval) + { + (void) strncpy( name2, (char*) OId::counterNames[OId::STORAGEOID], (size_t) sizeof(name2) ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name2; + if (check("DatabaseIf::isConsistent() SELECT STORAGEOID")) + generateException(); + // replaced MAX() (which ignores index) by ORDER BY variant -- PB 2005-jul-12 + // EXEC SQL SELECT MAX(StorageId) INTO :checkoid INDICATOR :oidind + // FROM RAS_STORAGE; + checkoid=0; + TALK( "SELECT StorageId FROM RAS_STORAGE..." ); + EXEC SQL SELECT StorageId INTO :checkoid INDICATOR :oidind + FROM RAS_STORAGE + ORDER BY StorageId DESC LIMIT 1; + // now "no data" means no error, but that we need to initialize the empty table + if (SQLCODE < 0) + { + check("DatabaseIf::isConsistent() SELECT MAX(StorageId)"); + generateException(); + } + + if ((checkoid > nextoid) && (oidind == 0)) + { + RMInit::logOut << "Fatal error: administrative tables for MDD storage structures are inconsistent. Please call support." << std::endl; + RMInit::dbgOut << std::endl << "Counter in RAS_STORAGE : " << checkoid << std::endl << "Counter in RAS_COUNTERS : " << nextoid << std::endl; + retval=false; + } + checkoid=0; + nextoid=0; + oidind=0; + } + + LEAVE( "DatabaseIf::isConsistent, retval=" << retval ); + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "isConsistent() " << retval); + return retval; +} + +void +DatabaseIf::createDB(const char* dbName, const char* schemaName, const char* volumeName) throw(r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "create(" << dbName << ", " << schemaName << ", " << volumeName << ")"); + ENTER( "DatabaseIf::createDB, dbName=" << dbName << ", schemaName=" << schemaName << ", volumeName=" << volumeName ); + + int i=0; + EXEC SQL BEGIN DECLARE SECTION; + long id; + long idd; + char name[255]; + EXEC SQL END DECLARE SECTION; + + name[0] = '\0'; // initialize to empty string + + try + { + if (AdminIf::getCurrentDatabaseIf() != 0) + { + RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "another database is open"); + TALK( "Error: another database is open" ); + throw r_Error(r_Error::r_Error_DatabaseOpen); + } + connect(); + TALK( "EXEC SQL BEGIN WORK;"); + EXEC SQL BEGIN WORK; + if(check("DatabaseIf::create() BEGIN WORK\0")) + generateException(); + +/* not used, see comment with databaseExists() + // does database exist already? + if (databaseExists(dbName)) + { + RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "database already exists"); + RMInit::logOut << "Database creation failed: database exists already." << std::endl; + TALK( "Error: database exists." ); + throw r_Error(DATABASE_EXISTS); + } +*/ + + // --- start table/index creation ------------------------------ + + // no index here because there is only one entry in the table + TALK( "EXEC SQL CREATE TABLE RAS_ADMIN ( IFVersion INTEGER NOT NULL, Architecture VARCHAR(20) NOT NULL, ServerVersion INTEGER NOT NULL) " ); + EXEC SQL CREATE TABLE RAS_ADMIN ( + IFVersion INTEGER NOT NULL, + Architecture VARCHAR(20) NOT NULL, + ServerVersion INTEGER NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_ADMIN\0")) + generateException(); + + id = RASSCHEMAVERSION; + idd = RMANVERSION; + (void) strncpy( name, RASARCHITECTURE, (size_t) sizeof(name) ); + + TALK( "EXEC SQL INSERT INTO RAS_ADMIN (IFVersion, Architecture, ServerVersion) VALUES (" << id << ", " << name << ", " << idd << ")" ); + EXEC SQL INSERT INTO RAS_ADMIN (IFVersion, Architecture, ServerVersion) VALUES (:id, :name, :idd); + if(check("DatabaseIf::create() INSERT INTO RAS_ADMIN\0")) + generateException(); + + // no index here because there is only 20 entries in the table + TALK( "EXEC SQL CREATE TABLE RAS_COUNTERS ( NextValue INTEGER NOT NULL, CounterName VARCHAR(20) NOT NULL)" ); + EXEC SQL CREATE TABLE RAS_COUNTERS ( + NextValue INTEGER NOT NULL, + CounterName VARCHAR(20) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_COUNTERS\0")) + generateException(); + + // initialising RAS_COUNTERS + for(i = 1; i < OId::maxCounter; i++) + { + (void) strncpy( name, (char*) OId::counterNames[i], (size_t) sizeof(name) ); + id = 1; + TALK( "EXEC SQL INSERT INTO RAS_COUNTERS (CounterName, NextValue) VALUES (" << name << "," << id << ")" ); + EXEC SQL INSERT INTO RAS_COUNTERS (CounterName, NextValue) VALUES (:name, :id); + if(check("DatabaseIf::create() INSERT INTO RAS_COUNTERS\0")) + generateException(); + } + + TALK( "...and several more tables..." ); + + // relblobif + EXEC SQL CREATE TABLE RAS_TILES ( + BlobId INTEGER NOT NULL, + DataFormat INTEGER, + Tile oid + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_TILES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_TILES_IX + ON RAS_TILES (BlobId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_TILES_IX\0")) + generateException(); + + //ras_itiles + EXEC SQL CREATE TABLE RAS_ITILES ( + ITileId INTEGER NOT NULL, + ITile oid + ); + if (check("DatabaseIf::create() CREATE TABLE RAS_ITILES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_ITILES_IX + ON RAS_ITILES (ITileId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_ITILES_IX\0")) + generateException(); + + // relcatalogif + EXEC SQL CREATE TABLE RAS_MDDTYPES ( + MDDTypeOId DEC(15,0) NOT NULL, + MDDTypeName VARCHAR(254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDTYPES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_MDDTYPES_IX + ON RAS_MDDTYPES (MDDTypeOId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDTYPES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_ITMAP ( + TileId INTEGER NOT NULL, + IndexId INTEGER NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_ITMAP\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_ITMAP_IX + ON RAS_ITMAP (TileId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_ITMAP_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_MDDBASETYPES ( + MDDBaseTypeOId DEC(15,0) NOT NULL, + BaseTypeId DEC(15,0) NOT NULL, + MDDTypeName VARCHAR(254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDBASETYPES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_MDDBASETYPES_IX + ON RAS_MDDBASETYPES (MDDBaseTypeOId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDBASETYPES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_MDDDIMTYPES ( + MDDDimTypeOId DEC(15,0) NOT NULL, + BaseTypeId DEC(15,0) NOT NULL, + Dimension INTEGER NOT NULL, + MDDTypeName VARCHAR(254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDDIMTYPES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_MDDDIMTYPES_IX + ON RAS_MDDDIMTYPES (MDDDimTypeOId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDDIMTYPES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_MDDDOMTYPES ( + MDDDomTypeOId DEC(15,0) NOT NULL, + BaseTypeId DEC(15,0) NOT NULL, + DomainId INTEGER NOT NULL, + MDDTypeName VARCHAR(254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDDOMAINTYPES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_MDDDOMTYPES_IX + ON RAS_MDDDOMTYPES (MDDDomTypeOId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDDOMTYPES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_SETTYPES ( + SetTypeId INTEGER NOT NULL, + MDDTypeOId DEC(15,0) NOT NULL, + SetTypeName VARCHAR(254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_SETTYPES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_SETTYPES_IX + ON RAS_SETTYPES (SetTypeId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_SETTYPES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_BASETYPENAMES ( + BaseTypeId SMALLINT NOT NULL, + BaseTypeName VARCHAR (254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_BASETYPENAMES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_BASETYPENAMES_IX + ON RAS_BASETYPENAMES (BaseTypeId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_BASETYPENAMES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_BASETYPES ( + BaseTypeId INTEGER NOT NULL, + Count SMALLINT NOT NULL, + ContentType DEC(15,0) NOT NULL, + ContentTypeName VARCHAR (254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_BASETYPES\0")) + generateException(); + + EXEC SQL CREATE INDEX RAS_BASETYPESC_IX + ON RAS_BASETYPES (BaseTypeId); + if(check("DatabaseIf::create() CREATE INDEX RAS_BASETYPES_IX\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_BASETYPES_IX + ON RAS_BASETYPES (BaseTypeId, Count); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_BASETYPES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_DOMAINS ( + DomainId INTEGER NOT NULL, + Dimension INTEGER NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_DOMAINS\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_DOMAINS_IX + ON RAS_DOMAINS (DomainId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_DOMAINS_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_DOMAINVALUES ( + DomainId INTEGER NOT NULL, + DimensionCount INTEGER NOT NULL, + Low INTEGER, + High INTEGER + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_DOMAINVALUES\0")) + generateException(); + + EXEC SQL CREATE INDEX RAS_DOMAINVALUESC_IX + ON RAS_DOMAINVALUES (DomainId); + if(check("DatabaseIf::create() CREATE INDEX RAS_DOMAINVALUESC_IX\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_DOMAINVALUES_IX + ON RAS_DOMAINVALUES (DomainId, DimensionCount); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_DOMAINVALUES_IX\0")) + generateException(); + + // relmddif + EXEC SQL CREATE TABLE RAS_MDDCOLLECTIONS ( + MDDId INTEGER NOT NULL, + MDDCollId INTEGER NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDCOLLECTIONS\0")) + generateException(); + + EXEC SQL CREATE INDEX RAS_COLLECTIONSC_IX + ON RAS_MDDCOLLECTIONS (MDDCOllId); + if(check("DatabaseIf::create() CREATE INDEX RAS_COLLECTIONSC_IX\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_COLLECTIONS_IX + ON RAS_MDDCOLLECTIONS (MDDCOllId, MDDId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_COLLECTIONS_IX\0")) + generateException(); + + // referes to MDDSet + EXEC SQL CREATE TABLE RAS_MDDCOLLNAMES ( + MDDCollId INTEGER NOT NULL, + SetTypeId INTEGER NOT NULL, + MDDCollName VARCHAR(254) + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDCOLLNAMES\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_MDDCOLLNAMES_IX + ON RAS_MDDCOLLNAMES (MDDCollId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDCOLLNAMES_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_MDDOBJECTS ( + MDDId INTEGER NOT NULL, + BaseTypeOId DEC(15,0) NOT NULL, + DomainId INTEGER NOT NULL, + PersRefCount INTEGER NOT NULL, + StorageOId DEC(15,0) NOT NULL, + NodeOId DEC(15,0) + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDOBJECTS\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_MDDOBJECTS_IX + ON RAS_MDDOBJECTS (MDDId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_MDDOBJECTS_IX\0")) + generateException(); + + //relstorageif + EXEC SQL CREATE TABLE RAS_STORAGE ( + StorageId INTEGER NOT NULL, + DomainId INTEGER, + TileSize INTEGER, + PCTMin INTEGER, + PCTMax INTEGER, + IndexSize INTEGER, + IndexType SMALLINT, + TilingScheme SMALLINT, + DataFormat SMALLINT + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_MDDOBJECTS\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_STORAGE_IX + ON RAS_STORAGE (StorageId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_STORAGE_IX\0")) + generateException(); + + // relindexif + // may not be needed + EXEC SQL CREATE TABLE RAS_HIERIX ( + MDDObjIxOId DEC(15,0) NOT NULL, + NumEntries SMALLINT NOT NULL, + Dimension SMALLINT NOT NULL, + ParentOId DEC(15,0) NOT NULL, + IndexSubType SMALLINT NOT NULL, + DynData OID + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_HIERIX\0")) + generateException(); + + // Note: table RAS_HIERIXDYN is not needed, we put each index node into the above DynData blob + + EXEC SQL CREATE TABLE RAS_UDFBODY ( + UOId DEC(15,0) NOT NULL, + Name VARCHAR(254) NOT NULL, + Body CHAR(3700) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_UDFBODY\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_UDFBODY_IX + ON RAS_UDFBODY (UOId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFBODY_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_UDFARGS ( + UOId DEC(15,0) NOT NULL, + ArgNum SMALLINT NOT NULL, + ArgName VARCHAR(254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_UDFARGS\0")) + generateException(); + + EXEC SQL CREATE INDEX RAS_UDFARGSC_IX + ON RAS_UDFARGS(UOId); + if(check("DatabaseIf::create() CREATE INDEX RAS_UDFARGSC_IX\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_UDFARGS_IX + ON RAS_UDFARGS(UOId, ArgNum); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFARGS_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_UDFPACKAGE ( + UOId DEC(15,0) NOT NULL, + Name VARCHAR(254) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_UDFPACKAGE\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_UDFPACKAGEN_IX + ON RAS_UDFPACKAGE (Name); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFPACKAGEN_IX\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_UDFPACKAGEO_IX + ON RAS_UDFPACKAGE (UOId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFPACKAGEO_IX\0")) + generateException(); + + EXEC SQL CREATE TABLE RAS_UDFNSCONTENT ( + UOId DEC(15,0) NOT NULL, + UDFOId DEC(15,0) NOT NULL + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_UDFNSCONTENT\0")) + generateException(); + + EXEC SQL CREATE INDEX RAS_UDFNSCONTENTC_IX + ON RAS_UDFNSCONTENT(UOId); + if(check("DatabaseIf::create() CREATE INDEX RAS_UDFNSCONTENTC_IX\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_UDFNSCONTENT_IX + ON RAS_UDFNSCONTENT(UOId, UDFOId); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_UDFNSCONTENT_IX\0")) + generateException(); + + // We need 1 byte more because the first character may not be a \0 -> the first byte is always 13 + // note: this does not hold for PG, but we keep it to remain cross-platform consistent in data + // note2: we use blob instead of varchar because the latter can hold only ascii data in PG + EXEC SQL CREATE TABLE RAS_RCINDEXDYN ( + Id DEC(15,0) NOT NULL, + Count DEC(3,0) NOT NULL, + DynData oid + ); + if(check("DatabaseIf::create() CREATE TABLE RAS_RCINDEXDYN\0")) + generateException(); + + EXEC SQL CREATE INDEX RAS_RCINDEXDYNC_IX + ON RAS_RCINDEXDYN (Id); + if(check("DatabaseIf::create() CREATE INDEX RAS_RCINDEXDYNC_IX\0")) + generateException(); + + EXEC SQL CREATE UNIQUE INDEX RAS_RCINDEXDYN_IX + ON RAS_RCINDEXDYN (Id, Count); + if(check("DatabaseIf::create() CREATE UNIQUE INDEX RAS_RCINDEXDYN_IX\0")) + generateException(); + + EXEC SQL CREATE VIEW RAS_MDDTYPES_VIEW + (MDDTypeOId, MDDTypeName) + AS + SELECT + MDDTypeOId * 512 + 3, MDDTypeName + FROM + RAS_MDDTYPES + UNION + SELECT + MDDBaseTypeOId * 512 + 4, MDDTypeName + FROM + RAS_MDDBASETYPES + UNION + SELECT + MDDDimTypeOId * 512 + 5, MDDTypeName + FROM + RAS_MDDDIMTYPES + UNION + SELECT + MDDDomTypeOId * 512 + 6, MDDTypeName + FROM + RAS_MDDDOMTYPES; + if(check("DatabaseIf::create() CREATE VIEW")) + generateException(); + + TALK( "EXEC SQL COMMIT WORK" ); + EXEC SQL COMMIT WORK; + if(check("DatabaseIf::create() COMMIT WORK")) + generateException(); + + disconnect(); + } + catch (r_Error& err) + { + // abort TA, ignore any error there + TALK( "EXEC SQL ABORT WORK;"); + EXEC SQL ABORT WORK; + + RMDBGMIDDLE(0, RMDebug::module_adminif, "DatabaseIf", "create(" << dbName << ", " << schemaName << ", " << volumeName << ") error caught " << err.what() << " " << err.get_errorno()); + throw; // rethrow exception + } + + LEAVE( "DatabaseIf::createDB, SQLCODE=" << SQLCODE ); + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "create(" << dbName << ", " << schemaName << ", " << volumeName << ")"); +} + +void +DatabaseIf::destroyDB(const char* dbName) throw(r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "destroyDB(" << dbName << ")"); + ENTER( "DatabaseIf::destroyDB, dbName=" << dbName ); + + if (AdminIf::getCurrentDatabaseIf() != 0) + { + RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "another database is already open"); + LEAVE( "Error: another database is already open" ); + RMInit::logOut << "Another database is already open." << std::endl << "Cannot destroy database " << dbName << "." << std::endl; + throw r_Error(r_Error::r_Error_DatabaseOpen); + } + connect(); + +/* this check is omitted, see databaseExists() comment + // terminate processing of database was not found -- PB 2003-sep-05 + // try + // { + if (!databaseExists(dbName)) + { + RMDBGMIDDLE(5, RMDebug::module_adminif, "DatabaseIf", "unknown database"); + LEAVE( "Error: Database unknown" ); + RMInit::logOut << "Database " << dbName << " not found." << std::endl << "Cannot destroy database " << dbName << "." << std::endl; + throw r_Error(r_Error::r_Error_DatabaseUnknown); + } + // } + // catch (r_Error& err) + // { + // RMInit::logOut << "Caught exception while trying to check for existence of database: " << err.what() << " " << err.get_errorno() << " " << err.get_kind() << endl; + // RMInit::logOut << "Continuing with destruction of the database" << endl; + // TALK( "Continuing destruction of the database after error " << err.get_errorno() << " " << err.get_kind() ); + // } +*/ + + EXEC SQL BEGIN WORK; + check("DatabaseIf::destroyDB() BEGIN WORK\0"); + + EXEC SQL DROP VIEW RAS_MDDTYPES_VIEW; + check("DatabaseIf::destroyDB() DROP VIEW RAS_MDDTYPES_VIEW\0"); + + // relblobif + EXEC SQL DROP TABLE RAS_TILES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_TILES\0"); + + EXEC SQL DROP TABLE RAS_ITILES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_ITILES\0"); + + // relcatalogif + EXEC SQL DROP TABLE RAS_MDDTYPES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDTYPES\0"); + + EXEC SQL DROP TABLE RAS_ITMAP; + check("DatabaseIf::destroyDB() DROP TABLE RAS_ITMAP\0"); + + EXEC SQL DROP TABLE RAS_MDDBASETYPES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDBASETYPES\0"); + + EXEC SQL DROP TABLE RAS_MDDDIMTYPES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDDIMENSIONTYPES\0"); + + EXEC SQL DROP TABLE RAS_MDDDOMTYPES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDDOMAINTYPES\0"); + + EXEC SQL DROP TABLE RAS_SETTYPES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_SETTYPES\0"); + + EXEC SQL DROP TABLE RAS_BASETYPENAMES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_BASETYPENAMES\0"); + + EXEC SQL DROP INDEX RAS_BASETYPES_IX; + check("DatabaseIf::destroyDB() DROP INDEX RAS_BASETYPES_IX\0"); + + EXEC SQL DROP TABLE RAS_BASETYPES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_BASETYPES\0"); + + EXEC SQL DROP TABLE RAS_DOMAINS; + check("DatabaseIf::destroyDB() DROP TABLE RAS_DOMAINS\0"); + + EXEC SQL DROP TABLE RAS_DOMAINVALUES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_DOMAINVALUES\0"); + + // relmddif + // referes to DBMDDCollOIdEntry + EXEC SQL DROP TABLE RAS_MDDCOLLECTIONS; + check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDCOLLECTIONS\0"); + + // referes to MDDSet + EXEC SQL DROP TABLE RAS_MDDCOLLNAMES; + check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDCOLLNAMES\0"); + + EXEC SQL DROP TABLE RAS_MDDOBJECTS; + check("DatabaseIf::destroyDB() DROP TABLE RAS_MDDOBJECTS\0"); + + // relindexif + // may not be needed + EXEC SQL DROP TABLE RAS_HIERIX; + check("DatabaseIf::destroyDB() DROP TABLE RAS_HIERIX\0"); + + EXEC SQL DROP INDEX RAS_HIERIXDYN_IX; + check("DatabaseIf::destroyDB() DROP INDEX RAS_HIERIXDYN_IX\0"); + + EXEC SQL DROP TABLE RAS_HIERIXDYN; + check("DatabaseIf::destroyDB() DROP TABLE RAS_HIERIXDYN\0"); + + EXEC SQL DROP TABLE RAS_STORAGE; + check("DatabaseIf::destroyDB() DROP TABLE RAS_STORAGE\0"); + + EXEC SQL DROP TABLE RAS_COUNTERS; + check("DatabaseIf::destroyDB() DROP TABLE RAS_COUNTERS\0"); + + EXEC SQL DROP TABLE RAS_UDFBODY; + check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFBODY"); + + EXEC SQL DROP TABLE RAS_UDFARGS; + check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFARGS"); + + EXEC SQL DROP TABLE RAS_UDFPACKAGE; + check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFPACKAGE"); + + EXEC SQL DROP TABLE RAS_UDFNSCONTENT; + check("DatabaseIf::destroyDB() DROP TABLE RAS_UDFNSCONTENT"); + + EXEC SQL DROP INDEX RAS_RCINDEXDYN_IX; + check("DatabaseIf::destroyDB() DROP INDEX RAS_RCINDEXDYN_IX\0"); + + EXEC SQL DROP TABLE RAS_RCINDEXDYN; + check("DatabaseIf::destroyDB() DROP TABLE RAS_RCINDEXDYN\0"); + + EXEC SQL DROP TABLE RAS_ADMIN; + check("DatabaseIf::destroyDB() DROP TABLE RAS_ADMIN\0"); + + EXEC SQL COMMIT WORK; + check("DatabaseIf::destroyDB() COMMIT\0"); + + disconnect(); + + LEAVE( "DatabaseIf::destroyDB" ); + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "destroyDB(" << dbName << ")"); +} + +/** +This test is omitted because in PG it would fail the transaction, +hence making continuation impossible. +On the other hand, if the database really doesn't exist +/ exists already (whatever is the erroneous situation) +the transaction will fail for the very same reason. +And here we can't decide what situation is good / not good! +The only thing we lose is an appropriate error message +on the top-level situation of the whole database. + +To make sure that no invocation of this function leads to erroneous results, we disable it. +**/ + +#if 0 // disable function to avoid invocation -- PB 2005-feb05 +bool +DatabaseIf::databaseExists(const char* dbname) throw (r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "databaseExists(" << dbname << ")"); + ENTER( "DatabaseIf::databaseExists, dbName(ignored)=" << dbname ); + + EXEC SQL BEGIN DECLARE SECTION; + long nextoid; + short oidind; + char name1[255]; // must be large enough to hold counterNames, see oidif.cc + EXEC SQL END DECLARE SECTION; + bool retval = true; + + (void) strncpy( name1, (char*) OId::counterNames[OId::DBMINTERVALOID], (size_t) sizeof(name1) ); + TALK( "EXEC SQL SELECT NextValue INTO :nextoid FROM RAS_COUNTERS WHERE CounterName = " << name1 << ";" ) + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name1; + retval = (SQLCODE == SQLOK) ? true : false; + + LEAVE( "DatabaseIf::databaseExists, SQLCODE=" << SQLCODE << ", retval=" << retval ); + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "databaseExists(" << dbname << ") retval " << retval); + + return retval; +} +#endif // 0 diff --git a/reladminif/databaseifcommon.cc b/reladminif/databaseifcommon.cc new file mode 100644 index 0000000..b3e3097 --- /dev/null +++ b/reladminif/databaseifcommon.cc @@ -0,0 +1,242 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +// This is -*- C++ -*- +/************************************************************************* + * + * + * PURPOSE: + * Contains all code that is shared by the database interface implementations + * + * + * COMMENTS: + * - schema version depending on release doesn't make sense; rather change + * it when the schema _really_ changes! + * + ***********************************************************************/ + + +#include <string.h> +#include <malloc.h> + +#include "globals.hh" // DEFAULT_DBNAME + +#include "databaseif.hh" +#include "adminif.hh" +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" +#include "externs.h" +#include "sqlerror.hh" +#include "raslib/error.hh" +#include "relcatalogif/alltypes.hh" + +// defined in rasserver.cc +extern char globalConnectId[256]; + +const char* DatabaseIf::DefaultDatabaseName = DEFAULT_DBNAME; + +DatabaseIf::~DatabaseIf() +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "~DatabaseIf()"); + if (isConnected()) + { + baseDBMSClose(); + } + if (myName) + { + free(myName); + myName = NULL; + } + + connected = false; + opened = false; + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "~DatabaseIf()"); +} + +bool +DatabaseIf::isConnected() const +{ + RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "isConnected() " << connected); + return connected; +} + +bool +DatabaseIf::isOpen() const +{ + RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "isOpen() " << opened); + return opened; +} + +void +DatabaseIf::open(const char* dbName) throw(r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "open(" << dbName << ")"); + + if (opened) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "another database is already open"); + throw r_Error(r_Error::r_Error_DatabaseOpen); + } + else + { + //cannot do any further error checking + if ( 0 ) // we allow any other database name -- strcmp(dbName, DefaultDatabaseName)) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "database name unknown"); + RMInit::logOut << "b_DatabaseIf::open(" << dbName << ") dbName=" << dbName << std::endl; + throw r_Error(r_Error::r_Error_DatabaseUnknown); + } + else + { + opened = true; + myName = strdup(dbName); + } + } + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "open(" << dbName << ")"); +} + +void +DatabaseIf::baseDBMSOpen() throw (r_Error) +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSOpen() " << ((myName)? myName:"NULL")); + if (connected) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "DatabaseIf", "databasename is already connected"); + throw r_Error(r_Error::r_Error_TransactionOpen); + } +#ifdef RMANDEBUG + if (AdminIf::getCurrentDatabaseIf()) + { + RMDBGMIDDLE(0, RMDebug::module_adminif, "DatabaseIf", "baseDBMSOpen() CurrentDatabaseIf != 0"); + RMInit::logOut << "Transaction begin:" << std::endl \ + << "There seems to be another database connection active (Internal State 1)." << std::endl \ + << "Please contact Customer support." << std::endl; + throw r_Error(DATABASE_OPEN); + } +#endif + AdminIf::setCurrentDatabaseIf(this); + connect(); + connected = true; + +#ifdef DBMS_PGSQL // cannot have this check in PostgreSQL -- PB 2005-jan-09 + if (!databaseExists(myName)) + { + RMInit::logOut << "Database " << ((myName)? myName: "NULL") << " unknown" << std::endl; + throw r_Error(r_Error::r_Error_DatabaseUnknown); + } +#endif // DBMS_PGSQL + +#ifndef FASTCONNECT + checkCompatibility(); + if (!isConsistent()) + { + RMInit::logOut << "Database " << ((myName)? myName: "NULL") << " inconsistent" << std::endl; + throw r_Error(DATABASE_INCONSISTENT); + } +#endif + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSOpen()"); +} + +void +DatabaseIf::close() +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "close()"); + opened = false; + if (myName) + { + free(myName); + myName = NULL; + } + if (connected) + { + disconnect(); + connected = false; + } + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "close()"); +} + +void +DatabaseIf::baseDBMSClose() +{ + RMDBGENTER(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSClose()"); +#ifdef RMANDEBUG + if (AdminIf::getCurrentDatabaseIf() == this) + { +#endif + AdminIf::setCurrentDatabaseIf(0); +#ifdef RMANDEBUG + } + else + { + //this happens when a transaction is killed by the server + RMDBGONCE(0, RMDebug::module_adminif, "DatabaseIf", "baseDBMSClose() current DatabaseIf != this"); + } +#endif + disconnect(); + connected = false; + RMDBGEXIT(4, RMDebug::module_adminif, "DatabaseIf", "baseDBMSClose()"); +} + +DatabaseIf::DatabaseIf() + : opened(false), + connected(false), + myName(NULL) +{ + RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "DatabaseIf()"); +} + +const char* +DatabaseIf::getName() const +{ + RMDBGONCE(4, RMDebug::module_adminif, "DatabaseIf", "getName() " << ((myName)? myName:"NULL")); + return myName; +} + +ostream& +operator << (ostream& stream, DatabaseIf& db) +{ + stream << "DatabaseIf" << std::endl; + stream << "\tConnected To\t: " << ((db.getName())? db.getName():" ") << std::endl; + if (db.opened) + { + if (db.connected) + { + stream << "\tDatabase is really ONLINE" << std::endl; + } + else + { + stream << "\tDatabase is only FAKE ONLINE" << std::endl; + } + } + else + { + stream << "\tDatabase is OFFLINE" << std::endl; + } + return stream; +} + +void +DatabaseIf::garbage( ) +{ + RMDBGONCE(0, RMDebug::module_adminif, "DatabaseIf", "garbage() NOT IMPLEMENTED"); +} + diff --git a/reladminif/dbnamedobject.cc b/reladminif/dbnamedobject.cc new file mode 100644 index 0000000..1ad2472 --- /dev/null +++ b/reladminif/dbnamedobject.cc @@ -0,0 +1,179 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "mymalloc/mymalloc.h" + +/***************************************************************************** + * + * + * PURPOSE: + * + * + * + * COMMENTS: + * uses embedded SQL + * + *****************************************************************************/ + +#include <string.h> +#include <stdlib.h> +#include "dbnamedobject.hh" +#include "dbobject.hh" +#include "raslib/rmdebug.hh" + +// Beware: keep this value less or equal to STRING_MAXLEN in externs.h! +#define MAXNAMELENGTH_CONST 200 +short DBNamedObject::MAXNAMELENGTH = MAXNAMELENGTH_CONST; + +const char* DBNamedObject::defaultName="unamed object\0"; + +void +DBNamedObject::printStatus(unsigned int level, std::ostream& stream) const +{ + DBObject::printStatus(level, stream); + stream << " Name: " << myName; +} + +DBNamedObject::DBNamedObject(const OId& id) throw (r_Error) + : DBObject(id), + myName(NULL), + myNameSize(0) +{ + RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(" << myOId << ")"); +} + +DBNamedObject::DBNamedObject() + : DBObject(), + myNameSize(0), + myName(NULL) +{ + RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject()"); + setName(defaultName); +} + +DBNamedObject::DBNamedObject(const DBNamedObject& old) + : DBObject(old), + myNameSize(0), + myName(NULL) +{ + RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(const DBNamedObject& old)"); + setName(old.getName()); +} + +DBNamedObject::DBNamedObject(const char* name) + : DBObject(), + myNameSize(0), + myName(NULL) +{ + RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(" << name << ")"); + setName(name); +} + +DBNamedObject::DBNamedObject(const OId& id, const char* name) + : DBObject(id), + myNameSize(0), + myName(NULL) +{ + RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "DBNamedObject(" << myOId << ", " << name << ")"); + setName(name); +} + +DBNamedObject::~DBNamedObject() +{ + RMDBGENTER(9, RMDebug::module_adminif, "DBNamedObject", "~DBNamedObject() " << myOId); + if (myName) + { + free(myName); + myName = NULL; + } + myNameSize = 0; + RMDBGEXIT(9, RMDebug::module_adminif, "DBNamedObject", "~DBNamedObject() " << myOId); +} + +DBNamedObject& +DBNamedObject::operator=(const DBNamedObject& old) +{ + RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "operator=(" << old.getName() << ") " << myName); + if (this != &old) + { + DBObject::operator=(old); + setName(old.getName()); + } + return *this; +} + +const char* +DBNamedObject::getName() const +{ + RMDBGONCE(9, RMDebug::module_adminif, "DBNamedObject", "getName() " << myName); + return myName; +} + +void +DBNamedObject::setName(const char* newname) +{ + RMDBGENTER(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << newname << ")"); + if (myName) + { + RMDBGMIDDLE(10, RMDebug::module_adminif, "DBNamedObject", "myName\t:" << myName); + free(myName); + myName=NULL; + } + int len = strlen(newname); + if (len > MAXNAMELENGTH) + len = MAXNAMELENGTH; + myName = (char*)mymalloc((len + 1) * sizeof(char)); + myNameSize = (len + 1) * sizeof(char); + strncpy(myName, newname, len); + *(myName + len) = 0; + RMDBGEXIT(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << myName << ")"); +} + +void +DBNamedObject::setName(const short length, const char* data) +{ + RMDBGENTER(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << length << ", data ) " << myOId); + if (myName) + { + RMDBGMIDDLE(10,RMDebug::module_adminif, "DBNamedObject", "myName\t:" << myName); + free(myName); + myName=NULL; + } + int len = 0; + if (length > MAXNAMELENGTH) + len = MAXNAMELENGTH; + else + len = length; + myName = (char*)mymalloc((len + 1) * sizeof(char)); + myNameSize = (len + 1) * sizeof(char); + strncpy(myName, data, len); + *(myName + len) = 0; + RMDBGMIDDLE(10,RMDebug::module_adminif, "DBNamedObject", "myName\t:" << myName); + RMDBGEXIT(9, RMDebug::module_adminif, "DBNamedObject", "setName(" << length << ", data ) " << myOId); +} + +r_Bytes +DBNamedObject::getMemorySize() const +{ + return sizeof(char) * myNameSize + DBObject::getMemorySize() + sizeof(unsigned short); +} + diff --git a/reladminif/dbnamedobject.hh b/reladminif/dbnamedobject.hh new file mode 100644 index 0000000..654547c --- /dev/null +++ b/reladminif/dbnamedobject.hh @@ -0,0 +1,121 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _DBNAMEDOBJECT_HH_ +#define _DBNAMEDOBJECT_HH_ + +class DBObject; +class DBNamedObject; + +#include "dbobject.hh" + +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: +Has functionality for setting the name of itsself from VARCHAR structures. +Takes care of too long names. +Implements set/getName functionality. +*/ + +class DBNamedObject : public DBObject + { + public: + DBNamedObject(); + /*@Doc: + sets Name to defaultName + */ + + DBNamedObject(const OId& id) throw (r_Error); + /*@Doc: + only initializes itself + */ + + DBNamedObject(const DBNamedObject& old); + /*@Doc: + sets myName to the name of the old object + */ + + DBNamedObject(const char* name); + /*@Doc: + sets myName to name + */ + + DBNamedObject(const OId& id, const char* name); + /*@Doc: + sets myName to name and calls DBObject(OId). this is needed by MDDSet. + */ + + virtual ~DBNamedObject(); + /*@Doc: + frees myName + */ + + const char* getName() const; + /*@Doc: + returns a pointer to myName. + */ + + static short MAXNAMELENGTH; + /*@Doc: + the maximum length of a name. + */ + + DBNamedObject& operator=(const DBNamedObject& old); + /*@Doc: + takes care of the name + */ + + virtual r_Bytes getMemorySize() const; + /*@Doc: + Should be revised not to include attribute sizes + */ + + virtual void printStatus(unsigned int level = 0, std::ostream& stream = std::cout) const; + /*@Doc: + prints the status of DBObject + Name: myName + */ + + protected: + + void setName(const char* newname); + /*@Doc: + renames the object + */ + + void setName(const short length, const char* data); + /*@Doc: + sets the name from a VARCHAR structure + */ + + char* myName; + /*@Doc: + the name of the object + */ + + unsigned short myNameSize; + /*@Doc: + the size of the name + */ + + static const char* defaultName; + }; + +#endif diff --git a/reladminif/dbobject.cc b/reladminif/dbobject.cc new file mode 100644 index 0000000..eabe794 --- /dev/null +++ b/reladminif/dbobject.cc @@ -0,0 +1,459 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * Code with embedded SQL for relational DBMS + * + * + * COMMENTS: + * none + * + ***********************************************************************/ + +// mainly for ostringstream: +#include <iostream> +#include <string> +#include <sstream> +#include <fstream> +#include <cstring> + +using namespace std; + +#include "objectbroker.hh" +#include "dbobject.hh" +#include "adminif.hh" +#include "externs.h" +#include "raslib/rmdebug.hh" +#include "raslib/error.hh" +#include "eoid.hh" + +#ifdef RMANBENCHMARK +RMTimer DBObject::readTimer = RMTimer("DBObject","read"); +RMTimer DBObject::updateTimer = RMTimer("DBObject","update"); +RMTimer DBObject::insertTimer = RMTimer("DBObject","insert"); +RMTimer DBObject::deleteTimer = RMTimer("DBObject","delete"); +#endif + +const char* +BinaryRepresentation::fileTag = "RMAN"; + +void +DBObject::printStatus(unsigned int level, std::ostream& stream) const + { + char* indent = new char[level*2 +1]; + for (int j = 0; j < level*2 ; j++) + indent[j] = ' '; + indent[level*2] = '\0'; + + stream << indent; + stream << myOId; + delete[] indent; + indent=0; + } + +r_Bytes +DBObject::getTotalStorageSize() const + { + return 0; + } + +r_Bytes +DBObject::getMemorySize() const + { + return sizeof(DBObject); + } + +void +DBObject::setCached(bool newCached) + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "setCached(" << (int)newCached << ") " << myOId); + _isCached = newCached; + } + +bool +DBObject::isCached() const + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "isCached()" << (int) _isCached) + return _isCached; + } + +void +DBObject::destroy() + { + RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "destroy() " << myOId); +#ifdef RMANDEBUG + OId tempid(myOId); +#endif + if (referenceCount == 0) + { + if (!_isCached) + { + //exception may be possible when !isModified() + if (!AdminIf::isReadOnlyTA()) + { + RMDBGMIDDLE(10, RMDebug::module_adminif, "DBObject", "deleting object " << myOId); + delete this;//is dynamic and may be deleted + } + else { + if (!_isPersistent) + { + RMDBGMIDDLE(10, RMDebug::module_adminif, "DBObject", "deleting object " << myOId); + //is dynamic and may be deleted + delete this; + } + } + } + } +#ifdef RMANDEBUG + RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "destroy() " << tempid); +#else + RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "destroy()"); +#endif + } + +void +DBObject::release() + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "release() "); + //no dynamic memory + } + +void DBObject::incrementReferenceCount(void) + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "incrementReferenceCount() " << referenceCount); + referenceCount++; + } + +void DBObject::decrementReferenceCount(void) + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "decrementReferenceCount() " <<referenceCount); + referenceCount--; + if (referenceCount == 0) + destroy(); + } + +int +DBObject::getReferenceCount(void) const + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "getReferenceCount() " <<referenceCount); + return referenceCount; + } + +//public: +DBObject::DBObject() + : _isInDatabase(false), + _isPersistent(false), + _isModified(true), + _isCached(false), + referenceCount(0), + objecttype(OId::INVALID), + myOId(0) + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "DBObject() " << myOId); + } + +DBObject::DBObject(const DBObject& old) + : _isInDatabase(old._isInDatabase), + _isPersistent(old._isPersistent), + _isModified(old._isModified), + _isCached(old._isCached), + referenceCount(old.referenceCount), + objecttype(old.objecttype), + myOId(old.myOId) + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "DBObject(const DBObject& old)" << myOId); + } + +//constructs an object and reads it from the database. the oid must match the type of the object. +//a r_Error::r_Error_ObjectUnknown is thrown when the oid is not in the database. +DBObject::DBObject(const OId& id) throw (r_Error) + : referenceCount(0), + _isCached(false), + myOId(id), + objecttype(id.getType()) + { + //flags must be set by readFromDb() + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "DBObject(" << myOId << ")"); + } + +DBObject& +DBObject::operator=(const DBObject& old) + { + RMDBGONCE(10, RMDebug::module_adminif, "DBObject", "operator=(" << old.myOId << ")"); + if (this != &old) + { + _isPersistent = old._isPersistent; + _isInDatabase = old._isInDatabase; + _isModified = old._isModified; + _isCached = old._isCached; + objecttype = old.objecttype; + myOId = old.myOId; + } + return *this; + } + +//setPersistent(true) makes the object persistent as soon as validate is called. +//a r_Error::r_Error_TransactionReadOnly is thrown when the transaction is readonly. +void +DBObject::setPersistent(bool newPersistent) throw (r_Error) + { + RMDBGENTER(6, RMDebug::module_adminif, "DBObject", "setPersistent(" << (int)newPersistent << ") " << myOId); + if (newPersistent) + {//make object persistent + if (!_isPersistent) + {//object is not persistent + if (!AdminIf::isReadOnlyTA()) + {//may be written to database + OId::allocateOId(myOId, objecttype); + _isPersistent = true; + _isModified = true; + ObjectBroker::registerDBObject(this); + RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: yes, was not persistent"); + } + else {//read only transaction + RMDBGEXIT(6, RMDebug::module_adminif, "DBObject", "ReadOnlyTransaction"); + RMInit::logOut << "DBObject::setPersistent() read only transaction" << endl; + throw r_Error(r_Error::r_Error_TransactionReadOnly); + } + } + else {//is already persitent + RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: yes, was already persistent"); + } + } + else {//delete the object from database + if (_isPersistent) + { + if (!AdminIf::isReadOnlyTA()) + {//may be deleted to database + RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: no, was persistent"); + _isPersistent = false; + _isModified = true; + } + else {//read only transaction + RMDBGEXIT(6, RMDebug::module_adminif, "DBObject", "ReadOnlyTransaction"); + RMInit::logOut << "DBObject::setPersistent() read only transaction" << endl; + throw r_Error(r_Error::r_Error_TransactionReadOnly); + } + } + else { + RMDBGMIDDLE(6, RMDebug::module_adminif, "DBObject", "persistent\t: no, was not persistent"); + } + } + RMDBGEXIT(6, RMDebug::module_adminif, "DBObject", "setPersistent(" << (int)newPersistent << ") " << myOId); + } + +//tells if an object is persistent. +bool +DBObject::isPersistent() const + { + RMDBGONCE(6, RMDebug::module_adminif, "DBObject", "isPersistent()" << (int)_isPersistent); + return _isPersistent; + } + +//writes the object to database/deletes it or updates it. +//a r_Error::r_Error_TransactionReadOnly is thrown when the transaction is readonly. +void +DBObject::validate() throw (r_Error) + { + RMDBGENTER(9, RMDebug::module_adminif, "DBObject", "validate() " << myOId); + if (_isModified) + { + if (!AdminIf::isReadOnlyTA()) + { + if (!AdminIf::isAborted()) + { + if (_isInDatabase) + { + if (_isPersistent) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBObject", "is persistent and modified and in database"); +#ifdef RMANBENCHMARK + updateTimer.resume(); +#endif + this->updateInDb(); +#ifdef RMANBENCHMARK + updateTimer.pause(); +#endif + } + else { + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBObject", "is not persistent and in database"); +#ifdef RMANBENCHMARK + deleteTimer.resume(); +#endif + this->deleteFromDb(); +#ifdef RMANBENCHMARK + deleteTimer.pause(); +#endif + } + } + else { + if (_isPersistent) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBObject", "is persistent and modified and not in database"); + +#ifdef RMANBENCHMARK + insertTimer.resume(); +#endif + this->insertInDb(); +#ifdef RMANBENCHMARK + insertTimer.pause(); +#endif + } + else { + //don´t do anything: not in db and not persistent + } + } + } + else { + //don´t do anything: is aborted + } + } + else { + //don´t do anything: is read only + } + } + else { + //don´t do anything: not modified + } + RMDBGEXIT(9, RMDebug::module_adminif, "DBObject", "validate() " << myOId); + } + +void +DBObject::setModified() throw (r_Error) + { + RMDBGENTER(8, RMDebug::module_adminif, "DBObject", "setModified() " << myOId); + if (!AdminIf::isReadOnlyTA()) + _isModified = true; + else { + RMDBGMIDDLE(5, RMDebug::module_adminif, "DBObject", "readonly transaction " << myOId); + //this happens really a lot. + //RMInit::logOut << "DBObject::setModified() read only transaction" << endl; + //throw r_Error(r_Error::r_Error_TransactionReadOnly); + _isModified = true; + } + RMDBGEXIT(8, RMDebug::module_adminif, "DBObject", "setModified() " << myOId); + } + +bool +DBObject::isModified() const + { + RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "isModified() " << (int)_isModified); + return _isModified; + } + +OId +DBObject::getOId() const + { + RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "getOId() " << myOId); + return myOId; + } + +EOId +DBObject::getEOId() const + { + RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "getEOId() " << myOId); + return EOId(myOId); + } + +OId::OIdType +DBObject::getObjectType() const + { + RMDBGONCE(8, RMDebug::module_adminif, "DBObject", "getObjectType() " << objecttype); + return objecttype; + } + +DBObject::~DBObject() + { + RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "~DBObject() " << myOId); + ObjectBroker::deregisterDBObject(myOId); + RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "~DBObject() " << myOId); + } + +void +DBObject::updateInDb() throw (r_Error) + { + RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "updateInDb() " << myOId); + _isModified = false; + _isInDatabase = true; + _isPersistent = true; + RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "updateInDb() " << myOId); + } + +//writes the object into the database. the object must not be in the database. +void +DBObject::insertInDb() throw (r_Error) + { + RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "insertInDb() " << myOId); + _isModified = false; + _isInDatabase = true; + _isPersistent = true; + RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "insertInDb() " << myOId); + } + +void +DBObject::deleteFromDb() throw (r_Error) + { + RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "deleteFromDb() " << myOId); + _isModified = false; + _isInDatabase = false; + _isPersistent = false; + RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "deleteFromDb() " << myOId); + } + +void +DBObject::readFromDb() throw (r_Error) + { + RMDBGENTER(10, RMDebug::module_adminif, "DBObject", "readFromDb() " << myOId); + _isPersistent = true; + _isModified = false; + _isInDatabase = true; + RMDBGEXIT(10, RMDebug::module_adminif, "DBObject", "readFromDb() " << myOId); + } + +BinaryRepresentation +DBObject::getBinaryRepresentation() const throw (r_Error) + { + RMInit::logOut << "getBinaryRepresentation() for " << objecttype << " not implemented" << endl; + throw r_Error(BINARYEXPORTNOTSUPPORTEDFOROBJECT); + } + +void +DBObject::setBinaryRepresentation(const BinaryRepresentation& br) throw (r_Error) + { + RMInit::logOut << "setBinaryRepresentation() for " << objecttype << " not implemented" << endl; + throw r_Error(BINARYIMPORTNOTSUPPORTEDFOROBJECT); + } + +char* +DBObject::getBinaryName() const + { + //if we use 64bit oids we have at most 20 digits + "_" + type + ostringstream o; + o << (int)objecttype << '_' << myOId.getCounter() << ".raw"; + const char* temp = o.str().c_str(); + char* retval = new char[strlen(temp) + 1]; + memcpy(retval, temp, strlen(temp) + 1); + return retval; + } diff --git a/reladminif/dbobject.hh b/reladminif/dbobject.hh new file mode 100644 index 0000000..80e3360 --- /dev/null +++ b/reladminif/dbobject.hh @@ -0,0 +1,291 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _DBOBJECT_HH_ +#define _DBOBJECT_HH_ + +class DBObject; +class EOId; + +template <class T> class DBRef; + +#include <iosfwd> + +#include "oidif.hh" +#include "raslib/mddtypes.hh" +#include "raslib/error.hh" +#include "binaryrepresentation.hh" + +#ifdef RMANBENCHMARK +#include "raslib/rmdebug.hh" +#endif + +typedef DBRef<DBObject> DBObjectId; + +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: +Base class for all persistent classes. it supplies functionality for reference counting, +management by ObjectBroker, modification management, cache size. + +a persistent DBObject has a unique OId. this oid identifies it in the database. +*/ + +class DBObject + { + public: + virtual void destroy(void); + /*@Doc: + deletes the object if and only if + the refence count is zero and + the object is not cached and + the transaction is not readonly. + */ + + int getReferenceCount(void) const; + /*@Doc: + Returns the number of references that exist for this object + */ + + void incrementReferenceCount(void); + /*@Doc: + Reference counting functions. These should be private with friend DBRef, but the compiler + doesn't allow friend template classes, only instances. Don't call directly, only DBRef + is allowed to. + */ + + void decrementReferenceCount(void); + /*@Doc: + Reference counting functions. These should be private with friend DBRef, but the compiler + doesn't allow friend template classes, only instances. Don't call directly, only DBRef + is allowed to. + */ + + virtual ~DBObject(); + /*@Doc: + deregisters this object with the ObjectBroker. + the oid is not invalidated to allow the ObjectBroker to kill it. + */ + + DBObject(); + /*@Doc: + initializes all attributes. the oid is set to 0. the objecttype is set to OId::INVALID. + */ + + DBObject(const DBObject& old); + /*@Doc: + clones all attributes. + */ + + DBObject(const OId& id) throw (r_Error); + /*@Doc: + initializes only referenceCount, myOId, objecttype. _isCached is set to 0. + Subclasses may contain a call to readFromDb which can throw a r_Error_ObjectUnknown + or database related exception. + */ + + virtual void setPersistent(bool newPersistent) throw (r_Error); + /*@Doc: + setPersistent(true) makes the object persistent as soon as validate is called. + a r_Error_TransactionReadOnly is thrown when the transaction is readonly. + setPersistent(false) deletes the object from the database as soon as validate is called. + if the state of the object changes in a read only transaction + (e.g. persistent->non persistent) a r_Error_TransactionReadOnly is thrown. + */ + + bool isPersistent() const; + /*@Doc: + tells if an object is persistent. + */ + + void validate() throw (r_Error); + /*@Doc: + writes the object to database/deletes it or updates it. + any r_Errors from insertInDb, updateInDb, deleteFromDb, readFromDb are passed to the + caller. + */ + + virtual void setModified() throw (r_Error); + /*@Doc: + marks this object dirty. + a r_Error_TransactionReadOnly should be thrown when the transaction is readonly. + this is because of o2 related stuff in dbmddobject. should be taken care of. + */ + + bool isModified() const; + /*@Doc: + tells if this object is dirty. + */ + + OId getOId() const; + /*@Doc: + returns the oid of this object + */ + + EOId getEOId() const; + /*@Doc: + returns the EOId of this object. + */ + + OId::OIdType getObjectType() const; + /*@Doc: + returns the type of this object (MDDSet, ...). objects which are not + yet persistent also return their object type. + */ + + DBObject& operator=(const DBObject& old); + /*@Doc: + clones all DBObject attributes except reference count. + */ + + bool isCached() const; + /*@Doc: + tells if this object is cached. + */ + + virtual void setCached(bool newCached); + /*@Doc: + + */ + + virtual r_Bytes getMemorySize() const; + /*@Doc: + returns the memory space used by this object. + */ + + virtual void printStatus(unsigned int level = 0, std::ostream& stream = std::cout) const; + /*@Doc: + prints the indent, OIdType, myOId as long and myOId as double. + */ + + virtual r_Bytes getTotalStorageSize() const; + /*@Doc: + returns the space taken up by this object in the database. + as dbobject has no persistent attributes it returns 0. + */ + + virtual BinaryRepresentation getBinaryRepresentation() const throw (r_Error); + /*@Doc: + returns the binary representation fit for storage in the database + */ + + virtual void setBinaryRepresentation(const BinaryRepresentation&) throw (r_Error); + /*@Doc: + set the objects state from the binary represenation + */ + + virtual char* getBinaryName() const; + /*Doc: + create the name for binary represenation from the oid + */ + +#ifdef RMANBENCHMARK + static RMTimer readTimer; + + static RMTimer updateTimer; + + static RMTimer insertTimer; + + static RMTimer deleteTimer; +#endif + + protected: + virtual void release(); + /*@Doc: + releases all dynamic memory (references to other persistent obkjects). + this is needed for cross transactional caches. + dbobject does not have any dynamic memory. + */ + + virtual void readFromDb() throw (r_Error); + /*@Doc: + reads the object from database. myOId must be set!!! + a r_Error_ObjectUnknown is thrown when the oid is not in the database. + */ + + virtual void insertInDb() throw (r_Error); + /*@Doc: + writes the object into the database. the object must not be in the database. + a r_Error_TransactionReadOnly is thrown when the transaction is readonly. + this implementation checks for readOnlyTA + */ + + virtual void deleteFromDb() throw (r_Error); + /*@Doc: + deletes an object in the database. + a r_Error_TransactionReadOnly is thrown when the transaction is readonly. + this implementation checks for readOnlyTA + */ + + virtual void updateInDb() throw (r_Error); + /*@Doc: + updates an existing object in the database + a r_Error_TransactionReadOnly is thrown when the transaction is readonly. + this implementation checks for readOnlyTA + */ + + bool _isPersistent; + /*@Doc: + tells, if this object should be in the database or not. + */ + + bool _isInDatabase; + /*@Doc: + tells, if this object is already in the database. + */ + + bool _isModified; + /*@Doc: + tells, if this object has changed an should be updated in the database. + */ + + bool _isCached; + /*@Doc: + tells , if this objects is cached or not + */ + + OId myOId; + /*@Doc: + the oid of this object. is set by setPersistent(1) or by the constructor + of optional persistent objects (types). + */ + + OId::OIdType objecttype; + /*@Doc: + the type of this object. needed by setPersistent(1) to allocate the correct oid. + */ + + int referenceCount; + /*@Doc: + The number of references that exist for this file. Use get_reference() for reading + its value from derived classes. Modified by incr_reference and decr_reference. + */ + + private: + + void sharedObjectInit(void); + /*@Doc: + Initialization code shared by all constructors. + does not do anything. + */ + }; + +#endif diff --git a/reladminif/dbobjectiditerator.cc b/reladminif/dbobjectiditerator.cc new file mode 100644 index 0000000..17889be --- /dev/null +++ b/reladminif/dbobjectiditerator.cc @@ -0,0 +1,103 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "dbobjectiditerator.hh" +#include "objectbroker.hh" +#include "dbref.hh" +#include "raslib/rmdebug.hh" + +template<class T> +DBObjectIdIterator<T>::DBObjectIdIterator(const DBObjectIdIterator<T>& oidlist) + : mySet(NULL), + counter(0) + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "DBObjectIdIterator(const DBObjectIdIterator<T>&)"); + mySet = oidlist.mySet; + myIter = mySet->begin(); + } + +template<class T> +DBObjectIdIterator<T>::DBObjectIdIterator(const std::set<DBRef<T>, std::less<DBRef<T> > >& oidlist) + : mySet(NULL), + counter(0) + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "DBObjectIdIterator(OIdSet)"); + mySet = (std::set<DBRef<T>, std::less<DBRef<T> > >*)&oidlist; + myIter = mySet->begin(); + } + +template<class T> void +DBObjectIdIterator<T>::reset() + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator","reset()"); + myIter = mySet->begin(); + counter = 0; + } + +template<class T> bool +DBObjectIdIterator<T>::not_done() const + { + RMDBGENTER(7, RMDebug::module_adminif, "DBObjectIdIterator","not_done()"); + bool retval = false; + if (myIter == mySet->end()) + { + retval = false; + } + else { + if (mySet->empty()) + { + retval = false; + } + else { + if (counter == mySet->size()) + retval = false; + else + retval = true; + } + } + RMDBGEXIT(7, RMDebug::module_adminif, "DBObjectIdIterator","not_done() " << retval); + return retval; + } + +template<class T> void +DBObjectIdIterator<T>::advance() + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator","advance() " << counter); + myIter++; + counter++; + } + +template<class T> DBRef<T> +DBObjectIdIterator<T>::get_element() const + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "get_element() " << (*myIter).getOId()); + return (*myIter); + } + +template<class T> +DBObjectIdIterator<T>::~DBObjectIdIterator() + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIdIterator", "~DBObjectIdIterator()"); + mySet = NULL; + counter = 0; + } + diff --git a/reladminif/dbobjectiditerator.hh b/reladminif/dbobjectiditerator.hh new file mode 100644 index 0000000..bb6ba78 --- /dev/null +++ b/reladminif/dbobjectiditerator.hh @@ -0,0 +1,108 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/* + * 2007-may-10 CJ fixed compilation errors (gcc 4.1) +*/ + +#ifndef _DBOBJECtIdIterATOR_HH_ +#define _DBOBJECtIdIterATOR_HH_ + +template <class T> class DBObjectIdIterator; +template <class T> class DBRef; +class ObjectBroker; + +#include "lists.h" +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: + +this object gets a set of oids. when an oid is accessed the iterator returns a DBRef to the oid. + +*/ + + +template<class T> +class DBObjectIdIterator + { + public: + DBObjectIdIterator(const std::set<DBRef<T>, std::less<DBRef<T> > >& oidlist); + /*@Doc: + constructs a new Iterator. the OIdSet will be deleted by the DBOBjectIdIterator. + there may be oids of objects with other classes present. you should be carefull + when using this feature - as in mddtypes/mddbasetypes/mdddim/domtypes + */ + + DBObjectIdIterator(const DBObjectIdIterator<T>& it); + /*@Doc: + */ + + ~DBObjectIdIterator(); + /*@Doc: + deletes the OIdSet passed to it in the constructor + */ + + void reset(); + /*@Doc: + resets the iterator to the beginning + */ + + bool not_done() const; + /*@Doc: + checks if there are more elements + */ + + void advance(); + /*@Doc: + advances the iterator one entry + */ + + DBRef<T> get_element() const; + /*@Doc: + returns an dbref<object> + */ + + private: + typename std::set<DBRef<T>, std::less<DBRef<T> > >::iterator myIter; + /*@Doc: + internal pointer where the iterator is + */ + + std::set<DBRef<T>, std::less<DBRef<T> > >* mySet; + /*@Doc: + the actual list which is used to lookup objects by the objectbroker + */ + + unsigned int counter; + /*@Doc: + holds the actual position in set + */ + }; + +#ifdef EARLY_TEMPLATE +#ifdef __EXECUTABLE__ +#include "dbobjectiditerator.cc" +#endif +#endif + +#endif + + diff --git a/reladminif/dbobjectiterator.cc b/reladminif/dbobjectiterator.cc new file mode 100644 index 0000000..69517b5 --- /dev/null +++ b/reladminif/dbobjectiterator.cc @@ -0,0 +1,104 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "dbobjectiterator.hh" +#include "objectbroker.hh" +#include "dbref.hh" +#include "raslib/rmdebug.hh" + +template<class T> +DBObjectIterator<T>::DBObjectIterator(const DBObjectIterator<T>& oidlist) + : mySet(NULL), + counter(0) + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "DBObjectIterator(const DBObjectIterator<T>&)"); + mySet = new OIdSet(*(oidlist.mySet)); + myIter = mySet->begin(); + } + +template<class T> +DBObjectIterator<T>::DBObjectIterator(const OIdSet& oidlist) + : mySet(NULL), + counter(0) + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "DBObjectIterator(OIdSet)"); + mySet = new OIdSet(oidlist); + myIter = mySet->begin(); + } + +template<class T> void +DBObjectIterator<T>::reset() + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator","reset()"); + myIter = mySet->begin(); + counter = 0; + } + +template<class T> bool +DBObjectIterator<T>::not_done() const + { + RMDBGENTER(7, RMDebug::module_adminif, "DBObjectIterator","not_done()"); + bool retval = false; + if (myIter == mySet->end()) + { + retval = false; + } + else { + if (mySet->empty()) + { + retval = false; + } + else { + if (counter == mySet->size()) + retval = false; + else + retval = true; + } + } + RMDBGEXIT(7, RMDebug::module_adminif, "DBObjectIterator","not_done() " << retval); + return retval; + } + +template<class T> void +DBObjectIterator<T>::advance() + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator","advance() " << counter); + myIter++; + counter++; + } + +template<class T> DBRef<T> +DBObjectIterator<T>::get_element() const + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "get_element() " << *myIter << " " << (*myIter).getType()); + return DBRef<T>(*myIter); + } + +template<class T> +DBObjectIterator<T>::~DBObjectIterator() + { + RMDBGONCE(7, RMDebug::module_adminif, "DBObjectIterator", "~DBObjectIterator()"); + delete mySet; + mySet = NULL; + counter = 0; + } + diff --git a/reladminif/dbobjectiterator.hh b/reladminif/dbobjectiterator.hh new file mode 100644 index 0000000..4f04370 --- /dev/null +++ b/reladminif/dbobjectiterator.hh @@ -0,0 +1,104 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _DBOBJECTITERATOR_HH_ +#define _DBOBJECTITERATOR_HH_ + +template <class T> class DBObjectIterator; +template <class T> class DBRef; +class ObjectBroker; + +#include "lists.h" +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: + +this object gets a set of oids. when an oid is accessed the iterator returns a DBRef to the oid. + +*/ + + +template<class T> +class DBObjectIterator + { + public: + DBObjectIterator(const OIdSet& oidlist); + /*@Doc: + constructs a new Iterator. the OIdSet will be deleted by the DBOBjectIterator. + there may be oids of objects with other classes present. you should be carefull + when using this feature - as in mddtypes/mddbasetypes/mdddim/domtypes + */ + + DBObjectIterator(const DBObjectIterator<T>& it); + /*@Doc: + */ + + ~DBObjectIterator(); + /*@Doc: + deletes the OIdSet passed to it in the constructor + */ + + void reset(); + /*@Doc: + resets the iterator to the beginning + */ + + bool not_done() const; + /*@Doc: + checks if there are more elements + */ + + void advance(); + /*@Doc: + advances the iterator one entry + */ + + DBRef<T> get_element() const; + /*@Doc: + returns an dbref<object> + */ + + private: + OIdSet::iterator myIter; + /*@Doc: + internal pointer where the iterator is + */ + + OIdSet* mySet; + /*@Doc: + the actual list which is used to lookup objects by the objectbroker + */ + + unsigned int counter; + /*@Doc: + holds the actual position in set + */ + }; + +#ifdef EARLY_TEMPLATE +#ifdef __EXECUTABLE__ +#include "dbobjectiterator.cc" +#endif +#endif + +#endif + + diff --git a/reladminif/dbref.cc b/reladminif/dbref.cc new file mode 100644 index 0000000..1012371 --- /dev/null +++ b/reladminif/dbref.cc @@ -0,0 +1,874 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * DBRef is a smart pointer for managing objects derived from + * the DbObject class. + * + * + * COMMENTS: + * + ************************************************************/ + + +#include "dbref.hh" +#include <iostream> +#include <stdio.h> +#include "raslib/rmdebug.hh" +#include "objectbroker.hh" +#include "indexmgr/indexds.hh" +#include "relindexif/dbrcindexds.hh" +#include "relindexif/dbtcindex.hh" +#include "indexmgr/hierindexds.hh" +#include "debug/debug.hh" + +template <class T> bool +DBRef<T>::pointerCaching = true; + +/*for testing +bool +DBRef<BLOBTile>::pointerCaching = false; + +bool +DBRef<InlineTile>::pointerCaching = false; + +bool +DBRef<DBTile>::pointerCaching = false; +*/ + +template <class T> void +DBRef<T>::setPointerCaching(bool useIt) + { + RMDBGONCE(10, RMDebug::module_adminif, "DBRef", "setPointerCaching(" << useIt << ") " << pointerCaching ); + pointerCaching = useIt; + } + +template <class T> bool +DBRef<T>::getPointerCaching() + { + RMDBGONCE(10, RMDebug::module_adminif, "DBRef", "getPointerCaching() " << pointerCaching ); + return pointerCaching; + } + +template <class T> +DBRef<T>::DBRef(void) + : object(0), + objId(DBOBJID_NONE), + pointerValid(false) + { + RMDBGONCE(11, RMDebug::module_adminif, "DBRef", "DBRef()"); + } + + +template <class T> +DBRef<T>::DBRef(const OId &id) + : object(0), + pointerValid(false), + objId(id) + { + RMDBGONCE(11, RMDebug::module_adminif, "DBRef", "DBRef(" << id << ")"); + } + + +template <class T> +DBRef<T>::DBRef(double id) + : object(0), + pointerValid(false), + objId(id) + { + RMDBGONCE(11, RMDebug::module_adminif, "DBRef", "DBRef(double " << id << ")"); + } + + +template <class T> +DBRef<T>::DBRef(const DBRef<T> &src) + : object(0), + pointerValid(src.pointerValid), + objId(src.objId) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "DBRef(const DBRef) src.OId=" << src.objId); + if (pointerCaching) + { + if (src.object) + { + object = src.object; + objId = object->getOId(); + object->incrementReferenceCount(); + } + } + else { + if (pointerValid && src.object) + { + object = src.object; + } + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "DBRef(const DBRef) " << objId); + } + + +template <class T> +DBRef<T>::DBRef(T *ptr) + : object(ptr), + pointerValid(true), + objId(DBOBJID_NONE) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "DBRef(const T* " << ptr << ")"); + + if (object != 0) + { + objId = object->getOId(); + object->incrementReferenceCount(); + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "DBRef(T* " << ptr->getOId() << ")"); + } + else { + pointerValid = false; + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "DBRef(T* 0) " << objId); + } + } + + +template <class T> +DBRef<T>::~DBRef(void) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "~DBRef() " << objId); + if ((object != 0) && pointerCaching) + object->decrementReferenceCount(); + object = 0; + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "~DBRef() " << objId); + } + +template <class T> +bool DBRef<T>::operator<(const DBRef<T>& other) const + { + RMDBGENTER(3, RMDebug::module_adminif, "DBRef", "DBRef<T>::operator<(" << other.objId << ", " << (r_Ptr)other.object << ") " << objId << ", " << (r_Ptr)object); + int ret = operator==(other); + return (ret == -1); + } + +template <class T> +bool operator< (const DBRef<T> &me, const DBRef<T> &him) + { + RMDBGENTER(3, RMDebug::module_adminif, "DBRef", "operator<({" << me.getOId() << "}, {" << him.getOId() << "})"); + return me.operator<(him); + } + +template <class T> +int DBRef<T>::operator==(const DBRef<T> &src) const + { + RMDBGENTER(3, RMDebug::module_adminif, "DBRef", "operator==(" << src.objId << ", " << (r_Ptr)src.object << ") " << objId << ", " << (r_Ptr)object); + int retval = 0; + if (isInitialised()) + { + if (src.isInitialised()) + { + if (object) + { + if (object->isPersistent()) + {//this persistent + if (src.object) + { + if (src.object->isPersistent()) + { + if (object->getOId() < src.object->getOId()) + retval = -1; + else + if (object->getOId() > src.object->getOId()) + retval = +1; + //else == -> 0 + } + else {//src is transient + retval = +1; + } + } + else {//src is persistent + if (object->getOId() < src.objId) + { + retval = -1; + } + else { + if (object->getOId() > src.objId) + retval = +1; + //else == -> 0 + } + } + } + else {//this transient + if (src.object) + { + if (src.object->isPersistent()) + { + retval = -1; + } + else {//src is transient + if (object < src.object) + retval = -1; + else + if (object > src.object) + retval = +1; + //else == -> 0 + } + } + else {//src is persistent + retval = -1; + } + } + } + else {//this is persistent + if (src.object) + { + if (src.object->isPersistent()) + { + if (objId < src.object->getOId()) + { + retval = -1; + } + else { + if (objId > src.object->getOId()) + retval = +1; + //else == -> 0 + } + + } + else {//src not persistent + retval = +1; + } + } + else {//src is persistent + if (objId < src.objId) + { + retval = -1; + } + else { + if (objId > src.objId) + retval = +1; + //else == -> 0 + } + } + } + } + else { + retval = +1; + } + } + else { + if (src.isInitialised()) + { + retval = -1; + } + //else is 0 + } + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator==(" << src.objId << ") " << retval); + return retval; + } + + +template <class T> +DBRef<T> &DBRef<T>::operator=(const DBRef<T> &src) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator=(" << src.objId << ") " << objId); + if ((object != 0) && pointerCaching) + { + object->decrementReferenceCount(); + } + object = src.object; + pointerValid = src.pointerValid; + objId = src.objId; + if (pointerCaching) + { + if (object) + { + objId = object->getOId(); + object->incrementReferenceCount(); + } + } + else { + if (object && pointerValid) + objId = object->getOId(); + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator=(" << src.objId << ") " << objId); + return *this; + } + + +template<class T> +DBRef<T> &DBRef<T>::operator=(T *ptr) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator=( at " << ptr << " ) " << objId); + if ((object != 0) && pointerCaching) + object->decrementReferenceCount(); + + object = ptr; + if (object == 0) + { + objId = DBOBJID_NONE; + pointerValid = false; + } + else { + objId = object->getOId(); + object->incrementReferenceCount(); + pointerValid = true; + } + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator=( at " << ptr << " ) " << objId); + return *this; + } + + +template <class T> +T &DBRef<T>::operator *(void) throw ( r_Error ) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator*() " << objId); + + if (is_null()) + { + TALK( "DBRef::operator*(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator*() " << objId); + return *object; + } + + +template <class T> +const T &DBRef<T>::operator *(void) const throw ( r_Error ) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator*() const " << objId); + + if (is_null()) + { + TALK( "DBRef::operator*(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator*() " << objId); + return *object; + } + + +#ifndef __GNUG__ + +template <class T> +T &DBRef<T>::operator[](int idx) const throw(r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator[](" << idx << ") " << objId); + + if (is_null()) + { + TALK( "DBRef::operator[](): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator[](" << idx << ") " << objId); + return *((this + idx).object); + } + +#endif + +template <class T> +T *DBRef<T>::operator->(void) throw(r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator->() " << objId); + + if (is_null()) + { + TALK( "DBRef::operator->(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator->() " << objId); + return object; + } + + +template <class T> +const T *DBRef<T>::operator->(void) const throw(r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator->() const " << objId); + + if (is_null()) + { + TALK( "DBRef::operator->(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator->() const " << objId); + return object; + } + + +template <class T> +T *DBRef<T>::ptr(void) throw(r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId); + + if (is_null()) + { + TALK( "DBRef::ptr(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId); + return object; + } + + +template <class T> +const T *DBRef<T>::ptr(void) const throw(r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId); + + if (is_null()) + { + TALK( "DBRef::ptr(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "ptr() " << objId); + return object; + } + + +template <class T> +DBRef<T>::operator T*() throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator T*() " << objId); + + if (is_null()) + { + TALK( "DBRef::T*(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator T*() " << objId); + return object; + } + + +template <class T> +DBRef<T>::operator const T*() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator const T*() const" << objId); + + if (is_null()) + { + TALK( "DBRef::T*(): object not found " << objId); + RMDBGMIDDLE(2, RMDebug::module_adminif, "DBRef", "object was not found " << objId); + r_Error err = r_Error(r_Error::r_Error_RefNull); + throw err; + } + + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator const T*() " << objId); + return object; + } + + +template <class T> +OId DBRef<T>::getOId(void) const + { + if (object && pointerCaching) + ((DBRef<T>)*this).objId = object->getOId(); + return objId; + } + +template <class T> +void DBRef<T>::delete_object(void) + { + if (!is_null()) + { + object->setPersistent(false); + object->decrementReferenceCount(); + object = 0; + objId = DBOBJID_NONE; + } + else { + r_Error err; + if (objId.getType() == OId::INVALID) + { + err = r_Error(r_Error::r_Error_OIdInvalid); + } + else { + err = r_Error(r_Error::r_Error_ObjectUnknown); + } + RMDBGONCE(0, RMDebug::module_adminif, "DBRef", "delete_object() " << objId << " not ok") + throw err; + } + } + +template <class T> +bool DBRef<T>::isInitialised() const + { + bool retval=false; + if (object) + retval=true; + else { + if (objId.getType() != OId::INVALID) + retval=true; + } + return retval; + } + +template <class T> +bool DBRef<T>::is_valid(void) const + { + bool retval=false; + if (!is_null()) + retval=true; + return retval; + } + + +template <class T> +void DBRef<T>::release() + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "release() " << objId); + if ((object != 0) && pointerCaching) + { + object->decrementReferenceCount(); + } + object = 0; + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "release() " << objId); + } + + +template <class T> +DBRef<T>::operator DBRef<DBObject>() const + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBObject>() " << objId); + if (object && pointerCaching) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBObject>(" << object << ") " << objId); + return DBRef<DBObject>(object); + } + else { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBObject>(" << objId << ") " << objId); + return DBRef<DBObject>(objId); + } + } + +template <class T> +DBRef<T>::operator DBRef<InlineTile>() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() " << objId); + if (object && pointerCaching) + { + if (object->getObjectType() == OId::INLINETILEOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() " << objId); + return DBRef<InlineTile>((InlineTile*)object); + } + } + else { + if (objId.getType() == OId::INLINETILEOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() " << objId); + return DBRef<InlineTile>(objId); + } + } + TALK( "DBRef::<InlineTile>(): operator mismatch" << objId); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<InlineTile>() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + +template <class T> +DBRef<T>::operator DBRef<DBTile>() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() " << objId << "; object=" << (long) object ); + TALK( "DBRef::DBRef<DBTile>(): object=" << (long) object ); + if (object && pointerCaching) + { + if ((object->getObjectType() == OId::BLOBOID) || (object->getObjectType() == OId::INLINETILEOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() " << objId); + return DBRef<DBTile>((DBTile*)object); + } + } + else { + if ((objId.getType() == OId::BLOBOID) || (objId.getType() == OId::INLINETILEOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() " << objId); + return DBRef<DBTile>(objId); + } + } + if (object) { TALK( "DBRef::DBRef<DBTile>(): object->getObjectType()=" << object->getObjectType() ); } + TALK( "DBRef::DBRef<DBTile>(): objId->getObjectType()=" << objId.getType() ); + TALK( "DBRef::DBRef<DBTile>(): operator mismatch" << objId ); + if (object) { RMDBGMIDDLE(0, RMDebug::module_adminif, "DBRef", "object->getObjectType()=" << object->getObjectType() ); } + RMDBGMIDDLE(0, RMDebug::module_adminif, "DBRef", "objId->getObjectType()=" << objId.getType() ); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTile>() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + +template <class T> +DBRef<T>::operator DBRef<BLOBTile>() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() " << objId); + if (object && pointerCaching) + { + if (object->getObjectType() == OId::BLOBOID || (object->getObjectType() == OId::INLINETILEOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() " << objId); + return DBRef<BLOBTile>((BLOBTile*)object); + } + } + else { + if ((objId.getType() == OId::BLOBOID) || (objId.getType() == OId::INLINETILEOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() " << objId); + return DBRef<BLOBTile>(objId); + } + } + TALK( "DBRef::DBRef<BLOBTile>(): operator mismatch" << objId); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<BLOBTile>() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + +template <class T> +DBRef<T>::operator DBRef<DBTCIndex>() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() " << objId); + if (object && pointerCaching) + { + if (object->getObjectType() == OId::DBTCINDEXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() " << objId); + return DBRef<DBTCIndex>((DBTCIndex*)object); + } + } + else { + if (objId.getType() == OId::DBTCINDEXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() " << objId); + return DBRef<DBTCIndex>(objId); + } + } + TALK( "DBRef::DBRef<DBTCIndex>(): operator mismatch" << objId); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBTCIndex>() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + +template <class T> +DBRef<T>::operator DBRef<DBHierIndex>() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() " << objId); + if (object && pointerCaching) + { + if ((object->getObjectType() == OId::MDDHIERIXOID) || (object->getObjectType() == OId::DBTCINDEXOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() " << objId); + return DBRef<DBHierIndex>((DBHierIndex*)object); + } + } + else { + if ((objId.getType() == OId::MDDHIERIXOID) || (objId.getType() == OId::DBTCINDEXOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() " << objId); + return DBRef<DBHierIndex>(objId); + } + } + TALK( "DBRef::DBRef<DBHierIndex>(): operator mismatch" << objId); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBHierIndex>() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + + +template <class T> +DBRef<T>::operator DBRef<DBRCIndexDS>() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() " << objId); + if (object && pointerCaching) + { + if (object->getObjectType() == OId::MDDRCIXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() " << objId); + return DBRef<DBRCIndexDS>((DBRCIndexDS*)object); + } + } + else { + if (objId.getType() == OId::MDDRCIXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() " << objId); + return DBRef<DBRCIndexDS>(objId); + } + } + TALK( "DBRef::DBRef<DBRCIndexDS>(): operator mismatch" << objId); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator DBRef<DBRCIndexDS>() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + + +template <class T> +DBRef<T>::operator HierIndexDS*() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator HierIndexDS*() " << objId); + if (object && pointerCaching) + { + if ((object->getObjectType() == OId::MDDHIERIXOID) || (object->getObjectType() == OId::DBTCINDEXOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator HierIndexDS*() " << objId); + return (HierIndexDS*)object; + } + } + else { + if (objId.getType() == OId::MDDHIERIXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBHierIndexId" << objId); + DBRef<DBHierIndex> t(objId); + return (HierIndexDS*)t.ptr(); + } + else { + if (objId.getType() == OId::DBTCINDEXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBTCIndexId" << objId); + DBRef<DBTCIndex> t(objId); + return (HierIndexDS*)t.ptr(); + } + } + } + TALK( "DBRef::HierIndexDS*(): operator mismatch" << objId); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator HierIndexDS*() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + + +template <class T> +DBRef<T>::operator IndexDS*() const throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() " << objId); + if (object && pointerCaching) + { + if ((object->getObjectType() == OId::MDDHIERIXOID) || (object->getObjectType() == OId::DBTCINDEXOID) || (object->getObjectType() == OId::MDDRCIXOID)) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() " << objId); + return (IndexDS*)object; + } + } + else { + if (objId.getType() == OId::MDDHIERIXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBHierIndexId" << objId); + DBRef<DBHierIndex> t(objId); + return (IndexDS*)t.ptr(); + } + else { + if (objId.getType() == OId::DBTCINDEXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBTCIndexId" << objId); + DBRef<DBTCIndex> t(objId); + return (IndexDS*)t.ptr(); + } + else { + if (objId.getType() == OId::MDDRCIXOID) + { + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "operator IndexDS*() DBRCIndexId" << objId); + DBRef<DBRCIndexDS> t(objId); + return (IndexDS*)t.ptr(); + } + } + } + } + TALK( "DBRef::IndexDS*(): operator mismatch" << objId); + RMDBGEXIT(0, RMDebug::module_adminif, "DBRef", "operator IndexDS*() mismatch " << objId); + throw r_Error(r_Error::r_Error_DatabaseClassMismatch); + } + + +template <class T> +bool DBRef<T>::is_null(void) const + { + RMDBGENTER(11, RMDebug::module_adminif, "DBRef", "is_null() " << objId); + bool retval = false; + T* t = 0; + if (object == 0) + { + if (objId.getType() == OId::INVALID) + { + throw r_Error(r_Error::r_Error_OIdInvalid); + } + else { + try { + t = (T*)ObjectBroker::getObjectByOId(objId); + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "found object"); + t->incrementReferenceCount(); + ((DBRef<T>*)this)->object = t; + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "object is at: " << object << " found object was at: " << t); + } + catch (r_Error& err) + { + if (err.get_kind() == r_Error::r_Error_ObjectUnknown) + retval = true; + else + throw; + } + } + } + else { + if (pointerCaching == false) + { + if (pointerValid == false) + { + try { + t = (T*)ObjectBroker::getObjectByOId(objId); + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "found object"); + t->incrementReferenceCount(); + ((DBRef<T>*)this)->object = t; + RMDBGMIDDLE(11, RMDebug::module_adminif, "DBRef", "object is at: " << object << " found object was at: " << t); + } + catch (r_Error& err) + { + if (err.get_kind() == r_Error::r_Error_ObjectUnknown) + retval = true; + else + throw; + } + } + else { + //retval = false; is done in initialize + } + } + else { + //retval = false; is done in initialize + } + } + RMDBGEXIT(11, RMDebug::module_adminif, "DBRef", "is_null() " << objId << " " << retval); + return retval; + } diff --git a/reladminif/dbref.hh b/reladminif/dbref.hh new file mode 100644 index 0000000..35065a9 --- /dev/null +++ b/reladminif/dbref.hh @@ -0,0 +1,301 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * DBRef is a smart pointer for managing objects derived from + * the DbObject class. + * + * + * COMMENTS: + * + ************************************************************/ + + +#ifndef _DBREF_HH_ +#define _DBREF_HH_ + +class DBHierIndex; +class DBRCIndexDS; +class DBTCIndex; +class BLOBTile; +class InlineTile; +class DBTile; +class OId; +class DBObject; +class r_Error; +class IndexDS; +class HierIndexDS; +class DBMDDObj; + +template <class T> class DBRef; + +#include "oidif.hh" + +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: +DBRef is a smart pointer class operating on classes derived from DbObject. A smart +pointer to an object with a known id is created using DBRef<T>(id). The object +managed by a given smart pointer can be changed (rebinding) by using the assignment +operator. +All access methods may throw database related r_Errors. +*/ + +#define DBOBJID_NONE OId() + +template <class T> +class DBRef + { + public: + + DBRef(void); + /*@Doc: + Default constructor. Object must be assigned a value before the first dereferencing. + */ + + DBRef(const OId &id); + /*@Doc: + Id-constructor, binds smart pointer to object with the given id (must only be unique + within class T, not within all classes derived from DbObject). + */ + + DBRef(OId::OIdPrimitive id); + /*@Doc: + Id-constructor, binds smart pointer to object with the given id (must only be unique + within class T, not within all classes derived from DbObject). + */ + + DBRef(const DBRef<T> &src); + /*@Doc: + Copy-constructor, binds smart pointer to the same object src is bound to. + */ + + DBRef(T *ptr); + /*@Doc: + Object-constructor, binds smart pointer explicitly to the object ptr. + */ + + ~DBRef(void); + /*@Doc: + Destructor: decrements reference count for the object that was managed by this + smart pointer. + */ + + bool operator<(const DBRef<T>& other) const; + /*@Doc: + Returns true if me.operator==(other) returns -1 + */ + + int operator==(const DBRef<T> &src) const; + /*@Doc: + Comparison operator: + Returns: + -1 if this is not initialised and src is initialised + -1 if persistent and objId < src.objId + -1 if transient and src is persistent + -1 if transient and object < src.object + 0 if persistent and src persistent and myOId == src.myOId + 0 if transient and src transient and object == src.object + 0 if this is not initialised and src is not initialised + +1 if persistent and objId > src.objId + +1 if persistent and src is transient + +1 if transient and object > src.object + -1 if this is initialised and src is not initialised + */ + + DBRef<T> &operator=(const DBRef<T> &src); + /*@Doc: + Assignment operator: removes old binding and rebinds to the same object managed by src. + */ + + DBRef<T> &operator=(T *ptr); + /*@Doc: + Assignment operator: removes old binding and rebinds to object ptr. + */ + + T *operator->(void) throw (r_Error); + /*@Doc: + Dereferencing operator -> for accessing the managed object's members. + */ + + const T *operator->(void) const throw (r_Error); + /*@Doc: + Dereferencing operator -> for accessing the managed object's members. + */ + + T &operator*(void) throw (r_Error); + /*@Doc: + Dereferencing operator * for accessing the managed object. + */ + + const T &operator*(void) const throw (r_Error); + /*@Doc: + Dereferencing operator * for accessing the managed object. + */ + +#ifndef __GNUG__ + T &operator[](int idx) const throw (r_Error); + /*@Doc: + Dereferencing operator [] for accessing array objects. + */ +#endif + + T *ptr(void) throw (r_Error); + /*@Doc: + Returns pointer to managed object. + */ + + const T *ptr(void) const throw (r_Error); + /*@Doc: + Returns pointer to managed object. + */ + + OId getOId(void) const; + /*@Doc: + Returns id of managed object + */ + + void delete_object(void); + /*@Doc: + deletes the object from database if it is valid else throws an exception. + */ + + bool is_null(void) const; + /*@Doc: + Returns false if valid binding exists, true otherwise. + this method may instantiate an object from the database + */ + + bool is_valid(void) const; + /*@Doc: + Returns true if valid binding exists, false otherwise + */ + + bool isInitialised() const; + /*@Doc: + Returns true if OId is valid or the pointer is valid, false otherwise + */ + + void release(); + /*@Doc: + releases this DBRef pointer and refcount to its object + */ + + operator DBRef<DBObject>() const; + /*@Doc: + cast operator. works allways. + */ + + operator DBRef<BLOBTile>() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of OId::BLOBOID. + */ + + operator DBRef<DBTile>() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of OId::BLOBOID or OId::INLINETILEOID. + */ + + operator DBRef<InlineTile>() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of OId::INLINETILEOID. + */ + + operator DBRef<DBHierIndex>() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of OId::MDDHIERIXOID. + */ + + operator DBRef<DBTCIndex>() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of OId::INLINEIXOID. + */ + + operator DBRef<DBRCIndexDS>() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of OId::MDDRCIXOID. + */ + + operator IndexDS*() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of any valid index. + */ + + operator HierIndexDS*() const throw (r_Error); + /*@Doc: + cast operator. checks it the objects type is of any valid hierarchical index. + */ + + operator T*() throw (r_Error); + /*@Doc: + */ + + operator const T*() const throw (r_Error); + /*@Doc: + */ + + static void setPointerCaching(bool useIt); + /*@Doc: + Make the dbref store and use pointers. + If set to false the DBRef will always ask the objectbroker. + May be set at any time to false. + Only between transactions may it be set to true. + */ + + static bool getPointerCaching(); + /*@Doc: + returns pointerCaching + */ + + private: + + + mutable T *object; + /*@Doc: + Pointer to the managed object or 0 if no binding exists. + */ + + OId objId; + /*@Doc: + id of managed object. + */ + + bool pointerValid; + /*@Doc: + whenever a smartpointer is initiaised by a pointer, this attribute is set to true. + this is neccessary for disabled pointer caching. + */ + + static bool pointerCaching; + }; + +template <class T> bool operator< (const DBRef<T> &me, const DBRef<T> &him); + +#ifdef EARLY_TEMPLATE +#ifdef __EXECUTABLE__ +#include "dbref.cc" +#endif +#endif + +#endif diff --git a/reladminif/destroyable.hh b/reladminif/destroyable.hh new file mode 100644 index 0000000..316cfeb --- /dev/null +++ b/reladminif/destroyable.hh @@ -0,0 +1,52 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _DESTROYABLE_HH_ +#define _DESTROYABLE_HH_ + +/**************************************************************************** + * + * + * + * COMMENTS: + * + ****************************************************************************/ + +//@ManMemo: Module: {\bf reladminif} +/*@Doc: + +This is an interface class. It is abstract. It supplies the signature that +is required to allow other interfaces to be defined without a virtual destructor. +*/ + +class Destroyable + { + public: + virtual void destroy() = 0; + /*@Doc: + delete the object. + object may not be deleted when reference counting is enabled. + */ + + }; + +#endif diff --git a/reladminif/eoid.cc b/reladminif/eoid.cc new file mode 100644 index 0000000..f07497e --- /dev/null +++ b/reladminif/eoid.cc @@ -0,0 +1,231 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * EOId is optimized for maps that contain only EOId of one system/database. + * + * + * COMMENTS: + * + **********************************************************************/ + +#include "eoid.hh" +#include "externs.h" +#include "adminif.hh" +#include "databaseif.hh" +#include "raslib/rmdebug.hh" +#include "raslib/error.hh" + +void +EOId::print_status(std::ostream& s) const + { + s << systemName.c_str() << "|" << databaseName.c_str() << "|"; + OId::print_status(s); + } + +std::ostream& +operator<<(std::ostream& s, const EOId& d ) + { + s << "EOId(" << d.getSystemName() << "|" << d.getBaseName() << "|" << d.getOId() << ")"; + return s; + } + +std::ostream& +operator<<(std::ostream& s, EOId& d ) + { + s << "EOId(" << d.getSystemName() << "|" << d.getBaseName() << "|" << d.getOId() << ")"; + return s; + } + +EOId::EOId(const char* systemname, const char* dbname, OId::OIdCounter id, OId::OIdType type) + : OId(id, type), + systemName(systemname), + databaseName(dbname) + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "EOId(" << systemname << "," << dbname << "," << id << "," << type << ")"); + } + +EOId::EOId(const OId& id) + : OId(id) + { + RMDBGENTER(10, RMDebug::module_adminif, "EOId", "EOId(" << id << ")"); + if (AdminIf::getCurrentDatabaseIf()) + { + systemName = (AdminIf::getSystemName()); + databaseName = (AdminIf::getCurrentDatabaseIf()->getName()); + } + else { + RMDBGMIDDLE(10, RMDebug::module_adminif, "EOId", "EOId(" << id << ") no current databaseif"); + throw r_Error(r_Error::r_Error_TransactionNotOpen); + } + RMDBGEXIT(10, RMDebug::module_adminif, "EOId", "EOId(" << id << ")"); + } + +EOId::EOId() + : OId() + { + RMDBGENTER(10, RMDebug::module_adminif, "EOId", "EOId()"); + if (AdminIf::getCurrentDatabaseIf()) + { + systemName = (AdminIf::getSystemName()); + databaseName = (AdminIf::getCurrentDatabaseIf()->getName()); + } + else { + RMDBGMIDDLE(10, RMDebug::module_adminif, "EOId", "EOId() no current databaseif"); + throw r_Error(r_Error::r_Error_TransactionNotOpen); + } + RMDBGEXIT(10, RMDebug::module_adminif, "EOId", "EOId()"); + } + +EOId::~EOId() + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "~EOId()"); + } + +const char* +EOId::getSystemName() const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "getSystemName() " << systemName.c_str()); + return systemName.c_str(); + } + + +const char* +EOId::getBaseName() const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "getBaseName() " << databaseName.c_str()); + return databaseName.c_str(); + } + + +OId +EOId::getOId() const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "getOId() " << (OId)*this); + return(OId)*this; + } + + +void +EOId::allocateEOId(EOId& eoid, OId::OIdType t) throw (r_Error) + { + RMDBGENTER(10, RMDebug::module_adminif, "EOId", "allocateEOId(" << eoid << "," << t << ")"); + if (AdminIf::getCurrentDatabaseIf()) + { + eoid.systemName = AdminIf::getSystemName(); + eoid.databaseName = AdminIf::getCurrentDatabaseIf()->getName(); + } + else { + RMDBGMIDDLE(10, RMDebug::module_adminif, "EOId", "allocateEOId(" << eoid << ") no current databaseif"); + throw r_Error(r_Error::r_Error_TransactionNotOpen); + } + allocateOId(eoid, t); + RMDBGEXIT(10, RMDebug::module_adminif, "EOId", "allocateEOId(" << eoid << "," << t << ")"); + } + +bool +EOId::operator==(const EOId& one) const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator==(" << one << ")"); + bool retval=false; + if(OId::operator==(one)) + if(systemName == one.systemName) + if(databaseName == one.databaseName) + retval=true; + return retval; + } + +bool +EOId::operator!=(const EOId& one) const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator!=(" << one << ")"); + return !EOId::operator==(one); + } + +EOId& +EOId::operator=(const EOId& old) + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator=(" << old << ")"); + if(this != &old) + { + OId::operator=(old); + systemName = old.systemName; + databaseName = old.databaseName; + } + return *this; + } + +bool +EOId::operator<(const EOId& old) const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator<(" << old << ")"); + bool retval=false; + if (OId::operator<(old)) + retval=true; + if (!retval && (databaseName < old.databaseName)) + retval=true; + if (!retval && (systemName < old.systemName)) + retval=true; + return retval; + } + +bool +EOId::operator>(const EOId& old) const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator>(" << old << ")"); + bool retval=false; + if (OId::operator>(old)) + retval=true; + if (!retval && (databaseName > old.databaseName)) + retval=true; + if (!retval && (systemName > old.systemName)) + retval=true; + return retval; + } + +bool +EOId::operator<=(const EOId& old) const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator<=(" << old << ")"); + bool retval=false; + if (operator<(old)) + retval=true; + if (!retval && (operator==(old))) + retval=true; + return retval; + } + +bool +EOId::operator>=(const EOId& old) const + { + RMDBGONCE(10, RMDebug::module_adminif, "EOId", "operator<=(" << old << ")"); + bool retval=false; + if (operator>(old)) + retval=true; + if (!retval && (operator==(old))) + retval=true; + return retval; + } + diff --git a/reladminif/eoid.hh b/reladminif/eoid.hh new file mode 100644 index 0000000..968dcb5 --- /dev/null +++ b/reladminif/eoid.hh @@ -0,0 +1,146 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _EOIDIF_HH_ +#define _EOIDIF_HH_ +/************************************************************* + * + * + * PURPOSE: + * EOId is optimized for maps that contain only EOId of one system/database. + * + * + * COMMENTS: + * When true multiple connections are implemented the order of compare + * statements in the operator"<" and ">" must be changed. + ***************************************************************************/ + +class EOId; +class r_Error; + +#include "oidif.hh" +#include <string> + +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: +EOId is optimized for maps that contain only EOId of one system/database. +when true multiple connections are implemented the order of compare +statements in the operator"<" and ">" must be changed. +*/ + +class EOId : public OId + { + public: + EOId(const char* systemname, const char* dbname, OId::OIdCounter id, OIdType type); + /*@Doc: + constructs a complete EOId. + */ + + EOId(const OId& id); + /*@Doc: + uses the currently open database to get system and db name + systemname and database name will be null string when the + database is not really open. + */ + + EOId(); + /*@Doc: + uses the currently open database to get system and db name + systemname and database name will be null string when the + database is not really open. + */ + + + ~EOId(); + /*@Doc: + does not do anything. + */ + + EOId& operator=(const EOId& old); + /*@Doc: + assignes all atributes. + */ + + + const char* getSystemName() const; + /*@Doc: + returns the system name, which is the same as the + one returned by databaseif. + */ + + + const char* getBaseName() const; + /*@Doc: + returns the database name, which is the same as the + one returned by databaseif + */ + + + OId getOId() const; + /*@Doc: + returns the oid of this eoid + */ + + + void print_status(std::ostream& o) const; + /*@Doc: + returns the systemname|databasename|oid + */ + + static void allocateEOId(EOId& eoid, OId::OIdType t) throw (r_Error); + /*@Doc: + Allocates a new logical MDD EOid in the currently opened base. + throws an r_Error_DatabaseClosed when the database is not really open. + */ + + bool operator<(const EOId& old) const; + + bool operator>(const EOId& old) const; + + bool operator<=(const EOId& old) const; + + bool operator>=(const EOId& old) const; + + bool operator== (const EOId& one) const; + + bool operator!= (const EOId& one) const; + + private: + + std::string databaseName; + /*@Doc: + the name of the database the oid of this eoid is valid for. + stl std::string was used because of the compare functionality. + */ + + std::string systemName; + /*@Doc: + the name of the system above mentioned database runs on + stl std::string was used because of the compare functionality. + */ + }; + +extern std::ostream& operator<<(std::ostream& s, EOId& d); + +extern std::ostream& operator<<(std::ostream& s, const EOId& d); + +#endif diff --git a/reladminif/externs.h b/reladminif/externs.h new file mode 100644 index 0000000..d947c7e --- /dev/null +++ b/reladminif/externs.h @@ -0,0 +1,81 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/***************************************************************************** + * + * + * PURPOSE: + * provide global definitions for embedded SQL usage (any base DBMS) + * + * + * COMMENTS: + * - uses embedded SQL + * - FIXME: should also contain stuff from sqlglobals.h, merge some time + * + *****************************************************************************/ + +#ifndef _EXTERNS_H_ +#define _EXTERNS_H_ + +const int SQLOK = 0; +const short INDNULL = -1; + +#ifdef BASEDB_INFORMIX + const int SQLNULLFETCHED = -245; + const int SQLTABLEUNKNOWN = -206; + const int SQLNODATAFOUND = 100; + + //SQLCODE and SQLSTATE are defined in the sqlca.h file +#endif // informix + +#ifdef BASEDB_DB2 + const int SQLNULLFETCHED = -1405; + const int SQLTABLEUNKNOWN = -942; + const int SQLNODATAFOUND = 100; + + //declared in sqlerror.sqC + extern long SQLCODE; + extern char SQLSTATE[6]; + +#endif // db2 + +#ifdef BASEDB_ORACLE + const int SQLNULLFETCHED = -1405; + const int SQLTABLEUNKNOWN = -942; + const int SQLNODATAFOUND = 100; + + #include <sqlca.h> + #define SQLCODE sqlca.sqlcode + + //declared in sqlerror.pc + extern struct sqlca sqlca; +#endif // oracle + +#ifdef BASEDB_PGSQL + #include "ecpgerrno.h" // PgSQL error codes + // const int SQLNULLFETCHED = -1405; unused + // const int SQLTABLEUNKNOWN = -942; not supported by PG + const int SQLNODATAFOUND = ECPG_NOT_FOUND; + //SQLCODE and SQLSTATE are defined in the sqlca.h file +#endif // pgsql + +#endif // _EXTERNS_H_ diff --git a/reladminif/lists.h b/reladminif/lists.h new file mode 100644 index 0000000..783c2af --- /dev/null +++ b/reladminif/lists.h @@ -0,0 +1,106 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _LISTS_H_ +#define _LISTS_H_ + +#include <vector> +#include <set> +#include <map> +#include "relmddif/mddid.hh" + +class DBObject; +class OId; +class InlineMinterval; +class r_Minterval; +class KeyObject; +class IndexDS; +class HierIndexDS; +class Tile; + +#include "raslib/mddtypes.hh" + +//used to hold oids for indexes, blobs, and dbmintervals. no double entries +typedef std::set< OId, std::less< double > > OIdSet; + +//used to hold oids for indexes, blobs, and dbmintervals. no double entries +typedef std::set< const OId, std::less< double > > OIdConstSet; + +typedef std::vector<HierIndexDS*> HierIndexDSPVector; + +//used to hold DBObject*. e.g. in objectbroker to temporarily store them before deletion +typedef std::vector<DBObject*> DBObjectPVector; + +//used to hold DBObject*. e.g. in objectbroker to temporarily store them before deletion +typedef std::vector<const DBObject*> DBObjectPConstVector; + +//used to hold oids for indexes, blobs, and dbmintervals +typedef std::vector<OId> OIdVector; + +//used to hold oids for indexes, blobs, and dbmintervals +typedef std::vector<const OId> OIdConstVector; + +//holds type information on specific blobs which are stored in above oidlists +typedef std::vector<r_Data_Format> CompTypeVector; + +typedef std::vector<const InlineMinterval*> IntervalPConstVector; + +typedef std::vector<InlineMinterval*> IntervalPVector; + +typedef std::vector<const InlineMinterval> IntervalConstVector; + +typedef std::vector<InlineMinterval> IntervalVector; + +typedef std::vector<const KeyObject*> KeyObjectPConstVector; + +typedef std::vector<KeyObject*> KeyObjectPVector; + +typedef std::vector<const KeyObject> KeyObjectConstVector; + +typedef std::vector<KeyObject> KeyObjectVector; + +typedef std::vector<r_Minterval> DomainVector; + +typedef std::vector<r_Minterval*> DomainPVector; + +typedef std::vector<const r_Minterval*> DomainPConstVector; + +typedef std::vector<IndexDS*> IndexPVector; + +typedef std::vector<Tile*> TilePVector; + +typedef std::map< double, DBObject*, std::less<double> > DBObjectPMap; +typedef std::pair< double, DBObject* > DBObjectPPair; +typedef std::pair< const double, DBObject* > ConstDBObjectPPair; + +typedef std::map< double, const DBObject*, std::less<double> > DBObjectPConstMap; +typedef std::pair< double, const DBObject* > DBObjectPConstPair; +typedef std::pair< const double, const DBObject* > ConstDBObjectPConstPair; + +typedef std::map< double, OId, std::less<double> > OIdMap; +typedef std::pair< const double, OId > OIdPair; +typedef std::pair< const double, const OId > OIdConstPair; + +typedef std::map< double, r_Minterval, std::less<double> > DomainMap; +typedef std::pair< const double, r_Minterval > DomainPair; +typedef std::pair< const double, const r_Minterval > DomainConstPair; +#endif diff --git a/reladminif/objectbroker.hh b/reladminif/objectbroker.hh new file mode 100644 index 0000000..bb8d429 --- /dev/null +++ b/reladminif/objectbroker.hh @@ -0,0 +1,506 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _OBJECTBROKER_HH_ +#define _OBJECTBROKER_HH_ + +class ObjectBroker; +class ULongType; +class LongType; +class CharType; +class BoolType; +class UShortType; +class ShortType; +class OctetType; +class DoubleType; +class FloatType; +class ComplexType1; +class ComplexType2; +class StructType; +class BaseType; +class SetType; +class MDDType; +class Type; +class DBObject; + +#include "oidif.hh" +#include "raslib/error.hh" +#include "lists.h" + +#ifdef RMANBENCHMARK +#include "raslib/rmdebug.hh" +#endif + +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: +the ObjectBroker is one of the three columns one which the persistence layer rests: +ObjectBroker, DBRef, DBObject. +the ObjectBroker keeps track of all persistent objects which are loaded into memory. +objects register themselves at this facility and deregister themselves when they are +deleted. + +The ObjectBroker supplies functionality for accessing persistent objects by oid and by +name. +The ObjectBroker can be configured to serve as a cross transaction cache. +The ObejctBroker can retrieve the oids of all objects of a specific type which are stored +in the database. +The list of objects which are kept by the ObjectBroker are cleared by TransactionIf. +*/ + +class ObjectBroker + { + public: + static bool freeMemory() throw (r_Error); + /*@Doc: + this will handle the memory issue. + returns true if memory was freed, false otherwise. + if false is returned there is really to much memory allocated and the transaction should be stopped. + */ + + static void deregisterTileIndexMapping(const OId& tileoid, const OId& indexoid); + /*@Doc: + deletes the object in the correct list + */ + + static void registerTileIndexMapping(const OId& tileoid, const OId& indexoid); + /*@Doc: + inserts the object in the correct list + */ + + static void registerDBObject(DBObject* object); + /*@Doc: + inserts the object in the correct list + */ + + static void deregisterDBObject(const OId& id); + /*@Doc: + removes the object with the specified oid from the list + */ + + static DBObject* getObjectByOId(const OId& id) throw (r_Error); + /*@Doc: + retrieve a dbobject from db. passes (r_Error)s from DBObject up. + */ + + static DBObject* isInMemory(const OId& id) throw (r_Error); + /*@Doc: + does not retrieve the object from db. only retrieves from memory. + if there is no matching object a 0 pointer is returned. + throws an (r_Error) if the OId has a invalid type + */ + + static OIdSet* getAllObjects(OId::OIdType type); + /*@Doc: + generates a list of all objects in the db and in memory with the + specified type. the vector must be deleted by the calling function + */ + + static MDDType* getMDDTypeByName(const char* name) throw (r_Error); + /*@Doc: + retrieves an object with that name and that type from the db. + this method was introduced to remove the spurious sqlwarnings. + passes (r_Error)s from DBObject up or ObjectNotFound when there is + no matching object + */ + + static DBObject* getObjectByName(OId::OIdType type, const char* name) throw (r_Error); + /*@Doc: + retrieves an object with that name and that type from the db. + passes (r_Error)s from DBObject up or ObjectNotFound when there is + no matching object + */ + + static void clearBroker() throw (r_Error); + /*@Doc: + deletes persistent objects from memory, depending on cache ofcourse. + any (r_Error)s thrown during the deletion/update/insert process are + handed up. the objects are removed before errors can occur. multiple + calls to clearBroker until the method completes are possible. memory + leaks may occur in this event. + */ + + static void clearCache() throw (r_Error); + /*@Doc: + deletes _all_ persistent objects from memory. + any (r_Error)s thrown during the deletion/update/insert process are + handed up. the objects are removed before errors can occur. multiple + calls to clearBroker until the method completes are possible. memory + leaks may occur in this event. + */ + + static void init(); + /*@Doc: + initialize the atomic types and maps + */ + + static void deinit(); + /*@Doc: + delete the atomic types and maps + */ + + static DBObjectPMap& getMap(OId::OIdType type) throw (r_Error); + /*@Doc: + returns a pointer to the store of objects of that particular type. + (r_Error) is thrown if there is no map for that type + */ + + protected: + static DBObject* loadDBMDDObj(const OId& id) throw (r_Error); + /*@Doc: + retrieves MDDObjects from memory and from database + */ + + static DBObject* loadMDDSet(const OId& id) throw (r_Error); + /*@Doc: + retrieves MDDSets from memory and from database + */ + + static DBObject* loadMDDType(const OId& id) throw (r_Error); + /*@Doc: + retrieves MDDTypes from memory and from database + */ + + static DBObject* loadMDDBaseType(const OId& id) throw (r_Error); + /*@Doc: + retrieves MDDBaseTypes from memory and from database + */ + + static DBObject* loadMDDDimensionType(const OId& id) throw (r_Error); + /*@Doc: + retrieves MDDDimTypes from memory and from database + */ + + static DBObject* loadMDDDomainType(const OId& id) throw (r_Error); + /*@Doc: + retrieves MDDDomTypes from memory and from database + */ + + static DBObject* loadStructType(const OId& id) throw (r_Error); + /*@Doc: + retrieves StructTypes from memory and from database + */ + + static DBObject* loadSetType(const OId& id) throw (r_Error); + /*@Doc: + retrieves SetTypes from memory and from database + */ + + static DBObject* loadBLOBTile(const OId& id) throw (r_Error); + /*@Doc: + retrieves BLOBTiles from memory and from database. + knows how to get a inlinetile from a dbtcindex. + */ + + static DBObject* loadDBMinterval(const OId& id) throw (r_Error); + /*@Doc: + retrieves DBMintervals from memory and from database + */ + + static DBObject* loadDBStorage(const OId& id) throw (r_Error); + /*@Doc: + retrieves DBStorageLayout from memory and from database + */ + + static DBObject* loadDBHierIndex(const OId& id) throw (r_Error); + /*@Doc: + retrieves HierIxs from memory and from database + */ + + static DBObject* loadDBTCIndex(const OId& id) throw (r_Error); + /*@Doc: + retrieves DBTCIndex from memory and from database + */ + + static DBObject* loadInlineTile(const OId& id) throw (r_Error); + /*@Doc: + retrieves InlineTiles from memory and from database + */ + + static DBObject* loadDBRCIndexDS(const OId& id) throw (r_Error); + /*@Doc: + retrieves DBRCIndexDS from memory and from database + */ + + static OId getOIdByName(OId::OIdType type, const char* name) throw (r_Error); + /*@Doc: + finds the oid of an object with the given type and name + */ + + static void clearMap(DBObjectPMap& theMap) throw (r_Error); + /*@Doc: + deletes entries in this map as long as they are not cached + (r_Error) is thrown when there is a problem in ~DBObject. + the object is removed from the map though. + */ + + static void completelyClearMap(DBObjectPMap& theMap) throw (r_Error); + /*@Doc: + deletes entries in this map + (r_Error) is thrown when there is a problem in ~DBObject. + the object is removed from the map though. + */ + + + static OId getOIdOfMDDSet(const char* name) throw (r_Error); + /*@Doc: + retrieves MDDSets from memory and from database + */ + + static OId getOIdOfMDDType(const char* name) throw (r_Error); + /*@Doc: + retrieves MDDTypes from memory and from database + */ + + static OId getOIdOfMDDBaseType(const char* name) throw (r_Error); + /*@Doc: + retrieves MDDBaseTypes from memory and from database + */ + + static OId getOIdOfMDDDimensionType(const char* name) throw (r_Error); + /*@Doc: + retrieves MDDDimTypes from memory and from database + */ + + static OId getOIdOfMDDDomainType(const char* name) throw (r_Error); + /*@Doc: + retrieves MDDDomTypes from memory and from database + */ + + static OId getOIdOfStructType(const char* name) throw (r_Error); + /*@Doc: + retrieves StructTypes from memory and from database + */ + + static OId getOIdOfSetType(const char* name) throw (r_Error); + /*@Doc: + retrieves SetTypes from memory and from database + */ + + static OIdSet* getAllMDDObjects() throw (r_Error); + /*@Doc: + retrieves the oids of all MDD Objects from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllMDDSets() throw (r_Error); + /*@Doc: + retrieves the oids of all MDDSets from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllMDDTypes() throw (r_Error); + /*@Doc: + retrieves the oids of all MDDTypes from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllMDDBaseTypes() throw (r_Error); + /*@Doc: + retrieves the oids of all MDDBaseTypes from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllMDDDimensionTypes() throw (r_Error); + /*@Doc: + retrieves the oids of all MDDDimTypes from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllMDDDomainTypes() throw (r_Error); + /*@Doc: + retrieves the oids of all MDDDomTypes from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllStructTypes() throw (r_Error); + /*@Doc: + retrieves the oids of all StructTypes from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllSetTypes() throw (r_Error); + /*@Doc: + retrieves the oids of all SetTypes from memory and from database + oidlist must be deallocated by the caller + (r_Error) occures in a database failure + */ + + static OIdSet* getAllAtomicTypes() throw (r_Error); + /*@Doc: + retrieves the oids of all AtomicTypes from memory + oidlist must be deallocated by the caller + (r_Error) should never occur + */ + + private: + ///the types have to be in fornt of* the maps because of static destructor! + static ULongType* theULong; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static CharType* theChar; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static BoolType* theBool; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static UShortType* theUShort; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static LongType* theLong; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static ShortType* theShort; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static OctetType* theOctet; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static DoubleType* theDouble; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static FloatType* theFloat; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static ComplexType1* theComplex1; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static ComplexType2* theComplex2; + /*@Doc: + a pointer to this member is returned by getObjectByOId(). + */ + + static DBObjectPMap theDBMDDObjs; + /*@Doc: + holds all MDDObjects in memory + */ + + static DBObjectPMap theMDDSets; + /*@Doc: + holds all MDDSets in memory + */ + + static DBObjectPMap theMDDTypes; + /*@Doc: + holds all MDDTypes in memory + */ + + static DBObjectPMap theMDDBaseTypes; + /*@Doc: + holds all MDDBaseTypes in memory + */ + + static DBObjectPMap theMDDDimensionTypes; + /*@Doc: + holds all MDDDimTypes in memory + */ + + static DBObjectPMap theMDDDomainTypes; + /*@Doc: + holds all MDDDomTypes in memory + */ + + static DBObjectPMap theStructTypes; + /*@Doc: + holds all StructTypes in memory + */ + + static DBObjectPMap theSetTypes; + /*@Doc: + holds all SetTypes in memory + */ + + static DBObjectPMap theBLOBTiles; + /*@Doc: + holds all BLOBTiles in memory + */ + + static DBObjectPMap theDBMintervals; + /*@Doc: + holds all DBMintervals in memory + */ + + static DBObjectPMap theDBStorages; + /*@Doc: + holds all MDDEntries in memory + */ + + static DBObjectPMap theDBHierIndexs; + /*@Doc: + holds all HierIxs in memory + */ + + static DBObjectPMap theDBTCIndexs; + /*@Doc: + holds all HierIxs in memory + */ + + static DBObjectPMap theInlineTiles; + /*@Doc: + holds all InlineTiles in memory + */ + + static DBObjectPMap theAtomicTypes; + /*@Doc: + holds all SetTypes in memory + */ + + static DBObjectPMap theRCIndexes; + /*@Doc: + holds all RC Indexes in memory + */ + + static OIdMap theTileIndexMappings; + /*@Doc: + key (first/double) is oid of tile, value (second/oid) is oid of index. + */ + + }; + +#endif + diff --git a/reladminif/objectbroker.pgc b/reladminif/objectbroker.pgc new file mode 100644 index 0000000..9313d9c --- /dev/null +++ b/reladminif/objectbroker.pgc @@ -0,0 +1,1029 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +// This is -*- C++ -*- + +/************************************************************************* + * + * + * PURPOSE: + * Code with embedded SQL for PostgreSQL DBMS + * + * + * COMMENTS: + * none + * + ***********************************************************************/ + +static const char rcsid[] = "@(#)reladminif,ObjectBroker: $Id: objectbroker.ec,v 1.4 2003/12/27 23:11:43 rasdev Exp $"; + +#include "debug-srv.hh" + +// general embedded SQL related definitions +EXEC SQL include "sqlglobals.h"; + +#include "objectbroker.hh" +#include "raslib/rmdebug.hh" +#include "sqlerror.hh" +#include "relindexif/dbtcindex.hh" +#include "relindexif/indexid.hh" +#include "adminif.hh" +#include "relindexif/dbrcindexds.hh" +#include "relblobif/inlinetile.hh" +#include "dbref.hh" +#include "dbnamedobject.hh" +#include "externs.h" +#include "catalogmgr/typefactory.hh" + +DBObject* +ObjectBroker::loadInlineTile(const OId& id) throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "loadInlineTile(" << id << ")"); + ENTER( "ObjectBroker::loadInlineTile, oid=" << id ); + + DBObject* retval = 0; + OIdMap::iterator i = theTileIndexMappings.find(id); + if (i != theTileIndexMappings.end()) + { + DBTCIndexId dbtc((*i).second); + retval = (DBObject*)dbtc->getInlineTile(id); + } + else + { + try + { + retval = new InlineTile(id); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + } + catch (r_Error& error) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + } + if (retval == 0) + { + EXEC SQL BEGIN DECLARE SECTION; + long indexid; + long inlineid; + EXEC SQL END DECLARE SECTION; + + indexid = 0; + inlineid = id.getCounter(); + + EXEC SQL SELECT + IndexId + INTO + :indexid + FROM + RAS_ITMAP + WHERE + TileId = :inlineid; + if (SQLCODE == SQLOK) + { + DBTCIndexId dbtc(OId(indexid, OId::DBTCINDEXOID)); + retval = (DBObject*)dbtc->getInlineTile(id); + } + else + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "db error not found in db"); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::loadInlineTile SELECT FROM RAS_ITMAP"); + generateException(); + } + } + } + DBObjectPPair myPair(retval->getOId(), retval); + theInlineTiles.insert(myPair); + } + + LEAVE( "ObjectBroker::loadInlineTile, retval=" << retval ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "loadInlineTile(" << id << ")"); + return retval; +} + + +OId +ObjectBroker::getOIdOfSetType(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getOIdOfSetType, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char setname[STRING_MAXLEN]; + long setoid; + EXEC SQL END DECLARE SECTION; + + OId retval; + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( setname, (char*) name, (size_t) sizeof(setname) ); + + EXEC SQL SELECT + SetTypeId + INTO + :setoid + FROM + RAS_SETTYPES + WHERE + SetTypeName = :setname; + + if (SQLCODE != SQLOK) + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getOIdOfSetType()\0"); + generateException(); + } + } + else + { + retval = OId(setoid, OId::SETTYPEOID); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is in db with " << retval); + } + + LEAVE( "ObjectBroker::getOIdOfSetType, retval=" << retval ); + return retval; +} + +MDDType* +ObjectBroker::getMDDTypeByName(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getMDDTypeByName, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char mddtnamev[STRING_MAXLEN]; + double mddtoidv; + EXEC SQL END DECLARE SECTION; + + MDDType* retval = 0; + DBObjectPMap* theMaps[] = {&theMDDTypes, &theMDDBaseTypes, &theMDDDimensionTypes, &theMDDDomainTypes}; + + // FIXME: why do we iterate 5 times? + for (int a = 0; a < 4; a++) + { + DBObjectPMap& theMap = *theMaps[a]; + //check if there is an object with that name already in memory + for (DBObjectPMap::iterator iter = theMap.begin(); iter != theMap.end(); iter++) + { + if (strcmp(((DBNamedObject*)(*iter).second)->getName(), name) == 0) + { + //RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals " << ((DBNamedObject*)(*iter).second)->getName()); + retval = (MDDType*)(*iter).second; + break; + } + else + { + //RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals NOT " << ((DBNamedObject*)(*iter).second)->getName()); + } + } + if (retval != 0) + break; + } + + if (retval == 0) + { + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + LEAVE( "ObjectBroker::getMDDTypeByName(): type name exceeding max length: " << name ); + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( mddtnamev, (char*) name, (size_t) sizeof(mddtnamev) ); + + TALK( "EXEC SQL SELECT MDDTypeOId INTO :mddtoidv FROM RAS_MDDTYPES_VIEW WHERE MDDTypeName = " << mddtnamev ); + EXEC SQL SELECT MDDTypeOId + INTO :mddtoidv + FROM RAS_MDDTYPES_VIEW + WHERE MDDTypeName = :mddtnamev; + + if (SQLCODE != SQLOK) + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + LEAVE( "ObjectBroker::getMDDTypeByName(): object not found" ); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getMDDTypeByName()\0"); + LEAVE( "ObjectBroker::getMDDTypeByName(): database access error: " << SQLCODE ); + generateException(); + } + } + else + { + retval = (MDDType*)getObjectByOId(OId(mddtoidv)); + } + } + + LEAVE( "ObjectBroker::getMDDTypeByName, retval=" << retval ); + return retval; +} + +OId +ObjectBroker::getOIdOfMDDType(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getOIdOfMDDType, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char mddtname[STRING_MAXLEN]; + long mddtoid; + EXEC SQL END DECLARE SECTION; + + OId retval; + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + LEAVE( "ObjectBroker::getOIdOfMDDType(): name exceeds max length:" << name ); + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( mddtname, (char*) name, (size_t) sizeof(mddtname) ); + + TALK( "EXEC SQL SELECT MDDTypeOId INTO :mddtoid FROM RAS_MDDTYPES WHERE MDDTypeName = " << mddtname ); + EXEC SQL SELECT MDDTypeOId + INTO :mddtoid + FROM RAS_MDDTYPES + WHERE MDDTypeName = :mddtname; + + if (SQLCODE != SQLOK) + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + LEAVE( "ObjectBroker::getOIdOfMDDType(): object not in db" ); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getOIdOfMDDType()\0"); + LEAVE( "ObjectBroker::getOIdOfMDDType(): db access error: " << SQLCODE ); + generateException(); + } + } + else + { + retval = OId(mddtoid,OId::MDDTYPEOID); + } + + LEAVE( "ObjectBroker::getOIdOfMDDType, retval=" << retval ); + return retval; +} + +OId +ObjectBroker::getOIdOfMDDBaseType(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getOIdOfMDDBaseType, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char mddbname[STRING_MAXLEN]; + long mddboid; + EXEC SQL END DECLARE SECTION; + + OId retval; + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + LEAVE( "ObjectBroker::getOIdOfMDDBaseType(): name exceeds max length:" << name ); + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( mddbname, (char*) name, (size_t) sizeof(mddbname) ); + + TALK( "EXEC SQL SELECT MDDBaseTypeOId INTO :mddboid FROM RAS_MDDBASETYPES WHERE MDDTypeName = " << mddbname ); + EXEC SQL SELECT MDDBaseTypeOId + INTO :mddboid + FROM RAS_MDDBASETYPES + WHERE MDDTypeName = :mddbname; + + if (SQLCODE != SQLOK) + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + LEAVE( "ObjectBroker::getOIdOfMDDBaseType(): object not in db" ); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getOIdOfMDDBaseType()\0"); + LEAVE( "ObjectBroker::getOIdOfMDDBaseType(): db access error: " << SQLCODE ); + generateException(); + } + } + else + { + retval = OId(mddboid,OId::MDDBASETYPEOID); + } + + LEAVE( "ObjectBroker::getOIdOfMDDBaseType, retval=" << retval ); + return retval; +} + +OId +ObjectBroker::getOIdOfMDDDimensionType(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getOIdOfMDDDimensionType, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char mdddiname[STRING_MAXLEN]; + long mdddioid; + EXEC SQL END DECLARE SECTION; + + OId retval; + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + LEAVE( "ObjectBroker::getOIdOfMDDDimensionType(): name exceeds max length:" << name ); + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( mdddiname, (char*) name, (size_t) sizeof(mdddiname) ); + + TALK( "EXEC SQL SELECT MDDDimTypeOId INTO :mdddioid FROM RAS_MDDDIMTYPES WHERE MDDTypeName = " << mdddiname ); + EXEC SQL SELECT MDDDimTypeOId + INTO :mdddioid + FROM RAS_MDDDIMTYPES + WHERE MDDTypeName = :mdddiname; + + if (SQLCODE != SQLOK) + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + LEAVE( "ObjectBroker::getOIdOfMDDDimensionType(): object not in db" ); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getOIdOfMDDDimensionType()\0"); + LEAVE( "ObjectBroker::getOIdOfMDDDimensionType(): db access error: " << SQLCODE ); + generateException(); + } + } + else + { + retval = OId(mdddioid,OId::MDDDIMTYPEOID); + } + + LEAVE( "ObjectBroker::getOIdOfMDDDimensionType, retval=" << retval ); + return retval; +} + +OId +ObjectBroker::getOIdOfMDDDomainType(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getOIdOfMDDDomainType, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char mdddoname[STRING_MAXLEN]; + long mdddooid; + EXEC SQL END DECLARE SECTION; + + OId retval; + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + LEAVE( "ObjectBroker::getOIdOfMDDDomainType(): name exceeds max length:" << name ); + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( mdddoname, (char*) name, (size_t) sizeof(mdddoname) ); + + TALK( "EXEC SQL SELECT MDDDomTypeOId INTO :mdddooid FROM RAS_MDDDOMTYPES WHERE MDDTypeName = " << mdddoname ); + EXEC SQL SELECT MDDDomTypeOId + INTO :mdddooid + FROM RAS_MDDDOMTYPES + WHERE MDDTypeName = :mdddoname; + + if (SQLCODE != SQLOK) + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + LEAVE( "ObjectBroker::getOIdOfMDDDomainType(): object not in db" ); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getOIdOfMDDDomainType()\0"); + LEAVE( "ObjectBroker::getOIdOfMDDDomainType(): db access error: " << SQLCODE ); + generateException(); + } + } + else + { + retval = OId(mdddooid,OId::MDDDOMTYPEOID); + } + + LEAVE( "ObjectBroker::getOIdOfMDDDomainType, retval=" << retval ); + return retval; +} + +OId +ObjectBroker::getOIdOfStructType(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getOIdOfStructType, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char structname[STRING_MAXLEN]; + long structoid; + EXEC SQL END DECLARE SECTION; + + OId retval; + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + LEAVE( "ObjectBroker::getOIdOfStructType(): name exceeds max length:" << name ); + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( structname, (char*) name, (size_t) sizeof(structname) ); + + TALK( "EXEC SQL SELECT BaseTypeId INTO :structoid FROM RAS_BASETYPENAMES WHERE BaseTypeName = " << structname ); + EXEC SQL SELECT BaseTypeId + INTO :structoid + FROM RAS_BASETYPENAMES + WHERE BaseTypeName = :structname; + + if (SQLCODE != SQLOK) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + LEAVE( "ObjectBroker::getOIdOfStructType(): object not in db" ); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getOIdOfStructType()\0"); + LEAVE( "ObjectBroker::getOIdOfStructType(): db access error: " << SQLCODE ); + generateException(); + } + } + else + { + retval = OId(structoid, OId::STRUCTTYPEOID); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is in db with " << retval); + } + + LEAVE( "ObjectBroker::getOIdOfStructType, retval=" << retval ); + return retval; +} + +OId +ObjectBroker::getOIdOfMDDSet(const char* name) throw (r_Error) +{ + ENTER( "ObjectBroker::getOIdOfMDDSet, name=" << name ); + + EXEC SQL BEGIN DECLARE SECTION; + char collname[STRING_MAXLEN]; + long colloid; + EXEC SQL END DECLARE SECTION; + + OId retval; + int len = strlen(name); + if (len > DBNamedObject::MAXNAMELENGTH) + { + LEAVE( "ObjectBroker::getOIdOfMDDSet(): name exceeds max length:" << name ); + throw r_Error(TYPENAMEISTOOLONG); + } + (void) strncpy( collname, (char*) name, (size_t) sizeof(collname) ); + + TALK( "EXEC SQL SELECT MDDCollId INTO :colloid FROM RAS_MDDCOLLNAMES WHERE MDDCollName = " << collname ); + EXEC SQL SELECT MDDCollId + INTO :colloid + FROM RAS_MDDCOLLNAMES + WHERE MDDCollName = :collname; + + if (SQLCODE != SQLOK) + { + if (SQLCODE == SQLNODATAFOUND) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is not in db"); + LEAVE( "ObjectBroker::getOIdOfMDDSet(): object not in db" ); + throw r_Error(r_Error::r_Error_ObjectUnknown); + } + else + { + check("ObjectBroker::getOIdOfMDDSet()\0"); + LEAVE( "ObjectBroker::getOIdOfMDDSet(): db access error: " << SQLCODE ); + generateException(); + } + } + else + { + retval = OId(colloid, OId::MDDCOLLOID); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "is in db with " << retval); + } + + LEAVE( "ObjectBroker::getOIdOfMDDSet, retval=" << retval ); + return retval; +} + +OIdSet* +ObjectBroker::getAllSetTypes() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllSetTypes()"); + ENTER( "ObjectBroker::getAllSetTypes" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::SETTYPEOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long settoid1; + EXEC SQL END DECLARE SECTION; + + TALK( "EXEC SQL DECLARE setcursor CURSOR FOR SELECT SetTypeId FROM RAS_SETTYPES ORDER BY SetTypeId" ); + EXEC SQL DECLARE setcursor CURSOR FOR + SELECT SetTypeId + FROM RAS_SETTYPES + ORDER BY SetTypeId; + + TALK( "EXEC SQL OPEN setcursor" ); + EXEC SQL OPEN setcursor; + + do + { + TALK( "EXEC SQL FETCH setcursor INTO :settoid1" ); + EXEC SQL FETCH setcursor INTO :settoid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllSetTypes\0"); + TALK( "EXEC SQL CLOSE setcursor" ); + EXEC SQL CLOSE setcursor; + delete retval; + retval = 0; + LEAVE( "ObjectBroker::getAllSetTypes(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(settoid1, OId::SETTYPEOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType()); + retval->insert(id); + } while (1); + + TALK( "EXEC SQL CLOSE setcursor" ); + EXEC SQL CLOSE setcursor; + + LEAVE( "ObjectBroker::getAllSetTypes, SQLCODE=" << SQLCODE ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllSetTypes() "); + return retval; +} + +OIdSet* +ObjectBroker::getAllMDDTypes() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDTypes()"); + ENTER( "ObjectBroker::getAllMDDTypes" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDTYPEOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long mddtoid1; + EXEC SQL END DECLARE SECTION; + + TALK( "EXEC SQL DECLARE mddtcursor CURSOR FOR SELECT MDDTypeOId FROM RAS_MDDTYPES ORDER BY MDDTypeOId" ); + EXEC SQL DECLARE mddtcursor CURSOR FOR + SELECT MDDTypeOId + FROM RAS_MDDTYPES + ORDER BY MDDTypeOId; + + TALK( "EXEC SQL OPEN mddtcursor" ); + EXEC SQL OPEN mddtcursor; + + do + { + TALK( "EXEC SQL FETCH mddtcursor INTO :mddtoid1" ) ; + EXEC SQL FETCH mddtcursor INTO :mddtoid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllMDDTypes()\0"); + EXEC SQL CLOSE mddtcursor; + delete retval; + retval = 0; + LEAVE( "ObjectBroker::getAllMDDTypes(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(mddtoid1, OId::MDDTYPEOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType() ); + retval->insert(id); + } while (1); + + TALK( "EXEC SQL CLOSE mddtcursor" ); + EXEC SQL CLOSE mddtcursor; + + LEAVE( "ObjectBroker::getAllMDDTypes, retval=" << retval ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDTypes() "); + return retval; +} + +OIdSet* +ObjectBroker::getAllMDDBaseTypes() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDBaseTypes()"); + ENTER( "ObjectBroker::getAllMDDBaseTypes" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDBASETYPEOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long mddboid1; + EXEC SQL END DECLARE SECTION; + + TALK( "EXEC SQL DECLARE mddbcursor CURSOR FOR SELECT MDDBaseTypeOId FROM RAS_MDDBASETYPES ORDER BY MDDBaseTypeOId" ); + EXEC SQL DECLARE mddbcursor CURSOR FOR + SELECT MDDBaseTypeOId + FROM RAS_MDDBASETYPES + ORDER BY MDDBaseTypeOId; + + TALK( "EXEC SQL OPEN mddbcursor" ); + EXEC SQL OPEN mddbcursor; + + do + { + TALK( "EXEC SQL FETCH mddbcursor INTO :mddboid1" ); + EXEC SQL FETCH mddbcursor INTO :mddboid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllMDDBaseTypes()\0"); + EXEC SQL CLOSE mddbcursor; + delete retval; + retval = 0; + LEAVE( "ObjectBroker::getAllMDDBaseTypes(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(mddboid1, OId::MDDBASETYPEOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType() ); + retval->insert(id); + } while (1); + + TALK( "EXEC SQL CLOSE mddbcursor" ); + EXEC SQL CLOSE mddbcursor; + + LEAVE( "ObjectBroker::getAllMDDBaseTypes, retval=" << retval ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDBaseTypes() "); + return retval; +} + +OIdSet* +ObjectBroker::getAllMDDDimensionTypes() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDimensionTypes()"); + ENTER( "ObjectBroker::getAllMDDDimensionTypes" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDDIMTYPEOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long mdddioid1; + EXEC SQL END DECLARE SECTION; + + TALK( "EXEC SQL DECLARE mdddicursor CURSOR FOR SELECT MDDDimTypeOId FROM RAS_MDDDIMTYPES ORDER BY MDDDimTypeOId" ); + EXEC SQL DECLARE mdddicursor CURSOR FOR + SELECT MDDDimTypeOId + FROM RAS_MDDDIMTYPES + ORDER BY MDDDimTypeOId; + + TALK( "EXEC SQL OPEN mdddicursor" ); + EXEC SQL OPEN mdddicursor; + + do + { + TALK( "EXEC SQL FETCH mdddicursor INTO :mdddioid1" ); + EXEC SQL FETCH mdddicursor INTO :mdddioid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllMDDDimensionTypes()\0"); + EXEC SQL CLOSE mdddicursor; + delete retval; + retval = 0; + LEAVE( "ObjectBroker::getAllMDDDimensionTypes(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(mdddioid1, OId::MDDDIMTYPEOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType() ); + retval->insert(id); + } while (1); + + TALK( "EXEC SQL CLOSE mdddicursor" ); + EXEC SQL CLOSE mdddicursor; + + LEAVE( "ObjectBroker::getAllMDDDimensionTypes, retval=" << retval ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDimensionTypes() "); + return retval; +} + +OIdSet* +ObjectBroker::getAllMDDDomainTypes() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDomainTypes()"); + ENTER( "ObjectBroker::getAllMDDDomainTypes" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDDOMTYPEOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long mdddooid1; + EXEC SQL END DECLARE SECTION; + + TALK( "EXEC SQL DECLARE mdddocursor CURSOR FOR SELECT MDDDomTypeOId FROM RAS_MDDDOMTYPES ORDER BY MDDDomTypeOId" ); + EXEC SQL DECLARE mdddocursor CURSOR FOR + SELECT MDDDomTypeOId + FROM RAS_MDDDOMTYPES + ORDER BY MDDDomTypeOId; + + TALK( "EXEC SQL OPEN mdddocursor" ); + EXEC SQL OPEN mdddocursor; + + do + { + TALK( "EXEC SQL FETCH mdddocursor INTO :mdddooid1" ); + EXEC SQL FETCH mdddocursor INTO :mdddooid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllMDDDomainTypes()\0"); + EXEC SQL CLOSE mdddocursor; + delete retval; + retval = 0; + LEAVE( "ObjectBroker::getAllMDDDomainTypes(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(mdddooid1, OId::MDDDOMTYPEOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType() ); + retval->insert(id); + } while (1); + TALK( "EXEC SQL CLOSE mdddocursor" ); + EXEC SQL CLOSE mdddocursor; + + LEAVE( "ObjectBroker::getAllMDDDomainTypes" ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDDomainTypes() "); + return retval; +} + +OIdSet* +ObjectBroker::getAllStructTypes() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllStructTypes()"); + ENTER( "ObjectBroker::getAllStructTypes" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::STRUCTTYPEOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long structoid1; + short maxbuiltin; + EXEC SQL END DECLARE SECTION; + + maxbuiltin = TypeFactory::MaxBuiltInId; + + TALK( "EXEC SQL DECLARE structcursor CURSOR FOR SELECT BaseTypeId FROM RAS_BASETYPENAMES ORDER BY BaseTypeId" ); + EXEC SQL DECLARE structcursor CURSOR FOR + SELECT BaseTypeId + FROM RAS_BASETYPENAMES + ORDER BY BaseTypeId; + + TALK( "EXEC SQL OPEN structcursor" ); + EXEC SQL OPEN structcursor; + + do + { + TALK( "EXEC SQL FETCH structcursor INTO :structoid1" ); + EXEC SQL FETCH structcursor INTO :structoid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllStructTypes()\0"); + EXEC SQL CLOSE structcursor; + delete retval; + retval = 0; + LEAVE( "ObjectBroker::getAllStructTypes(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(structoid1, OId::STRUCTTYPEOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType() ); + retval->insert(id); + } while (1); + TALK( "EXEC SQL CLOSE structcursor" ); + EXEC SQL CLOSE structcursor; + + LEAVE( "ObjectBroker::getAllStructTypes, retval=" << retval ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllStructTypes() "); + return retval; +} + +OIdSet* +ObjectBroker::getAllMDDObjects() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDObjects()"); + ENTER( "ObjectBroker::getAllMDDObjects" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long mddobjoid1; + EXEC SQL END DECLARE SECTION; + + TALK(" EXEC SQL DECLARE mddobjcursor CURSOR FOR SELECT MDDId FROM RAS_MDDOBJECTS ORDER BY MDDId" ); + EXEC SQL DECLARE mddobjcursor CURSOR FOR + SELECT MDDId + FROM RAS_MDDOBJECTS + ORDER BY MDDId; + + TALK( "EXEC SQL OPEN mddobjcursor" ); + EXEC SQL OPEN mddobjcursor; + + do + { + TALK( "EXEC SQL FETCH mddobjcursor INTO :mddobjoid1" ); + EXEC SQL FETCH mddobjcursor INTO :mddobjoid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllMDDObjects()\0"); + EXEC SQL CLOSE mddobjcursor; + delete retval; + retval = 0; + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "Database Failed"); + LEAVE( "ObjectBroker::getAllMDDObjects(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(mddobjoid1, OId::MDDOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType() ); + retval->insert(id); + } while (1); + TALK( "EXEC SQL CLOSE mddobjcursor" ); + EXEC SQL CLOSE mddobjcursor; + + LEAVE( "ObjectBroker::getAllMDDObjects, retval=" << retval ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDObjects() "); + return retval; +} + +OIdSet* +ObjectBroker::getAllMDDSets() throw (r_Error) +{ + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDSets()"); + ENTER( "ObjectBroker::getAllMDDSets" ); + + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::MDDCOLLOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + OId id; + + EXEC SQL BEGIN DECLARE SECTION; + long colloid1; + EXEC SQL END DECLARE SECTION; + + TALK( "EXEC SQL DECLARE collcursor CURSOR FOR SELECT MDDCollId FROM RAS_MDDCOLLNAMES ORDER BY MDDCollId" ); + EXEC SQL DECLARE collcursor CURSOR FOR + SELECT MDDCollId + FROM RAS_MDDCOLLNAMES + ORDER BY MDDCollId; + + TALK(" EXEC SQL OPEN collcursor" ); + EXEC SQL OPEN collcursor; + + do + { + TALK( "EXEC SQL FETCH collcursor INTO :colloid1" ); + EXEC SQL FETCH collcursor INTO :colloid1; + if (SQLCODE != SQLOK) + { + if (SQLCODE != SQLNODATAFOUND) + { + check("ObjectBroker::getAllMDDSets()\0"); + EXEC SQL CLOSE collcursor; + delete retval; + retval = 0; + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "Database Failed"); + LEAVE( "ObjectBroker::getAllMDDSets(): db access error: " << SQLCODE ); + generateException(); + } + break; + } + id = OId(colloid1, OId::MDDCOLLOID); + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "read " << id << " " << id.getType()); + TALK( "got object " << id << " " << id.getType() ); + retval->insert(id); + } while (1); + TALK( "EXEC SQL CLOSE collcursor" ); + EXEC SQL CLOSE collcursor; + + LEAVE( "ObjectBroker::getAllMDDSets, retval=" << retval ); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllMDDSets() "); + return retval; +} + diff --git a/reladminif/objectbrokercommon.cc b/reladminif/objectbrokercommon.cc new file mode 100644 index 0000000..648f3c6 --- /dev/null +++ b/reladminif/objectbrokercommon.cc @@ -0,0 +1,1144 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include <map> +#include <set> +#include <cstring> +#include <cstdlib> + +#include "raslib/rmdebug.hh" +#include "raslib/minterval.hh" +#include "objectbroker.hh" +#include "dbnamedobject.hh" +#include "relstorageif/dbstoragelayout.hh" +#include "adminif.hh" +#include "relcatalogif/alltypes.hh" +#include "relindexif/hierindex.hh" +#include "relblobif/blobtile.hh" +#include "relcatalogif/dbminterval.hh" +#include "relblobif/inlinetile.hh" +#include "relindexif/dbtcindex.hh" +#include "sqlerror.hh" +#include "relindexif/indexid.hh" +#include "relmddif/mddid.hh" +#include "dbref.hh" +#include "relmddif/dbmddobj.hh" +#include "catalogmgr/typefactory.hh" +#include "relmddif/dbmddset.hh" +#include "relindexif/dbrcindexds.hh" +#include "debug.hh" + +#ifdef LINUX +template class DBRef<BLOBTile>; +template class DBRef<DBTile>; +template class DBRef<InlineTile>; +#endif + +using namespace std; + +LongType* +ObjectBroker::theLong = 0; + +ShortType* +ObjectBroker::theShort = 0; + +OctetType* +ObjectBroker::theOctet = 0; + +ULongType* +ObjectBroker::theULong = 0; + +UShortType* +ObjectBroker::theUShort = 0; + +CharType* +ObjectBroker::theChar = 0; + +BoolType* +ObjectBroker::theBool = 0; + +DoubleType* +ObjectBroker::theDouble = 0; + +FloatType* +ObjectBroker::theFloat = 0; + +ComplexType1* +ObjectBroker::theComplex1 = 0; + +ComplexType2* +ObjectBroker::theComplex2 = 0; + +DBObjectPMap +ObjectBroker::theAtomicTypes; + +DBObjectPMap +ObjectBroker::theSetTypes; + +DBObjectPMap +ObjectBroker::theMDDTypes; + +DBObjectPMap +ObjectBroker::theMDDBaseTypes; + +DBObjectPMap +ObjectBroker::theMDDDimensionTypes; + +DBObjectPMap +ObjectBroker::theMDDDomainTypes; + +DBObjectPMap +ObjectBroker::theStructTypes; + +DBObjectPMap +ObjectBroker::theDBMintervals; + +DBObjectPMap +ObjectBroker::theDBMDDObjs; + +DBObjectPMap +ObjectBroker::theMDDSets; + +DBObjectPMap +ObjectBroker::theDBStorages; + +DBObjectPMap +ObjectBroker::theDBHierIndexs; + +DBObjectPMap +ObjectBroker::theDBTCIndexs; + +DBObjectPMap +ObjectBroker::theBLOBTiles; + +DBObjectPMap +ObjectBroker::theInlineTiles; + +DBObjectPMap +ObjectBroker::theRCIndexes; + +OIdMap +ObjectBroker::theTileIndexMappings; + +bool +ObjectBroker::freeMemory() throw (r_Error) + { + RMDBGONCE(0, RMDebug::module_adminif, "ObjectBroker", "memoryOverFlow()"); + bool retval = false; + DBRef<BLOBTile>::setPointerCaching(false); + DBRef<DBTile>::setPointerCaching(false); + DBRef<InlineTile>::setPointerCaching(false); + if (!ObjectBroker::theBLOBTiles.empty()) + { + int theLucky = ObjectBroker::theBLOBTiles.size() / 2; + DBObjectPMap::iterator it = ObjectBroker::theBLOBTiles.begin(); + for (int i = 0; i < theLucky; i++, it++); + delete (*it).second; + retval = true; + } + return retval; + } + +void +ObjectBroker::init() + { + RMDBGENTER(2, RMDebug::module_adminif, "ObjectBroker", "init()"); + ObjectBroker::theLong = new LongType(); + + ObjectBroker::theShort = new ShortType(); + + ObjectBroker::theOctet = new OctetType(); + + ObjectBroker::theULong = new ULongType(); + + ObjectBroker::theUShort = new UShortType(); + + ObjectBroker::theChar = new CharType(); + + ObjectBroker::theBool = new BoolType(); + + ObjectBroker::theDouble = new DoubleType(); + + ObjectBroker::theFloat = new FloatType(); + + ObjectBroker::theComplex1 = new ComplexType1(); + + ObjectBroker::theComplex2 = new ComplexType2(); + + DBObject* atomicTypes[] = {theComplex2, theComplex1, theFloat, theDouble, theOctet, theShort, theLong, theUShort, theBool, theChar, theULong}; + RMDBGIF(0, RMDebug::module_adminif, "ObjectBroker", \ + if (sizeof(atomicTypes)/sizeof(DBObject*) != TypeFactory::MaxBuiltInId) \ + { \ + RMInit::logOut << "ObjectBroker::init() not all atomic types were added!" << endl; \ + exit(1); \ + } ) + for (unsigned int a = 0; a < sizeof(atomicTypes)/sizeof(DBObject*); a++) + { + DBObjectPPair myPair(atomicTypes[a]->getOId(), atomicTypes[a]); + theAtomicTypes.insert(myPair); + } + RMDBGEXIT(2, RMDebug::module_adminif, "ObjectBroker", "init()"); + } + +void +ObjectBroker::deinit() + { + RMDBGONCE(2, RMDebug::module_adminif, "ObjectBroker", "deinit()"); + if (ObjectBroker::theLong != 0) + { + delete ObjectBroker::theLong; + ObjectBroker::theLong = 0; + } + + if (ObjectBroker::theShort != 0) + { + delete ObjectBroker::theShort; + ObjectBroker::theShort = 0; + } + + if (ObjectBroker::theOctet != 0) + { + delete ObjectBroker::theOctet; + ObjectBroker::theOctet = 0; + } + + if (ObjectBroker::theULong != 0) + { + delete ObjectBroker::theULong; + ObjectBroker::theULong = 0; + } + + if (ObjectBroker::theUShort != 0) + { + delete ObjectBroker::theUShort; + ObjectBroker::theUShort = 0; + } + + if (ObjectBroker::theChar != 0) + { + delete ObjectBroker::theChar; + ObjectBroker::theChar = 0; + } + + if (ObjectBroker::theBool != 0) + { + delete ObjectBroker::theBool; + ObjectBroker::theBool = 0; + } + + if (ObjectBroker::theDouble != 0) + { + delete ObjectBroker::theDouble; + ObjectBroker::theDouble = 0; + } + + if (ObjectBroker::theFloat != 0) + { + delete ObjectBroker::theFloat; + ObjectBroker::theFloat = 0; + } + + if (ObjectBroker::theComplex1 != 0) + { + delete ObjectBroker::theComplex1; + ObjectBroker::theComplex1 = 0; + } + + if (ObjectBroker::theComplex2 != 0) + { + delete ObjectBroker::theComplex2; + ObjectBroker::theComplex2 = 0; + } + + theAtomicTypes.clear(); + + theSetTypes.clear(); + + theMDDTypes.clear(); + + theMDDBaseTypes.clear(); + + theMDDDimensionTypes.clear(); + + theMDDDomainTypes.clear(); + + theStructTypes.clear(); + + theDBMintervals.clear(); + + theDBMDDObjs.clear(); + + theMDDSets.clear(); + + theDBStorages.clear(); + + theDBHierIndexs.clear(); + + theDBTCIndexs.clear(); + + theBLOBTiles.clear(); + + theInlineTiles.clear(); + + theRCIndexes.clear(); + + theTileIndexMappings.clear(); + } + +DBObject* +ObjectBroker::getObjectByOId(const OId& id) throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByOId(" << id << " " << id.getType() << ")"); + DBObject* retval = 0; + if (id.getType() == OId::INVALID) + retval = 0; + else { + retval = ObjectBroker::isInMemory(id); + if (retval == 0) + { + switch (id.getType()) + { + case OId::MDDOID: + retval = loadDBMDDObj(id); + break; + case OId::MDDCOLLOID: + retval = loadMDDSet(id); + break; + case OId::MDDTYPEOID: + retval = loadMDDType(id); + break; + case OId::MDDBASETYPEOID: + retval = loadMDDBaseType(id); + break; + case OId::MDDDIMTYPEOID: + retval = loadMDDDimensionType(id); + break; + case OId::MDDDOMTYPEOID: + retval = loadMDDDomainType(id); + break; + case OId::STRUCTTYPEOID: + retval = loadStructType(id); + break; + case OId::SETTYPEOID: + retval = loadSetType(id); + break; + case OId::BLOBOID: + retval = loadBLOBTile(id); + break; + case OId::DBMINTERVALOID: + retval = loadDBMinterval(id); + break; + case OId::STORAGEOID: + retval = loadDBStorage(id); + break; + case OId::MDDHIERIXOID: + retval = loadDBHierIndex(id); + break; + case OId::DBTCINDEXOID: + retval = loadDBTCIndex(id); + break; + case OId::INLINETILEOID: + retval = loadInlineTile(id); + break; + case OId::MDDRCIXOID: + retval = loadDBRCIndexDS(id); + break; + case OId::ATOMICTYPEOID: + RMInit::logOut << "Atomic type not found in memory." << endl; + default: + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByOId(" << id << " " << id.getType() << ")"); + RMInit::logOut << "Retrival of Object Failed (Internal State 3)." << endl << "Please contact Customer Support." << endl; + throw r_Error(INVALID_OIDTYPE); + break; + } + } + } + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByOId(" << id << " " << id.getType() << ") " << retval); + return retval; + } + + +DBObject* +ObjectBroker::isInMemory(const OId& id) throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "isInMemory(" << id << " " << id.getType() << ")"); + DBObject* retval = 0; + DBObjectPMap& theMap = ObjectBroker::getMap(id.getType()); + DBObjectPMap::iterator i = theMap.find(id); + if (i != theMap.end()) + { + retval = (*i).second; + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "found object with that id in map at " << (unsigned long)retval << " with id " << retval->getOId()); + } + else { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "did not find object with that id in map"); + } + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "isInMemory(" << id << " ( " << id.getCounter() << " "<< id.getType() << " ) ) " << retval); + return retval; + } + +void +ObjectBroker::registerDBObject(DBObject* obj) + { + DBObjectPPair myPair(obj->getOId(), obj); + ObjectBroker::getMap(obj->getOId().getType()).insert(myPair); + } + +void +ObjectBroker::deregisterDBObject(const OId& id) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "deregisterDBObject(" << id << ")"); + if (id.getType() != OId::INVALID) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "size of map before\t: " << ObjectBroker::getMap(id.getType()).size()); + DBObjectPMap& t = ObjectBroker::getMap(id.getType()); + DBObjectPMap::iterator i = t.find(id); + if (i != t.end()) + { + (*i).second = 0; + t.erase(i); + } + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "size of map after \t: " << ObjectBroker::getMap(id.getType()).size()); + } + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "deregisterDBObject(" << id << ")"); + } + +OIdSet* +ObjectBroker::getAllObjects(OId::OIdType type) + { + OIdSet* retval = 0; + switch (type) + { + case OId::MDDCOLLOID: + retval = getAllMDDSets(); + break; + case OId::MDDOID: + retval = getAllMDDObjects(); + break; + case OId::MDDTYPEOID: + retval = getAllMDDTypes(); + break; + case OId::MDDBASETYPEOID: + retval = getAllMDDBaseTypes(); + break; + case OId::MDDDIMTYPEOID: + retval = getAllMDDDimensionTypes(); + break; + case OId::MDDDOMTYPEOID: + retval = getAllMDDDomainTypes(); + break; + case OId::STRUCTTYPEOID: + retval = getAllStructTypes(); + break; + case OId::SETTYPEOID: + retval = getAllSetTypes(); + break; + case OId::ATOMICTYPEOID: + retval = getAllAtomicTypes(); + break; + + default: + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "getAllObjects(" << type << ")"); + RMInit::logOut << "Retrival of Object Failed (Internal State 4)." << endl << "Please contact Customer Support." << endl; + throw r_Error(INVALID_OIDTYPE); + break; + } + return retval; + } + + +OId +ObjectBroker::getOIdByName(OId::OIdType type, const char* name) throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getOIdByName(" << type << ", " << name << ")"); + OId id; + switch (type) + { + case OId::MDDCOLLOID: + id = getOIdOfMDDSet(name); + break; + case OId::MDDTYPEOID: + id = getOIdOfMDDType(name); + break; + case OId::MDDBASETYPEOID: + id = getOIdOfMDDBaseType(name); + break; + case OId::MDDDIMTYPEOID: + id = getOIdOfMDDDimensionType(name); + break; + case OId::MDDDOMTYPEOID: + id = getOIdOfMDDDomainType(name); + break; + case OId::STRUCTTYPEOID: + id = getOIdOfStructType(name); + break; + case OId::SETTYPEOID: + id = getOIdOfSetType(name); + break; + case OId::ATOMICTYPEOID: + if(strcmp(name, ULongType::Name) == 0) + id = theULong->getOId(); + else if(strcmp(name, BoolType::Name) == 0) + id = theBool->getOId(); + else if(strcmp(name, CharType::Name) == 0) + id = theChar->getOId(); + else if(strcmp(name, UShortType::Name) == 0) + id = theUShort->getOId(); + else if(strcmp(name, LongType::Name) == 0) + id = theLong->getOId(); + else if(strcmp(name, ShortType::Name) == 0) + id = theShort->getOId(); + else if(strcmp(name, OctetType::Name) == 0) + id = theOctet->getOId(); + else if(strcmp(name, DoubleType::Name) == 0) + id = theDouble->getOId(); + else if(strcmp(name, FloatType::Name) == 0) + id = theFloat->getOId(); + else if(strcmp(name, ComplexType1::Name) == 0) + id = theComplex1->getOId(); + else if(strcmp(name, ComplexType2::Name) == 0) + id = theComplex2->getOId(); + break; + + default: + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getOIdByName(" << type << ", " << name << ")"); + RMInit::logOut << "Retrival of Object Failed (Internal State 5)." << endl << "Please contact Customer Support." << endl; + throw r_Error(INVALID_OIDTYPE); + break; + } + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getOIdByName(" << type << ", " << name << ") " << id << " " << id.getType()); + return id; + } + + +DBObject* +ObjectBroker::getObjectByName(OId::OIdType type, const char* name) throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByName(" << type << ", " << name << ")"); + DBObject* retval = 0; + DBObjectPMap* theMap = 0; + switch (type) + { + case OId::MDDCOLLOID: + theMap = &theMDDSets; + break; + case OId::MDDTYPEOID: + theMap = &theMDDTypes; + break; + case OId::MDDBASETYPEOID: + theMap = &theMDDBaseTypes; + break; + case OId::MDDDIMTYPEOID: + theMap = &theMDDDimensionTypes; + break; + case OId::MDDDOMTYPEOID: + theMap = &theMDDDomainTypes; + break; + case OId::STRUCTTYPEOID: + theMap = &theStructTypes; + break; + case OId::SETTYPEOID: + theMap = &theSetTypes; + break; + case OId::ATOMICTYPEOID: + theMap = &theAtomicTypes; + break; + default: + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByName(" << type << ", " << name << ")"); + RMInit::logOut << "Retrival of Object Failed (Internal State 6)." << endl << "Please contact Customer Support." << endl; + throw r_Error(INVALID_OIDTYPE); + break; + } + + //check if there is an object with that name already in memory + for (DBObjectPMap::iterator iter = theMap->begin(); iter != theMap->end(); iter++) + { + if (strcmp(((DBNamedObject*)(*iter).second)->getName(), name) == 0) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals " << ((DBNamedObject*)(*iter).second)->getName()); + retval = (*iter).second; + break; + } + else { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", name << " equals NOT " << ((DBNamedObject*)(*iter).second)->getName()); + } + } + + //no - no matching object. try loading from db + if (!retval) + { + retval = ObjectBroker::getObjectByOId(ObjectBroker::getOIdByName(type,name)); + } + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getObjectByName(" << type << ", " << name << ") " << retval); + return retval; + } + +void +ObjectBroker::clearMap(DBObjectPMap& theMap) throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "clearMap()"); + DBObjectPVector test; + test.reserve(theMap.size()); + if (AdminIf::isAborted() || AdminIf::isReadOnlyTA()) + { + //only delete objects that are modifed/not cached + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++ ) + { + if ((*i).second->isModified() || !(*i).second->isCached()) + { + RMDBGMIDDLE(117, RMDebug::module_adminif, "ObjectBroker", "preparing to delete " << (*i).second->getOId() << " " << (*i).second->getOId().getType()); + test.push_back((*i).second); + //(*i).second = 0; not good because of circular dependencies in the destructors + } + else { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "leaving alone " << (*i).second->getOId() << " " << (*i).second->getOId().getType()); + } + } + } + else { + //only delete objects that are not cached. validate the cached objects. + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "theMap are validated"); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++ ) + { + if ((*i).second->isCached()) + { + RMDBGMIDDLE(117, RMDebug::module_adminif, "ObjectBroker", "leaving alone because of cache " << (*i).second->getOId() << " " << (*i).second->getOId().getType()); + (*i).second->validate(); + } + else { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "preparing to delete " << (*i).second->getOId() << " " << (*i).second->getOId().getType()); + test.push_back((*i).second); + //(*i).second = 0; not good because of circular dependencies in the destructors + } + } + } + for (DBObjectPVector::iterator i2 = test.begin(); i2 != test.end(); i2++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "deleting " << (*i2)->getOId() << " " << (*i2)->getOId().getType() << " size " << (*i2)->getMemorySize()); + delete (*i2); + } + test.clear(); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "clearMap() "); + } + +void +ObjectBroker::completelyClearMap(DBObjectPMap& theMap) throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "completelyClearMap()"); + DBObjectPVector test; + test.reserve(theMap.size()); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++ ) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "preparing to delete " << (*i).second->getOId() << " " << (*i).second->getOId().getType()); + (*i).second->validate(); + test.push_back((*i).second); + //(*i).second = 0; not good because of circular dependencies in the destructors + } + for (DBObjectPVector::iterator i2 = test.begin(); i2 != test.end(); i2++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "deleting " << (*i2)->getOId() << " " << (*i2)->getOId().getType()); + delete (*i2); + } + test.clear(); + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "completelyClearMap() "); + } + +void +ObjectBroker::clearBroker() throw (r_Error) + { + //do not ever clear the ATOMICTYPEOID map! those are on the stack, not heap! +// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFOID)); +// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFPACKAGEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDCOLLOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDHIERIXOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDRCIXOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBTCINDEXOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::INLINETILEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STORAGEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::SETTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDOMTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDIMTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDBASETYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STRUCTTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBMINTERVALOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::BLOBOID)); + theTileIndexMappings.clear(); + } + +void +ObjectBroker::clearCache() throw (r_Error) + { + //do not ever clear the ATOMICTYPEOID map! those are on the stack, not heap! +// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFOID)); +// ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::UDFPACKAGEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDCOLLOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDHIERIXOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDRCIXOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBTCINDEXOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::INLINETILEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STORAGEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::SETTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDOMTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDDIMTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDBASETYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::MDDTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::STRUCTTYPEOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::DBMINTERVALOID)); + ObjectBroker::completelyClearMap(ObjectBroker::getMap(OId::BLOBOID)); + theTileIndexMappings.clear(); + } + +DBObjectPMap& +ObjectBroker::getMap(OId::OIdType type) throw (r_Error) + { + DBObjectPMap* theMap = 0; + switch (type) + { + case OId::MDDOID: + theMap = &theDBMDDObjs; + break; + case OId::MDDCOLLOID: + theMap = &theMDDSets; + break; + case OId::MDDTYPEOID: + theMap = &theMDDTypes; + break; + case OId::MDDBASETYPEOID: + theMap = &theMDDBaseTypes; + break; + case OId::MDDDIMTYPEOID: + theMap = &theMDDDimensionTypes; + break; + case OId::MDDDOMTYPEOID: + theMap = &theMDDDomainTypes; + break; + case OId::STRUCTTYPEOID: + theMap = &theStructTypes; + break; + case OId::SETTYPEOID: + theMap = &theSetTypes; + break; + case OId::BLOBOID: + theMap = &theBLOBTiles; + break; + case OId::INLINETILEOID: + theMap = &theInlineTiles; + break; + case OId::DBMINTERVALOID: + theMap = &theDBMintervals; + break; + case OId::STORAGEOID: + theMap = &theDBStorages; + break; + case OId::DBTCINDEXOID: + theMap = &theDBTCIndexs; + break; + case OId::MDDHIERIXOID: + theMap = &theDBHierIndexs; + break; + case OId::ATOMICTYPEOID: + theMap = &theAtomicTypes; + break; + case OId::MDDRCIXOID: + theMap = &theRCIndexes; + break; + default: + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "getMap(" << type << ")"); + RMInit::logOut << "Retrival of Object Failed (Internal State 7)." << endl << "Please contact Customer Support." << endl; + throw r_Error(INVALID_OIDTYPE); + break; + } + return *theMap; + } + +DBObject* +ObjectBroker::loadDBStorage(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new DBStorageLayout(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + theDBStorages.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + +DBObject* +ObjectBroker::loadSetType(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new SetType(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + theSetTypes.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + +DBObject* +ObjectBroker::loadMDDType(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new MDDType(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(),retval); + theMDDTypes.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + + +DBObject* +ObjectBroker::loadMDDBaseType(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new MDDBaseType(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + theMDDBaseTypes.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + + +DBObject* +ObjectBroker::loadMDDDimensionType(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new MDDDimensionType(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + theMDDDimensionTypes.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + + +DBObject* +ObjectBroker::loadMDDDomainType(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new MDDDomainType(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + theMDDDomainTypes.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + + +DBObject* +ObjectBroker::loadStructType(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new StructType(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + theStructTypes.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + + +DBObject* +ObjectBroker::loadDBMinterval(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new DBMinterval(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair( retval->getOId(), retval); + theDBMintervals.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + + +DBObject* +ObjectBroker::loadDBMDDObj(const OId& id) throw (r_Error) +{ + ENTER( "ObjectBroker::loadDBMDDObj, id=" << id ); + + DBObject* retval = 0; + try + { + retval = new DBMDDObj(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + TALK( "found object, inserting " << retval->getOId() << " into result list" ); + theDBMDDObjs.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + LEAVE( "ObjectBroker::loadDBMDDObj, object not found in db, throwing error " << error.what() ); + throw error; + } + + LEAVE( "ObjectBroker::loadDBMDDObj, retval=" << retval ); + return retval; +} + + +DBObject* +ObjectBroker::loadMDDSet(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new DBMDDSet(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(),retval); + theMDDSets.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + +DBObject* +ObjectBroker::loadDBTCIndex(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new DBTCIndex(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(), retval); + retval->setCached(true); + theDBTCIndexs.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + +DBObject* +ObjectBroker::loadDBHierIndex(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new DBHierIndex(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair(retval->getOId(),retval); + retval->setCached(true); + theDBHierIndexs.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + + +DBObject* +ObjectBroker::loadBLOBTile(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new BLOBTile(id); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair( retval->getOId(),retval); + theBLOBTiles.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + if(retval) + { + delete retval; + retval=0; + } + throw error; + } + return retval; + } + +DBObject* +ObjectBroker::loadDBRCIndexDS(const OId& id) throw (r_Error) + { + DBObject* retval = 0; + try { + retval = new DBRCIndexDS(id); + retval->setCached(true); + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "found in db"); + DBObjectPPair myPair( retval->getOId(),retval); + theRCIndexes.insert(myPair); + } + catch (r_Error& error) + { + RMDBGONCE(11, RMDebug::module_adminif, "ObjectBroker", "not found in db"); + delete retval; + throw error; + } + return retval; + } + +void +ObjectBroker::registerTileIndexMapping(const OId& tileoid, const OId& indexoid) + { + OIdPair p(tileoid, indexoid); + theTileIndexMappings.insert(p); + } + +void +ObjectBroker::deregisterTileIndexMapping(const OId& tileoid, const OId& indexoid) + { + OIdPair p(tileoid, indexoid); + OIdMap::iterator i = theTileIndexMappings.find(tileoid); + if (i != theTileIndexMappings.end()) + theTileIndexMappings.erase(i); + else + RMDBGONCE(0, RMDebug::module_adminif, "ObjectBroker", "deregisterIndexTileMapping(" << indexoid << ", " << tileoid << ") NOT FOUND"); + } + +OIdSet* +ObjectBroker::getAllAtomicTypes() throw (r_Error) + { + RMDBGENTER(11, RMDebug::module_adminif, "ObjectBroker", "getAllAtomicTypes()"); + OIdSet* retval = new OIdSet(); + DBObjectPMap& theMap = ObjectBroker::getMap(OId::ATOMICTYPEOID); + for (DBObjectPMap::iterator i = theMap.begin(); i != theMap.end(); i++) + { + RMDBGMIDDLE(11, RMDebug::module_adminif, "ObjectBroker", "inserted from memory " << (*i).first); + retval->insert((*i).first); + } + RMDBGEXIT(11, RMDebug::module_adminif, "ObjectBroker", "getAllAtomicTypes() "); + return retval; + } + diff --git a/reladminif/oidif.hh b/reladminif/oidif.hh new file mode 100644 index 0000000..33ce760 --- /dev/null +++ b/reladminif/oidif.hh @@ -0,0 +1,307 @@ +#ifndef _OIDIF_HH_ +#define _OIDIF_HH_ + +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************ + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ***********************************************************************/ + + //@ManMemo: Module: {\bf adminif}. + +class OId; + +#include <iostream> + +#include "raslib/error.hh" + +#ifdef RMANBENCHMARK +#include "raslib/rmdebug.hh" +#endif + +//@ManMemo: Module: {\bf reladminif}. +/*@Doc: +the oid is a structure containing a counter and a type field. based on the type +it is possible to determine the type of the object the oid is refering to. +the counter is used to pinpoint the exact instance of the object. + +currently there are 19 different persistent classes. + +the counter and type information is encoded into a double: +ID_MULTIPLIER * counter + type; +the counters for each oid type are stored in the database. their exact value is read +when the transaction starts. the values are updated in the database at the end of a +transaction. this can be a problem with multiple concurrent open read/write +transactions. +*/ + + +class OId + { + public: + enum OIdType { INVALID = 0, + MDDOID, + MDDCOLLOID, + MDDTYPEOID, + MDDBASETYPEOID, + MDDDIMTYPEOID, + MDDDOMTYPEOID, + STRUCTTYPEOID, + SETTYPEOID, + BLOBOID, + DBMINTERVALOID, + STORAGEOID, + MDDHIERIXOID, + DBTCINDEXOID, + INLINETILEOID, + INNEROID, + ATOMICTYPEOID, + UDFOID, + UDFPACKAGEOID, + MDDRCIXOID}; + /*@Doc: + every persistent class needs a unique OIdType. + There is as always an exception: INNEROID is only used by DBTCIndex internally + */ + + typedef int OIdCounter; + /*@Doc: + every persistent object needs a unique OIdCounter within all persistent objects + with the same OIdType. + */ + + typedef double OIdPrimitive; + /*@Doc: + an oid can be converted from and to a primitive of this type. + */ + + static OIdPrimitive ID_MULTIPLIER; + /*@Doc: + is used to calculate the actual id and type from a given double + */ + + static void allocateOId(OId& id, OIdType type, OIdCounter howMany = 1); + /*@Doc: + allocates a OId for an object of the specified type or a whole bunch of them. + */ + + static void deinitialize(); + /*@Doc: + writes the current state of the oid counters back + into the database. + */ + + static void initialize(); + /*@Doc: + reads the state of the oid counters from the database. + */ + + OId::OIdType getType() const; + /*@Doc: + Returns type of the object with this OId. + */ + + OId(const OId& oldOId); + /*@Doc: + Copy constructor + */ + + OId(OIdCounter newId, OIdType type); + /*@Doc: + New OId with counter = newId, oidtype = type + */ + + OId(OIdPrimitive oidd); + /*@Doc: + generate a oid from a double. + */ + + OId(); + /*@Doc: + invalid oid + */ + + OIdCounter getCounter() const; + /*@Doc: + returns the counter part of the oid. + */ + + void print_status(std::ostream& s = std::cout) const; + /*@Doc: + prints a double + */ + + operator double() const; + /*@Doc: + converts the oid to a double: + oid * OId::ID_MULTIPLIER + oidtype; + */ + + static const char* counterNames[]; + /*@Doc: + holds the names of the counters in RAS_ADMIN, to go with counterIds + */ + + static unsigned int maxCounter; + + OId& operator=(const OId& old); + + bool operator== (const OId& one) const; + + bool operator!= (const OId& one) const; + + bool operator< (const OId& old) const; + + bool operator> (const OId& old) const; + + bool operator<= (const OId& old) const; + + bool operator>= (const OId& old) const; + + protected: + // protection agains writing back unloaded counters => inconsistent DB!! + static bool loadedOk; + + + OIdCounter oid; + /*@Doc: + the counter inside the oid + */ + + OIdType oidtype; + /*@Doc: + the type of object + */ + + static OIdCounter nextMDDOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextMDDCOLLOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextMDDTYPEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextMDDBASETYPEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextMDDDIMTYPEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextMDDDOMTYPEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextSTRUCTTYPEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextSETTYPEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextBLOBOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextDBMINTERVALOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextSTORAGEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextMDDHIERIXOID; + /*@Doc: + counter which holds the next oid + */ + + //static OIdCounter nextDBTCINDEXOID; + /*@Doc: + this counter is not used because mddhierix takes care of that + */ + + //static OIdCounter nextINLINETILEOID; + /*@Doc: + not used because they are the same as bloboid counter + */ + + static OIdCounter nextATOMICTYPEOID; + /*@Doc: + not used now because they are hard coded + */ + + static OIdCounter nextMDDRCIXOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextUDFOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter nextUDFPACKAGEOID; + /*@Doc: + counter which holds the next oid + */ + + static OIdCounter* counterIds[]; + /*@Doc: + holds all OIdCounters of next* sort, to go with the counterNames. + */ + + }; + +extern std::ostream& operator<<(std::ostream& in, const OId& d); + +extern std::ostream& operator<<(std::ostream& in, OId::OIdType d); + +extern bool operator== (const OId::OIdPrimitive one, const OId& two); + +extern bool operator== (const OId& two, const OId::OIdPrimitive one); + +#endif diff --git a/reladminif/oidif.pgc b/reladminif/oidif.pgc new file mode 100644 index 0000000..9f19254 --- /dev/null +++ b/reladminif/oidif.pgc @@ -0,0 +1,135 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +// This is -*- C++ -*- +/***************************************************************************** + * + * + * PURPOSE: + * + * + * COMMENTS: + * uses embedded SQL + * + *****************************************************************************/ + +static const char rcsid[] = "@(#)reladminif,OIdIf: $Id: oidif.ec,v 1.5 2003/12/27 23:11:43 rasdev Exp $"; + +#include "debug-srv.hh" + +// general embedded SQL related definitions +EXEC SQL include "sqlglobals.h"; + +#include "oidif.hh" +#include "raslib/rmdebug.hh" +#include "sqlerror.hh" +#include "adminif.hh" + +void +OId::initialize() +{ + RMDBGENTER(4, RMDebug::module_adminif, "OId", "initialize()"); + ENTER( "OId::initialize" ); + + loadedOk = false; + + EXEC SQL BEGIN DECLARE SECTION; + long nextoid; + char name[STRING_MAXLEN]; + EXEC SQL END DECLARE SECTION; + nextoid = 0; + for (int i = 1; i < maxCounter; i++) + { + (void) strncpy( name, (char*) counterNames[i], (size_t) sizeof(name) ); + + TALK( "EXEC SQL SELECT NextValue INTO :nextoid FROM RAS_COUNTERS WHERE CounterName = " << name ); + EXEC SQL SELECT NextValue INTO :nextoid + FROM RAS_COUNTERS + WHERE CounterName = :name; + TALK( "-> nextoid=" << nextoid ); + if (check("OId::initialize() SELECT OId")) + { + RMInit::logOut << "OId::initialize() error reading " << name << endl; + generateException(); + } + *counterIds[i] = nextoid; + RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "read " << counterNames[i] << " " << *counterIds[i]); + } + + loadedOk = true; + + LEAVE( "OId::initialize" ); + RMDBGEXIT(4, RMDebug::module_adminif, "OId", "initialize()"); +} + +void +OId::deinitialize() +{ + RMDBGENTER(4, RMDebug::module_adminif, "OId", "deinitialize()"); + ENTER( "OId::deinitialize" ); + + if (AdminIf::isReadOnlyTA()) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "do nothing is read only"); + } + else + { + if (AdminIf::isAborted()) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "do nothing is aborted"); + } + + else if(loadedOk==false) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "avoiding to write uninitialized counters into DB"); + } + + else + { + EXEC SQL BEGIN DECLARE SECTION; + long nextoid1; + char name2[STRING_MAXLEN]; + EXEC SQL END DECLARE SECTION; + + for (int i = 1; i < maxCounter; i++) + { + nextoid1 = *counterIds[i]; + (void) strncpy( name2, (char*) counterNames[i], (size_t) sizeof(name2) ); + + RMDBGMIDDLE(4, RMDebug::module_adminif, "OIdIf", "setting " << name2 << " to " << nextoid1) + TALK( "EXEC SQL UPDATE RAS_COUNTERS SET NextValue = " << nextoid1 << " WHERE CounterName = " << name2 ); + EXEC SQL UPDATE RAS_COUNTERS SET NextValue = :nextoid1 + WHERE CounterName = :name2; + if (check("OId::deinitialize() UPDATE OId")) + { + RMInit::logOut << "OId::deinitialize() error writing " << name2 << endl; + } + } + } + } + + loadedOk = false; + + LEAVE( "OId::deinitialize" ); + RMDBGEXIT(4, RMDebug::module_adminif, "OId", "deinitialize()"); +} + diff --git a/reladminif/oidifcommon.cc b/reladminif/oidifcommon.cc new file mode 100644 index 0000000..ed75ef3 --- /dev/null +++ b/reladminif/oidifcommon.cc @@ -0,0 +1,414 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +// This is -*- C++ -*- +/***************************************************************************** + * + * + * PURPOSE: + * code common to all database interface implementations + * + * + * COMMENTS: + * uses embedded SQL + * + *****************************************************************************/ +#include <string.h> +#include "oidif.hh" +#include "adminif.hh" +#include "databaseif.hh" +#include <stdlib.h> +#include "externs.h" +#include "sqlerror.hh" +#include "raslib/error.hh" +#include "raslib/rmdebug.hh" + +#ifdef RMANBENCHMARK +RMTimer +OId::oidAlloc("OId","allocateOId"); +#endif + +#ifdef RMANBENCHMARK +RMTimer +OId::oidResolve("OId","resolveOId"); +#endif + +double OId::ID_MULTIPLIER = 512; + +OId::OIdCounter OId::nextMDDOID = 0; + +OId::OIdCounter OId::nextMDDCOLLOID = 0; + +OId::OIdCounter OId::nextMDDTYPEOID = 0; + +OId::OIdCounter OId::nextMDDBASETYPEOID = 0; + +OId::OIdCounter OId::nextMDDDIMTYPEOID = 0; + +OId::OIdCounter OId::nextMDDDOMTYPEOID = 0; + +OId::OIdCounter OId::nextSTRUCTTYPEOID = 0; + +OId::OIdCounter OId::nextSETTYPEOID = 0; + +OId::OIdCounter OId::nextBLOBOID = 0; + +OId::OIdCounter OId::nextDBMINTERVALOID = 0; + +OId::OIdCounter OId::nextSTORAGEOID = 0; + +OId::OIdCounter OId::nextMDDHIERIXOID = 0; + +OId::OIdCounter OId::nextATOMICTYPEOID = 0; + +OId::OIdCounter OId::nextMDDRCIXOID = 0; + +OId::OIdCounter OId::nextUDFOID = 0; + +OId::OIdCounter OId::nextUDFPACKAGEOID = 0; + +unsigned int +OId::maxCounter = 20; + +const char* +OId::counterNames[] = { "INVALID", + "MDDOID", + "MDDCOLLOID", + "MDDTYPEOID", + "MDDBASETYPEOID", + "MDDDIMTYPEOID", + "MDDDOMTYPEOID", + "STRUCTTYPEOID", + "SETTYPEOID", + "BLOBOID", + "DBMINTERVALOID", + "STORAGEOID", + "MDDHIERIXOID", + "INLINEINDEXOID", + "INLINETILEOID", + "INNEROID", + "ATOMICTYPEOID", + "UDFOID", + "UDFPACKAGEOID", + "MDDRCIXOID" + }; + +OId::OIdCounter* +OId::counterIds[] = { + NULL, + &nextMDDOID, + &nextMDDCOLLOID, + &nextMDDTYPEOID, + &nextMDDBASETYPEOID, + &nextMDDDIMTYPEOID, + &nextMDDDOMTYPEOID, + &nextSTRUCTTYPEOID, + &nextSETTYPEOID, + &nextBLOBOID, + &nextDBMINTERVALOID, + &nextSTORAGEOID, + &nextMDDHIERIXOID, + &nextMDDHIERIXOID, + &nextBLOBOID, + &nextBLOBOID, + &nextATOMICTYPEOID, + &nextUDFOID, + &nextUDFPACKAGEOID, + &nextMDDRCIXOID + }; + +bool OId::loadedOk = false; + +void +OId::allocateOId(OId& id, OIdType type, OIdCounter howMany) + { + RMDBGENTER(4, RMDebug::module_adminif, "OId", "allocateOId(" << id << ", " << (OIdType)type << ")"); + if (howMany == 0) + { + RMInit::logOut << "OId::allocateOId(" << id << ", " << type << ", " << howMany << ") allocation of zero oids not supported" << endl; + throw r_Error(r_Error::r_Error_CreatingOIdFailed); + } + if (type == INVALID || type == INNEROID || type == ATOMICTYPEOID || type > maxCounter) + { + RMInit::logOut << "OIDs of the specified type (" << type << " cannot be allocated." << endl; + throw r_Error(r_Error::r_Error_CreatingOIdFailed); + } + else { + id.oid = *counterIds[type]; + *counterIds[type] = *counterIds[type] + howMany; + } + id.oidtype = type; + RMDBGEXIT(4, RMDebug::module_adminif, "OId", "allocateOId(" << id << ", " << type << ") "); + } + +OId::OId(const OId& oldOId) + { + RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId(" << oldOId << ")"); + oid = oldOId.oid; + oidtype = oldOId.oidtype; + RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId(" << oldOId << ")"); + } + +OId::OId() + { + RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId()"); + oidtype = INVALID; + oid = 0; + RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId()"); + } + +OId::OId(OIdPrimitive newId) + { + RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId(OIdPrimitive " << newId << ")"); + oid = newId / OId::ID_MULTIPLIER; + oidtype = (OId::OIdType)(newId - (OIdPrimitive)((OIdPrimitive)oid * OId::ID_MULTIPLIER)); + RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId(OIdPrimitive " << newId << ") ID " << oid << " TYPE " << oidtype); + } + +OId::OId(OIdCounter newId, OIdType type) + { + RMDBGENTER(4, RMDebug::module_adminif, "OId", "OId(" << newId << "," << type << ")"); + oidtype = type; + oid = newId; + RMDBGEXIT(4, RMDebug::module_adminif, "OId", "OId(" << newId << "," << type << ")"); + } + +OId::OIdType +OId::getType() const + { + RMDBGONCE(4, RMDebug::module_adminif, "OId", "getType() " << oidtype); + return oidtype; + } + +void +OId::print_status(ostream& s) const + { + s << this; + } + +OId::OIdCounter +OId::getCounter() const + { + RMDBGONCE(4, RMDebug::module_adminif, "OId", "getCounter() " << oid); + return oid; + } + +OId::operator double() const + { + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator() " << oid); + return oid * OId::ID_MULTIPLIER + oidtype; + } + +bool +OId::operator!= (const OId& one) const + { + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator!=(" << one << ") " << *this); + return !(OId::operator==(one)); + } + +bool +OId::operator== (const OId& one) const + { + bool retval = false; + if (oidtype == one.oidtype) + { + retval = (oid == one.oid); + } + else { + retval = false; + } + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator==(" << one << ") " << *this << " retval=" << retval); + return retval; + } + +OId& +OId::operator=(const OId& old) + { + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator=(" << old << ") "<< *this); + if (this != &old) + { + oid = old.oid; + oidtype = old.oidtype; + } + return *this; + } + +bool +OId::operator<(const OId& old) const + { + bool retval = false; + if (oidtype == old.oidtype) + { + retval = (oid < old.oid); + } + else { + retval = (oidtype < old.oidtype); + } + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator<(" << old << ") " << *this << " retval=" << retval); + return retval; + } + +bool +OId::operator>(const OId& old) const + { + bool retval = false; + if (oidtype == old.oidtype) + { + retval = (oid > old.oid); + } + else { + retval = (oidtype > old.oidtype); + } + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator>(" << old << ") " << *this << " retval=" << retval); + return retval; + } + +bool +OId::operator<=(const OId& old) const + { + bool retval = false; + if (oidtype == old.oidtype) + { + retval = (oid <= old.oid); + } + else { + retval = (oidtype < old.oidtype); + } + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator<=(" << old << ") " << *this << " retval=" << retval); + return retval; + } + +bool +OId::operator>=(const OId& old) const + { + bool retval = false; + if (oidtype == old.oidtype) + { + retval = (oid >= old.oid); + } + else { + retval = (oidtype > old.oidtype); + } + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator>=(" << old << ") " << *this << " retval=" << retval); + return retval; + } + +bool +operator== (const double one, const OId& two) + { + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator==(" << one << "," << two << ")"); + bool retval=false; + if (((double)two) == one) + retval=true; + return retval; + } + +bool +operator== (const OId& two, const double one) + { + RMDBGONCE(4, RMDebug::module_adminif, "OId", "operator==(" << two << "," << one << ")"); + bool retval=false; + if (((double)two) == one) + retval=true; + return retval; + } + +std::ostream& +operator<<(std::ostream& s, const OId& d) + { + s << "OId(" << d.getCounter() << ":" << d.getType() << ")"; + return s; + } + +std::ostream& +operator<<(std::ostream& s, OId::OIdType d) + { + switch (d) + { + case OId::INVALID: + s << "INVALID"; + break; + case OId::MDDOID: + s << "MDDOID"; + break; + case OId::MDDCOLLOID: + s << "MDDCOLLOID"; + break; + case OId::MDDTYPEOID: + s << "MDDTYPEOID"; + break; + case OId::MDDBASETYPEOID: + s << "MDDBASETYPEOID"; + break; + case OId::MDDDIMTYPEOID: + s << "MDDDIMTYPEOID"; + break; + case OId::MDDDOMTYPEOID: + s << "MDDDOMTYPEOID"; + break; + case OId::STRUCTTYPEOID: + s << "STRUCTTYPEOID"; + break; + case OId::SETTYPEOID: + s << "SETTYPEOID"; + break; + case OId::BLOBOID: + s << "BLOBOID"; + break; + case OId::DBMINTERVALOID: + s << "DBMINTERVALOID"; + break; + case OId::STORAGEOID: + s << "STORAGEOID"; + break; + case OId::MDDHIERIXOID: + s << "MDDHIERIXOID"; + break; + case OId::DBTCINDEXOID: + s << "DBTCINDEXOID"; + break; + case OId::INLINETILEOID: + s << "INLINETILEOID"; + break; + case OId::INNEROID: + s << "INNEROIDOID"; + break; + case OId::ATOMICTYPEOID: + s << "ATOMICTYPEOID"; + break; + case OId::UDFOID: + s << "UDFOID"; + break; + case OId::UDFPACKAGEOID: + s << "UDFPACKAGEOID"; + break; + case OId::MDDRCIXOID: + s << "MDDRCIXOID"; + break; + default: + s << "UNKNOWN: " << (int)d; + break; + } + return s; + } + + diff --git a/reladminif/sqlerror.hh b/reladminif/sqlerror.hh new file mode 100644 index 0000000..869fb86 --- /dev/null +++ b/reladminif/sqlerror.hh @@ -0,0 +1,118 @@ +#ifndef _SQLERROR_HH_ +#define _SQLERROR_HH_ + +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************ + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ***********************************************************************/ + +//@ManMemo: Module: {\bf reladminif}. + +/*@Doc: + + SQL Errors Handling + +*/ +#include <iostream> +using std::cout; +using std::endl; + +#include "raslib/error.hh" + +#ifdef BASEDB_DB2 +#define generateException() generateExceptionn(sqlca) + +void generateExceptionn(struct sqlca&) throw (r_Error); + +/*@Doc: +generates a new r_Ebase_dbms exception and throws it. +*/ + +#define check(msg) checkk(msg, sqlca) +int checkk(const char* msg, struct sqlca& mysql) throw( r_Error ); + /*@Doc: + returns sqlcode, prints error messages when appropriate. + the msg is inserted in the error message. + changes are not rolledback, nothing is done to the connection. + */ + +#endif + +#ifdef BASEDB_ORACLE +void generateException() throw (r_Error); +/*@Doc: +generates a new r_Ebase_dbms exception and throws it. +*/ + +int check(const char* msg) throw (r_Error); +/*@Doc: +returns sqlcode, prints error messages when appropriate. +the msg is inserted in the error message. +changes are not rolledback, nothing is done to the connection. +*/ + +void printSQLError(void* err, int status); +void printSQLError(void* err) throw (r_Error); +/*@Doc: +This diplays cli errors. +*/ +#endif + +#ifdef BASEDB_INFORMIX +void generateException() throw (r_Error); +/*@Doc: +This generates exceptions. +*/ + +int check(const char* msg, bool displayWarning = false) throw (r_Error); +/*@Doc: +This diplays esql errors. +*/ + +void printSQLError(int error, const char*); +/*@Doc: +This diplays cli errors. +*/ +#endif + +#ifdef BASEDB_PGSQL +void generateException() throw (r_Error); +/*@Doc: +This generates exceptions. +*/ + +int check(const char* msg) throw (r_Error); +/*@Doc: +Display error message if SQL errors have occurred. +*/ +#endif + +#endif + diff --git a/reladminif/sqlerror.pgc b/reladminif/sqlerror.pgc new file mode 100644 index 0000000..94d41a3 --- /dev/null +++ b/reladminif/sqlerror.pgc @@ -0,0 +1,198 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +// This is -*- C++ -*- +/************************************************************************* + * + * + * PURPOSE: + * process base DBMS errors (PostgreSQL) by printing messages and throwing exceptions. + * + * + * COMMENTS: + * - different from other implementations in that no distinction between + * error and warning + * - the whole module should be redesigned for all DBMSs - very unconcise + * - no function printSQLError() as eg in Informix + * - FIXME: generateException() should be declared r_Ebase_dbms instead of r_Error + * + ***********************************************************************/ + +static const char rcsid[] = "@(#)reladminif,SQLError: $Id: sqlerror.ec,v 1.4 2003/12/27 23:11:43 rasdev Exp $"; + +// #define SQLCA_STORAGE_CLASS extern + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "sqlerror.hh" +#include "externs.h" + +#include "raslib/rmdebug.hh" +#include "raslib/error.hh" +#include "debug-srv.hh" + +// general embedded SQL related definitions +EXEC SQL include "sqlglobals.h"; + +// SQLSTATE not available in PGSQL (SQLCODE is, funny enough) +#define SQLSTATE sqlca.sqlstate + +// error codes +EXEC SQL define SUCCESS 0; +EXEC SQL define WARNING 1; +EXEC SQL define NODATA 100; +EXEC SQL define RTERROR -1; + +// general message buffer size +#define BUFFER_SIZE 4000 + +// SQL error message max size +// FIXME: is this really enough? +const int MSG_MAXLEN=BUFFER_SIZE; + +// length of buffer for remembering last message +#define LASTERRORMSGLEN BUFFER_SIZE +char lastErrorMsg[LASTERRORMSGLEN]; + +/* + * The sqlstate_err() function checks the SQLSTATE status variable to see + * if an error or warning has occurred following an SQL statement. + */ +int sqlstate_err() +{ + int err_code = RTERROR; + + if (SQLSTATE[0] == '0') /* trap '00', '01', '02' */ + { + switch(SQLSTATE[1]) + { + case '0': /* success - return 0 */ + err_code = SUCCESS; + break; + case '1': /* warning - return 1 */ + err_code = WARNING; + break; + case '2': /* end of data - return 100 */ + err_code = NODATA; + break; + default: /* error - return SQLCODE */ + break; + } + } + return err_code; +} // sqlstate_err() + + +/* + * The disp_sqlstate_err() function prints details into msgbuf. + */ +void disp_sqlstate_err(char* msgbuf, size_t length) +{ + char error_buffer[BUFFER_SIZE]; + size_t characters_written = 0; + + snprintf(error_buffer, BUFFER_SIZE, "SQLSTATE: %5s SQLCODE: %d\n", SQLSTATE, SQLCODE); + characters_written = strlen(error_buffer); + if (characters_written > length) + { + RMInit::logOut << "error message didn't fit into buffer: " << error_buffer << endl; + } + else + { + strcat(msgbuf, error_buffer); + } +} // disp_sqlstate_err() + +/* + * disp_error(): print statement and error/warning text into buffer + */ +void disp_error(const char* stmt, char* msgbuf, size_t length) +{ + char error_buffer[BUFFER_SIZE]; + snprintf(error_buffer, BUFFER_SIZE, "Warning/error in %s:\n", stmt); + + size_t error_len = strlen(error_buffer); + + if (error_len > length) + RMInit::logOut << "error message didn't fit into buffer: " << error_buffer << endl; + else + { + strcat(msgbuf, error_buffer); + length = length - error_len; + } + disp_sqlstate_err(msgbuf, length); +} // disp_error() + +/* + * disp_exception(): if sql_errcode says there was an error, + * allocate msg buffer and copy error msg + */ +char* disp_exception(const char* stmt, int sqlerr_code) +{ + char* msgbuf = NULL; + switch (sqlerr_code) + { + case SUCCESS: + case NODATA: + break; + case WARNING: + case RTERROR: + msgbuf = new char[BUFFER_SIZE]; + memset(msgbuf, 0, BUFFER_SIZE); + disp_error(stmt, msgbuf, BUFFER_SIZE); + break; + default: + RMInit::logOut << "Invalid exception state for " << stmt << " " << sqlerr_code << endl; + break; + } + return msgbuf; +} // disp_exception() + +/* + * check(): check base DBMS for any error occurred during last + * database access and print message into log if so. + */ +int +check(const char* stmt) throw (r_Error) +{ + char* msg = disp_exception(stmt, sqlstate_err()); + if (msg != NULL) + { + RMInit::logOut << msg << endl; + snprintf(lastErrorMsg, LASTERRORMSGLEN, msg); + delete [] msg; + msg = NULL; + } + return SQLCODE; +} + +// generate r_Ebase_dbms exception using SQL error code and message +void +generateException() throw (r_Error) +{ + TALK( "Throwing Exception (SQLCODE=" << SQLCODE << "): " << lastErrorMsg ); + RMInit::dbgOut << "Throwing Exception (SQLCODE=" << SQLCODE << "): " << lastErrorMsg << endl; + throw r_Ebase_dbms( SQLCODE, lastErrorMsg ); +} // generateException() + diff --git a/reladminif/sqlglobals.h b/reladminif/sqlglobals.h new file mode 100644 index 0000000..5ac83cf --- /dev/null +++ b/reladminif/sqlglobals.h @@ -0,0 +1,50 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/***************************************************************************** + * + * + * PURPOSE: + * provide global definitions for embedded SQL usage (any base DBMS) + * + * + * COMMENTS: + * - further SQL-relevant constants for C++ usage can be found in externs.h + * + *****************************************************************************/ + +#ifndef _SQLGLOBALS_H_ +#define _SQLGLOBALS_H_ + +// this syntax should be the same for all embedded SQL versions +// right now only tested & used with Informix, though + +// max length of varchar attributes and other string buffers; incl padding zero +// see $(INFORMIXDIR)/incl/esql/varchar.h +// unfortunately there it is not made known to ESQL, so we must use a literal here +EXEC SQL define VARCHAR_MAXLEN 255; +EXEC SQL define STRING_MAXLEN 255; + +// SQL query string buffer size +#define SQL_QUERY_BUFFER_SIZE 400 + +#endif // _SQLGLOBALS_H_ diff --git a/reladminif/test/Makefile b/reladminif/test/Makefile new file mode 100644 index 0000000..40097a2 --- /dev/null +++ b/reladminif/test/Makefile @@ -0,0 +1,90 @@ +# -*-Makefile-*- +# +# This file is part of rasdaman community. +# +# Rasdaman community is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Rasdaman community 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +# +# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +# rasdaman GmbH. +# +# For more information please see <http://www.rasdaman.org> +# or contact Peter Baumann via <baumann@rasdaman.com>. # Top Level makefile. This points to the various modules that have to be build +# and/or deployed +# +# MAKEFILE FOR: +# reladminif tests. +# +# COMMENTS: +# - List environment dependencies, known bugs, specialities etc. +# +################################################################## +######################### Definitions ############################ + +# all test programs +ALLTESTS = test_databaseif dbreftest admintest perstest eoidtest dbnamedobjtest testindex testconnect test_databaseif + +# Needed rasdaman libraries for linking. To be completed. +NEEDEDLIBS = $(CACHETAMGR) $(QLPARSER) $(INDEXMGR) $(RELADMINIF) $(RELMDDIF) $(RELBLOBIF) $(RELINDEXIF) $(CACHETAMGR) $(RELCATALOGIF) $(RASLIB) $(RELADMINIF) $(RELMDDIF) + +# insert names of source files which need STL<TOOLKIT> +# also insert names of source files which include .hh files which need stl +NEEDSTL := dbreftest.C eoidtest.C admintest.C perstest.C dbnamedobjtest.C testindex.c + +# insert any files that are not object, bind or generated .c/.C files +# e.g.: libs +MISCCLEAN := client.bm client.dbg client.log ir.out core + +# insert object files here. makes only sense if oracle and db2 files are the same +OBJS := dbreftest.o admintest.o perstest.o eoidtest.o dbnamedobjtest.o testindex.o testconnect.o test_databaseif.o + +# add to compile flag set +CXXFLAGS += $(I_SYM)$(RMANBASE)/raslib + +########################### Targets ############################## + +# make all tests +.PHONY: test +test: $(ALLTESTS) + +indextest.o: indextest.cc + $(CXX) -c $(BASEDBCXXFLAGS) $(STLCXXFLAGS) $(CXXFLAGS) $< + +######################## Dependencies ############################ + +admintest: admintest.o $(NEEDEDLIBS) +admintest.o: admintest.C + +dbreftest: dbreftest.o +dbreftest.o: dbreftest.C + +eoidtest: eoidtest.o +eoidtest.o: eoidtest.C + +dbnamedobjtest: dbnamedobjtest.o +dbnamedobjtest.o: dbnamedobjtest.C + +perstest: perstest.o +perstest.o: perstest.C + +dbcheck.o: dbcheck.c +dbcheck.c: dbcheck.pc +dbcheck: dbcheck.o + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -L/home/proj/rasdaman/3rdParty/linux/lib -L$(RMANHOME)/lib -Xlinker -Bstatic $(LIBAKINSIDE) -lmddmgr -ltilemgr -lindexmgr -lcatalogmgr -lstoragemgr -lreladminif -lrelmddif -lrelstorageif -lrelindexif -lrelcatalogif -lrelblobif -lcompression -lconversion -lraslib $(RMANHOME)/mymalloc/mymalloc_svc.o -lpng -ltiff -ljpeg -lmfhdf -ldf -lz $(REL_STATIC_LIBS) + +check: check.o + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ -L$(RMANHOME)/lib -Xlinker -Bstatic $(LIBAKINSIDE) -lmddmgr -ltilemgr -lindexmgr -lcatalogmgr -lstoragemgr -lreladminif -lrelmddif -lrelstorageif -lrelindexif -lrelcatalogif -lrelblobif -lcompression -lconversion -lraslib $(RMANHOME)/mymalloc/mymalloc_svc.o -lpng -ltiff -ljpeg -lmfhdf -ldf -lz $(REL_STATIC_LIBS) + +test_databaseif: test_databaseif.o ../databaseif.o + $(PURIFY) $(CXX) $(LDFLAGS) -o $@ $^ $(RMANBASE)/mymalloc/mymalloc_svc.o ../sqlerror.o ../oidif.o ../adminif.o -L$(RMANBASE)/lib -lraslib -lrasodmg $(BASEDBLDFLAGS) + diff --git a/reladminif/test/admintest.C b/reladminif/test/admintest.C new file mode 100644 index 0000000..adf0d94 --- /dev/null +++ b/reladminif/test/admintest.C @@ -0,0 +1,92 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "raslib/rmdebug.hh" +#include <iostream.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "adminif.hh" +#include "databaseif.hh" +#include "transactionif.hh" +#include "raslib/rmdebug.hh" +#include "externs.h" + +RMINITGLOBALS('C') + + +int +main(int argc, char *argv[]) + { + int RManDebug2 = 5; + int RManModule = 1; + DatabaseIf database; + TransactionIf ta; + char* name = 0; + + if (argc == 2) + name = argv[1]; + else + name = "RASBASE"; + + cout << "OPENING DATABASEIF" << endl; + if (database.open(name)) + { + cout << "ERROR OPENING DATABASE" << endl; + return -1; + } + cout << "OPENED DATABASEIF" << endl; + + if (!database.databaseExists()) + { + cout << "DATABASE EXISTS NOT" << endl; + cout << "CREATEING DATABASE" << endl; + database.create(name, 0, 0); + cout << "DATABASE CREATED" << endl; + } + else { + cout << "DATABASE EXISTS" << endl; + cout << "BEGINNING TRANSACTIONIF" << endl; + ta.begin(&database); + cout << "TRANSACTIONIF BEGUN" << endl; + cout << "DESTROYING DATABASE" << endl; + database.destroyDB(&ta, name); + cout << "DATABASE DESTROYED" << endl; + } + cout << "CLOSING DATABASEIF" << endl; + database.close(); + cout << "CLOSED DATABASEIF" << endl; + + cout << "OPENING DATABASEIF" << endl; + if (database.open(name)) + { + cout << "ERROR OPENING DATABASE" << endl; + return -1; + } + cout << "OPENED DATABASEIF" << endl; + if (database.databaseExists()) + cout << "DATABASE EXISTS" << endl; + else + cout << "DATABASE EXISTS NOT" << endl; + database.close(); + cout << "CLOSED DATABASEIF" << endl; + } diff --git a/reladminif/test/check.cc b/reladminif/test/check.cc new file mode 100644 index 0000000..44e5892 --- /dev/null +++ b/reladminif/test/check.cc @@ -0,0 +1,301 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/* +get mddoid, iterate domain, dataformat + +select mdd +get domain + { + begin ta + iterate over domain + retrieve tiles + alter tiles + commit ta + } +*/ + +#ifdef EARLY_TEMPLATE +#define __EXECUTABLE__ +#include "server/template_inst.hh" +#endif + +#include "reladminif/adminif.hh" +#include "reladminif/databaseif.hh" +#include "reladminif/transactionif.hh" +#include "reladminif/oidif.hh" +#include "mddmgr/mddobj.hh" +#include "tilemgr/tile.hh" +#include "cmlparser.hh" +#include "raslib/mitera.hh" + +#define ALLDONE 0 +#define ERRORPARSINGCOMMANDLINE 1 +#define DOMAINMISSING 2 +#define OIDMISSING 3 +#define OIDINVALID 4 +#define DOMAINMISMATCH 5 +#define FAILED 6 +#define DOMAININVALID 7 +#define UNKNOWNDATAFORMAT 8 + +char globalConnectId[256]; + +RMINITGLOBALS('S') + +r_Minterval domain; +OId oid; + +int +main(int argc, char** argv) + { + RMInit::logOut.rdbuf(cout.rdbuf()); + RMInit::dbgOut.rdbuf(cout.rdbuf()); + int retval = 0; + CommandLineParser &cmlInter = CommandLineParser::getInstance(); + CommandLineParameter &clp_help = cmlInter.addFlagParameter('h', "help", "show command line switches"); + CommandLineParameter &clp_connect = cmlInter.addStringParameter(CommandLineParser::noShortName, "connect", "database connect string", "/"); + CommandLineParameter &clp_mdddomain = cmlInter.addStringParameter(CommandLineParser::noShortName, "mdddomain", "the domain to do the changes in."); + CommandLineParameter &clp_domain = cmlInter.addStringParameter(CommandLineParser::noShortName, "domain", "the extent to be used when selecting data from the mdd."); + CommandLineParameter &clp_oid = cmlInter.addStringParameter(CommandLineParser::noShortName, "oid", "the oid of the mdd to operate on"); + CommandLineParameter &clp_comptype = cmlInter.addStringParameter(CommandLineParser::noShortName, "storageformat", "name of storage format", "Array"); + CommandLineParameter &clp_readonly = cmlInter.addFlagParameter('r', "readonly", "read only check"); + try { + cmlInter.processCommandLine(argc, argv); + } + catch(CmlException& err) + { + cmlInter.printHelp(); + cout << "Error parsing command line:" << endl; + cout << err.what() << endl; + return ERRORPARSINGCOMMANDLINE; + } + if (cmlInter.isPresent('h')) + { + cmlInter.printHelp(); + return ALLDONE; + } + r_Data_Format storageFormat = r_Array; + if (cmlInter.isPresent("storageformat")) + { + storageFormat = get_data_format_from_name(cmlInter.getValueAsString("storageformat")); + if (storageFormat == r_Data_Format_NUMBER) + { + cout << "unknown data format " << cmlInter.getValueAsString("storageformat") << endl; + return UNKNOWNDATAFORMAT; + } + } + if (!cmlInter.isPresent("domain")) + { + cout << "domain is missing" << endl; + return DOMAINMISSING; + } + if (!cmlInter.isPresent("oid")) + { + cout << "oid is missing" << endl; + return OIDMISSING; + } + strcpy((char*)globalConnectId, cmlInter.getValueAsString("connect")); + cout << "connect " << globalConnectId << endl; + try { + domain = r_Minterval(cmlInter.getValueAsString("domain")); + } + catch (const r_Error& e) + { + cout << "domain is not valid: " << e.what() << " " << e.get_errorno() << endl; + return DOMAININVALID; + } + oid = OId(atol(cmlInter.getValueAsString("oid"))); + if (oid.getType() != OId::MDDOID) + { + cout << "oid is not a mdd oid" << endl; + return OIDINVALID; + } + bool readonly = cmlInter.isPresent("readonly"); + if (readonly) + { + cout << "performing read only check" << std::endl; + } + else { + cout << "performing recompression" << std::endl; + } + cout << "set up done" << endl; + AdminIf::instance(); + DatabaseIf d; + TransactionIf t; + MDDObj* mdd = NULL; + r_Minterval completeDomain; + r_MiterArea* miter = NULL; + try { + d.open("RASBASE"); + t.begin(&d, true); + mdd = new MDDObj(oid); + if (mdd->getCurrentDomain().dimension() == domain.dimension()) + { + completeDomain = mdd->getCurrentDomain(); + if (cmlInter.isPresent("mdddomain")) + { + try { + r_Minterval temp(cmlInter.getValueAsString("mdddomain")); + if (temp.dimension() == completeDomain.dimension()) + { + cout << "Not using complete mdd domain (" << completeDomain << ") but " << temp << endl; + completeDomain = temp; + } + else { + cout << "Domains do not have same number of dimensions" << endl; + delete mdd; + mdd = NULL; + t.commit(); + d.close(); + return DOMAINMISMATCH; + } + } + catch (const r_Error& e2) + { + cout << "mdddomain parameter is not correct: " << e2.get_errorno() << " " << e2.what() << endl; + delete mdd; + mdd = NULL; + t.commit(); + d.close(); + return DOMAININVALID; + } + } + miter = new r_MiterArea(&domain, &completeDomain); + } + else { + t.commit(); + d.close(); + return DOMAINMISMATCH; + } + delete mdd; + mdd = NULL; + t.commit(); + d.close(); + } + catch (const r_Error& e) + { + delete miter; + miter = NULL; + cout << "Caught exception " << e.get_errorno() << " " << e.what() << endl; + try { + t.abort(); + } + catch (const r_Error& ee) + { + cout << "Caugh exception while aborting " << ee.get_errorno() << " " << ee.what() << endl; + try { + t.abort(); + } + catch (const r_Error& eee) + { + cout << "Caugh exception while 2nd aborting " << eee.get_errorno() << " " << eee.what() << endl; + } + } + try { + d.close(); + } + catch (const r_Error& eeee) + { + cout << "Caugh exception while closing " << eeee.get_errorno() << " " << eeee.what() << endl; + } + return FAILED; + } + std::vector<Tile*>* tiles = NULL; + std::vector<Tile*>::iterator here; + std::vector<Tile*>::iterator end; + r_Minterval currentDomain; + while (!miter->isDone()) + { + currentDomain = miter->nextArea(); + try { + d.open("RASBASE"); + t.begin(&d, readonly); + mdd = new MDDObj(oid); + tiles = mdd->intersect(currentDomain); + end = tiles->end(); + if (tiles) + { + cout << "working on " << currentDomain << " with " << tiles->size() << " tiles" << endl; + for (here = tiles->begin(); here < end; here++) + { + cout << " tile " << (*here)->getDomain() << " " << (*here)->getDBTile()->getOId() << " " << (*here)->getDataFormat() << " " << (*here)->getCompressedSize(); + if (!(*here)->decompress()) + { + cout << " decompress failed"; + } + if (((*here)->getDataFormat() != storageFormat) && (!readonly)) + { + cout << " changing storage format"; + (*here)->setCompressionFormat(storageFormat); + cout << " compressed size " << (*here)->getCompressedSize(); + } + cout << endl; + } + } + else { + cout << currentDomain << " no tiles" << endl; + } + delete mdd; + mdd = NULL; + delete tiles; + tiles = NULL; + t.commit(); + d.close(); + } + catch (const r_Error& e) + { + delete miter; + miter = NULL; + delete tiles; + tiles = NULL; + cout << "Caught exception " << e.get_errorno() << " " << e.what() << endl; + try { + t.abort(); + } + catch (const r_Error& ee) + { + cout << "Caugh exception while aborting " << ee.get_errorno() << " " << ee.what() << endl; + try { + t.abort(); + } + catch (const r_Error& eee) + { + cout << "Caugh exception while 2nd aborting " << eee.get_errorno() << " " << eee.what() << endl; + } + } + try { + d.close(); + } + catch (const r_Error& eeee) + { + cout << "Caugh exception while closing " << eeee.get_errorno() << " " << eeee.what() << endl; + } + return FAILED; + } + } + delete tiles; + tiles = NULL; + delete miter; + miter = NULL; + return retval; + } diff --git a/reladminif/test/dbnamedobjtest.C b/reladminif/test/dbnamedobjtest.C new file mode 100644 index 0000000..e0c47f4 --- /dev/null +++ b/reladminif/test/dbnamedobjtest.C @@ -0,0 +1,88 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "mymalloc/mymalloc.h" +#include "raslib/rmdebug.hh" +#include <iostream.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "dbnamedobject.hh" + +RMINITGLOBALS('C') + +int RManDebug2 = 6; +int RManModule = 4; + +int +main(int argc, char *argv[]) + { + if (argc == 1) + { + cout << "Usage:" << endl; + cout << "\t1\t: " << endl << "\t\t" << endl; + } + else { + cout << "arg 1: " << argv[0] << " arg 2: " << argv[1] << " arg 3: " << argv[2] << endl; + OId* id = 0; + DBNamedObject* obj = 0; + char* text = (char*)mymalloc(sizeof(char) * 300); + struct { + short length; + char data[200]; + } VARCHAR; + + cout << "DATADUMP\t:" << VARCHAR.data << endl; + strcpy(VARCHAR.data, "aslkjfdhaskldjfjsd\0askdjfhdkjsladf\0laksjddf\0"); + cout << "DATADUMP\t:" << VARCHAR.data << endl; + switch (atoi(argv[1])) + { + case 1: + strcpy(text, "maxidaxi\0waxitaxi"); +// id = new OId(1,1); + DBNamedObject::MAXNAMELENGTH = atoi(argv[2]); + cout << "Name: " << text << endl; + obj = new DBNamedObject(text);//*id, text); + cout << "Get Name: " << obj->getName() << endl; + break; + case 2: + DBNamedObject::MAXNAMELENGTH = atoi(argv[2]); + obj = new DBNamedObject(text);//*id, text); + cout << "Get Name: " << obj->getName() << endl; + VARCHAR.length = atoi(argv[3]); + obj->setName(VARCHAR.length, (char*)VARCHAR.data); + cout << "Get Name: " << obj->getName() << endl; + break; + case 3: + DBNamedObject::MAXNAMELENGTH = atoi(argv[2]); + obj = new DBNamedObject(); + cout << "Get Name: " << obj->getName() << endl; + VARCHAR.length = atoi(argv[3]); + obj->setName(VARCHAR.length, (char*)VARCHAR.data); + cout << "Get Name: " << obj->getName() << endl; + break; + default: + cout << "DONT KNOW WHAT TO DO" << endl; + break; + } + } + } diff --git a/reladminif/test/dbreftest.C b/reladminif/test/dbreftest.C new file mode 100644 index 0000000..5c62b64 --- /dev/null +++ b/reladminif/test/dbreftest.C @@ -0,0 +1,70 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "raslib/rmdebug.hh" +#include <iostream.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "dbnamedobject.hh" +#include "dbref.hh" +#include "dbobject.hh" +#include "oidif.hh" +#include "adminif.hh" +#include "databaseif.hh" +#include "oidif.hh" +#include "transactionif.hh" + +#include "alltypes.hh" +#include "typefactory.hh" + +#include "dbmddcoll.hh" +#include "dbmddcolloidentry.hh" +#include "dbmddobj.hh" + +#include "raslib/rmdebug.hh" + +RMINITGLOBALS('C') + +int RManDebug2 = 8; +int RManModule = 3; + +int +main(int argc, char *argv[]) + { + OId t(10, OId::BASETYPEOID); + + AdminIf* myAdmin; + DatabaseIf database; + TransactionIf ta; + RManDebug = 6; + + myAdmin = AdminIf::instance(); + database.open("RMAN"); + ta.begin(&database); + + DbRef<BaseType> p(t); + cout << "Type " << p->getName() << endl; + + ta.abort(); + database.close(); + } diff --git a/reladminif/test/demobld.sql b/reladminif/test/demobld.sql new file mode 100644 index 0000000..0895e87 --- /dev/null +++ b/reladminif/test/demobld.sql @@ -0,0 +1,125 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +-- +-- $Header: /home/rasdev/CVS-repository/rasdaman/reladminif/test/demobld.sql,v 1.3 2003/12/27 23:11:46 rasdev Exp $ +-- Copyright (c) Oracle Corporation 1988, 1993. All Rights Reserved. +-- +-- +-- This script creates the SQL*Plus demonstration tables. +-- +-- It should be STARTed by each user wishing to access the tables. +-- + +set termout on +prompt Building demonstration tables. Please wait. +set termout off +set feedback off + +ALTER SESSION SET NLS_LANGUAGE = AMERICAN; +ALTER SESSION SET NLS_TERRITORY = AMERICA; + +DROP TABLE EMP; +DROP TABLE DEPT; +DROP TABLE BONUS; +DROP TABLE SALGRADE; +DROP TABLE DUMMY; + +CREATE TABLE EMP + (EMPNO NUMBER(4) NOT NULL, + ENAME VARCHAR2(10), + JOB VARCHAR2(9), + MGR NUMBER(4), + HIREDATE DATE, + SAL NUMBER(7,2), + COMM NUMBER(7,2), + DEPTNO NUMBER(2)); + +INSERT INTO EMP VALUES + (7369,'SMITH','CLERK',7902,'17-DEC-80',800,NULL,20); +INSERT INTO EMP VALUES + (7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600,300,30); +INSERT INTO EMP VALUES + (7521,'WARD','SALESMAN',7698,'22-FEB-81',1250,500,30); +INSERT INTO EMP VALUES + (7566,'JONES','MANAGER',7839,'2-APR-81',2975,NULL,20); +INSERT INTO EMP VALUES + (7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250,1400,30); +INSERT INTO EMP VALUES + (7698,'BLAKE','MANAGER',7839,'1-MAY-81',2850,NULL,30); +INSERT INTO EMP VALUES + (7782,'CLARK','MANAGER',7839,'9-JUN-81',2450,NULL,10); +INSERT INTO EMP VALUES + (7788,'SCOTT','ANALYST',7566,'09-DEC-82',3000,NULL,20); +INSERT INTO EMP VALUES + (7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000,NULL,10); +INSERT INTO EMP VALUES + (7844,'TURNER','SALESMAN',7698,'8-SEP-81',1500,0,30); +INSERT INTO EMP VALUES + (7876,'ADAMS','CLERK',7788,'12-JAN-83',1100,NULL,20); +INSERT INTO EMP VALUES + (7900,'JAMES','CLERK',7698,'3-DEC-81',950,NULL,30); +INSERT INTO EMP VALUES + (7902,'FORD','ANALYST',7566,'3-DEC-81',3000,NULL,20); +INSERT INTO EMP VALUES + (7934,'MILLER','CLERK',7782,'23-JAN-82',1300,NULL,10); + +CREATE TABLE DEPT + (DEPTNO NUMBER(2), + DNAME VARCHAR2(14), + LOC VARCHAR2(13) ); + +INSERT INTO DEPT VALUES + (10,'ACCOUNTING','NEW YORK'); +INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS'); +INSERT INTO DEPT VALUES + (30,'SALES','CHICAGO'); +INSERT INTO DEPT VALUES + (40,'OPERATIONS','BOSTON'); + +CREATE TABLE BONUS + ( + ENAME VARCHAR2(10), + JOB VARCHAR2(9), + SAL NUMBER, + COMM NUMBER + ); + +CREATE TABLE SALGRADE + ( GRADE NUMBER, + LOSAL NUMBER, + HISAL NUMBER ); + +INSERT INTO SALGRADE VALUES (1,700,1200); +INSERT INTO SALGRADE VALUES (2,1201,1400); +INSERT INTO SALGRADE VALUES (3,1401,2000); +INSERT INTO SALGRADE VALUES (4,2001,3000); +INSERT INTO SALGRADE VALUES (5,3001,9999); + +CREATE TABLE DUMMY + ( DUMMY NUMBER ); + +INSERT INTO DUMMY VALUES (0); + +COMMIT; + +EXIT; diff --git a/reladminif/test/demodrop.sql b/reladminif/test/demodrop.sql new file mode 100644 index 0000000..282bf6d --- /dev/null +++ b/reladminif/test/demodrop.sql @@ -0,0 +1,42 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +-- +-- $Header: /home/rasdev/CVS-repository/rasdaman/reladminif/test/demodrop.sql,v 1.3 2003/12/27 23:11:46 rasdev Exp $ +-- Copyright (c) Oracle Corporation 1988, 1993. All Rights Reserved. +-- +-- +-- This script drops the SQL*Plus demonstration tables. +-- +-- It should be STARTed by each owner of the tables. + +set termout on +prompt Dropping demonstration tables. Please wait. +set termout off + +DROP TABLE EMP; +DROP TABLE DEPT; +DROP TABLE BONUS; +DROP TABLE SALGRADE; +DROP TABLE DUMMY; + +EXIT; diff --git a/reladminif/test/eoidtest.C b/reladminif/test/eoidtest.C new file mode 100644 index 0000000..66aa0ee --- /dev/null +++ b/reladminif/test/eoidtest.C @@ -0,0 +1,128 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "raslib/rmdebug.hh" +#include <iostream.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "dbnamedobject.hh" +#include "dbref.hh" +#include "dbobject.hh" +#include "oidif.hh" +#include "adminif.hh" +#include "databaseif.hh" +#include "oidif.hh" +#include "eoid.hh" +#include "transactionif.hh" + +#include "alltypes.hh" +#include "typefactory.hh" + +#include "dbmddcoll.hh" +#include "dbmddcolloidentry.hh" +#include "dbmddobj.hh" + +#include "raslib/rmdebug.hh" + +RMINITGLOBALS('C') + +int RManDebug2 = 8; +int RManModule = 3; + +int +main(int argc, char *argv[]) + { + typedef map< EOId, string, less<EOId> > ap; + typedef pair< EOId, string > air; + ap* myMap = new ap(); + AdminIf* myAdmin; + DatabaseIf database; + myAdmin = AdminIf::instance(); + database.open("RMAN"); + TransactionIf ta; + ta.begin(&database); + + cout << "DBName " << database.getName() << endl; + cout << " or " << AdminIf::getCurrentDatabaseIf()->getName() << endl;; + + OId* o = new OId(1, OId::BASETYPEOID); + EOId* e = new EOId("asys", "abase", 0L, 3); + string* s = new string("aa0"); + myMap->insert(air(*e, *s)); + + e = new EOId("asys", "abase", 5L, 3); + s = new string("aa5"); + myMap->insert(air(*e, *s)); + + e = new EOId("asys", "abase", 10L, 3); + s = new string("aa10"); + myMap->insert(air(*e, *s)); + + e = new EOId("bsys", "abase", 0L, 3); + s = new string("ba0"); + myMap->insert(air(*e, *s)); + + e = new EOId("bsys", "abase", 5L, 3); + s = new string("ba5"); + myMap->insert(air(*e, *s)); + + e = new EOId("bsys", "abase", 10L, 3); + s = new string("ba10"); + myMap->insert(air(*e, *s)); + + e = new EOId("asys", "bbase", 0L, 3); + s = new string("ab0"); + myMap->insert(air(*e, *s)); + + e = new EOId("asys", "bbase", 5L, 3); + s = new string("ab5"); + myMap->insert(air(*e, *s)); + + e = new EOId("asys", "bbase", 10L, 3); + s = new string("ab10"); + myMap->insert(air(*e, *s)); + + e = new EOId("bsys", "bbase", 0L, 3); + s = new string("bb0"); + myMap->insert(air(*e, *s)); + + e = new EOId("bsys", "bbase", 10L, 3); + s = new string("bb10"); + myMap->insert(air(*e, *s)); + + e = new EOId("bsys", "bbase", 15L, 3); + s = new string("bb15"); + myMap->insert(air(*e, *s)); + + e = new EOId("asys", "abase", 5L, 3); + s = new string("fuenf b"); + myMap->insert(air(*e, *s)); + + int i = 0; + ap::iterator iter = myMap->begin(); + for (; iter != myMap->end(); iter++) + { + i++; + cout << "Nummer " << i << " key " << (*iter).first << " value " << (*iter).second.c_str() << endl; + } + } diff --git a/reladminif/test/indextest.cc b/reladminif/test/indextest.cc new file mode 100644 index 0000000..fdcdfa9 --- /dev/null +++ b/reladminif/test/indextest.cc @@ -0,0 +1,227 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "mymalloc/mymalloc.h" +#include <stdlib.h> +#include <iostream> + +#include "chartype.hh" +#include "cachetamgr/persmddcoll.hh" +#include "cachetamgr/persmddobj.hh" +#include "cachetamgr/perstile.hh" +#include "cachetamgr/persmddcolliter.hh" + +#include "adminif.hh" +#include "databaseif.hh" +#include "transactionif.hh" +#include "oidif.hh" + +#include "raslib/rminit.hh" +#include "typefactory.hh" + +#include "dbmddobj.hh" +#include "dbmddcoll.hh" + +#include "mddbasetype.hh" +#include "mdddimensiontype.hh" +#include "settype.hh" + +#ifndef BASEDB_O2 +#include "externs.h" +#endif + +RMINITGLOBALS('C') +#ifndef BASEDB_O2 +char* O2DBName = "RASBASE"; +#else +char* O2DBName = "NorbertBase"; +#endif +char *collName = "testColl"; +char defaultCollName[]= "ObjsContainer"; + +#ifdef BASEDB_O2 +extern char* myExecArgv0 = ""; +#endif + +int +main( int argc, char** argv) + { +#ifdef BASEDB_O2 + myExecArgv0 = argv[0]; +#endif + RManDebug = 3; +#ifndef BASEDB_O2 + RManModule = 0; +#endif + RMInit::logOut = cout.rdbuf(); + RMInit::dbgOut = cout.rdbuf(); + RMInit::tileSize = 12; + MDDStorage::DefaultIxType = MDDStorage::RPlusTreeNode; + + // variables representing O2 database, ta and session + DatabaseIf db; + + // don't forget to initialize before using AdminIf! + AdminIf* myAdmin = AdminIf::instance(); + TransactionIf ta; + // connect to the database + cout << "Connecting to database " << O2DBName << "..." << endl; + int errorDBOpen; + try { + errorDBOpen = db.open(O2DBName); + } + catch(...) + { + cout << "Caught Exception " << endl; + exit(-1); + } + ta.begin(&db); + int i = PersMDDColl::destroyRoot(collName, &db); + ta.commit(); + ta.begin(&db); + const CollectionType* greyset = TypeFactory::mapSetType("GreySet"); + MDDDimensionType* mddtype = (MDDDimensionType*)TypeFactory::mapMDDType("GreyCube"); + if (!mddtype || !greyset) + { + cout << "didnt find types" << endl; + exit(-1); + } + OId oColl; + if (OId::allocateMDDCollOId(&oColl) == 0) + { + } + else + cout <<"Error allocating OId for collection " << endl; + PersMDDColl* col; + try { + // CollectionType* ct = TypeFactory::mapSetType("ObjsContainerType"); + col = PersMDDColl::createRoot(collName, oColl, greyset, &db); + } + catch (...) + { + cout << "Error creating PersMDDColl" << endl; + exit(-1); + } + + greyset = TypeFactory::mapSetType("GreySet3"); + mddtype = (MDDDimensionType*)TypeFactory::mapMDDType("GreyCube"); + + OId oid1; + if (OId::allocateMDDOId(&oid1) == 0) + { + + } + else + { + cout << "Error by allocation of OId" <<endl; + exit(1); + } + + // read root object + + PersMDDColl objsSet(collName); + + + // create MDD Object 1 + + r_Sinterval limits1Obj1(0l,100l); + r_Sinterval limits2Obj1(0l,100l); + r_Sinterval limits3Obj1(0l,100l); + r_Minterval dom(3); + dom << limits1Obj1 << limits2Obj1 << limits3Obj1; + + PersMDDObj* MDDObj1 = new PersMDDObj(mddtype, dom, O2DBName, oid1); + cout << "created new persmddobj" << endl; + + char* test = (char*)mymalloc((dom.cell_count() + 1) * mddtype->getBaseType()->getSize()); + for (i = 0; i < 1000; i++) + test[i] = i%255; + + dom[0].set_interval(0l,1l); + dom[1].set_interval(0l,1l); + dom[2].set_interval(0l,1l); + PersTile* tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "1--------------" << endl; + + dom[0].set_interval(2l,3l); + dom[1].set_interval(0l,1l); + dom[2].set_interval(0l,1l); + tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "2--------------" << endl; + + dom[0].set_interval(4l,5l); + dom[1].set_interval(0l,1l); + dom[2].set_interval(0l,1l); + tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "3--------------" << endl; + + dom[1].set_interval(0l,1l); + dom[0].set_interval(20l,21l); + dom[2].set_interval(0l,1l); + tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "4--------------" << endl; + + dom[1].set_interval(0l,1l); + dom[0].set_interval(22l,23l); + dom[2].set_interval(0l,1l); + tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "5--------------" << endl; + + dom[1].set_interval(0l,1l); + dom[0].set_interval(24l,25l); + dom[2].set_interval(0l,1l); + tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "6--------------" << endl; + + dom[1].set_interval(0l,1l); + dom[0].set_interval(10l,11l); + dom[2].set_interval(0l,1l); + tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "7--------------" << endl; + + dom[1].set_interval(0l,1l); + dom[0].set_interval(26l,27l); + dom[2].set_interval(0l,1l); + tile1Obj1 = new PersTile(dom, mddtype->getBaseType(), test); + MDDObj1->insertTile(tile1Obj1); + cout << "8--------------" << endl; + + objsSet.insert(MDDObj1); + + r_Point po("[10,0,1]"); + char* utest = MDDObj1->pointQuery(po); + if (utest) + cout << "works" << endl; + else + cout << "failure" << endl; + ta.commit(); + db.close(); + } + + diff --git a/reladminif/test/perstest.C b/reladminif/test/perstest.C new file mode 100644 index 0000000..118fcf4 --- /dev/null +++ b/reladminif/test/perstest.C @@ -0,0 +1,1155 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "mymalloc/mymalloc.h" +#define TEST_PROTECTED +#define TEST_PRIVATE + +#include <stdlib.h> +#include <iostream.h> + +#include "ulongtype.hh" +#include "cachetamgr/persmddcoll.hh" +#include "cachetamgr/persmddobj.hh" +#include "cachetamgr/perstile.hh" +#include "cachetamgr/persmddcolliter.hh" + +#include "adminif.hh" +#include "databaseif.hh" +#include "transactionif.hh" +#include "oidif.hh" + +#include "raslib/rminit.hh" +#include "typefactory.hh" + +#include "dbmddobj.hh" +#include "dbmddcoll.hh" + +#include "mddbasetype.hh" +#include "mdddomaintype.hh" +#include "settype.hh" + +#include "externs.h" + + + +/* + Global Variables +*/ + +RMINITGLOBALS('C') + +static char* O2DBName; +char *collName; +char defaultCollName[]= "ObjsContainer"; +OId globalOId1, globalOId2; +OId globalCollOId; +EOId globalEOId[4]; +int numObjsCreated; +TransactionIf ta; +int ExitNo; + +/* + Functions +*/ + +int +getOption( ) +{ + unsigned int result; + cout << endl; + cout << "Choose Option : " << endl; + cout << "-----------------------------------------------------------------"<<endl; + cout << " 1 - Create MDD collection with name .. " << collName << endl; + cout << " 2 - Populate collection with MDD objects (testConstructors) " << endl; + cout << " 3 - Access MDD collection given name (testAccessing) " << endl; + cout << " 4 - Access MDD collection given OId (testAccessing)" << endl; + cout << " 5 - Access MDD object given OId (testAccessingMDDObj) " << endl; + cout << " 6 - Remove MDD object from the collection given OId (testRemove) "<<endl; + cout << " 7 - Test PersMDDObj::intersect( ) (testSearch) " <<endl; + cout << " 8 - Test PersMDDColl::getCardinality( ) "<<endl; + cout << " 9 - Test PersMDDObj get functions "<< endl; + cout << " 10 - Remove MDD Collection given OId " << endl; + cout << " 11 - Insert MDD given OId in a second collection "<< endl; + cout << " 12 - Insert tile in MDD given OId "<< globalOId1 <<endl; + cout << " 13 - Test removeTile from MDD "<< globalOId1 << endl; + ExitNo = 14; + cout << " " << ExitNo << " - Exit " << endl; + cout << "------------------------------------------------------------------"<<endl; + cout << "Enter option: "; + cin >> result; + switch (result) + { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + return result; + break; + default: + return getOption(); + } +} + +// 1 - Create MDD collection +static int createMDDColl( const char* collName, DatabaseIf* db ); + +// 2 - Populate collection with MDD objects +static void testConstructors( char* cn ); + +// 3 - Retrieves an MDD collection with name cn and prints contents: +static void testAccessing( char* cn ); + +// 4 - Retrieves an MDD collection with OId o and prints contents: +static void testAccessing( OId o ); + +// 5 - Retrieves an MDD object with OId o and prints contents: +static void testAccessingMDDObj( OId o ); + +// Removes one of the MDD objects in the collection +static void testRemove( ); + +// 6 - Removes MDD object with OId o in the collection +static void testRemove( OId o ); + +// 7 - Test PersMDDObj::intersect( ) objects of the collection +static void testSearch( ); + +// 8 - Test PersMDDColl::getCardinality( ) +static void testGetCardinality( char* cn); + +// 9 - Scans collection and tests PersMDDObj get functions +static void testGetFunctions( ); + +//10 - Remove MDD collection given OId + +//11 - Insert MDD given OId in a second collection +static void testInsertMDDObjColl( OId o, char* cn ); + +//12 - Test later insertion of tile in PersMDDObj +static void testLaterInsert( OId o ); + +//13 - Test removeTile from an MDD obj +static void testRemoveTile( OId o ); + +// Tries accessing several OIds, including ilegal ones, to test +// several error conditions. +static void testAccessingOId( ); + + +/************************************************************* + * Function name.: int main( int argc, char** argv) + * + * Arguments.....: + * argc: number of arguments given to program + * argv: array of char* with arguments + * Return value..: exit status + * Description...: none + ************************************************************/ +int +main( int argc, char** argv) +{ +RManDebug = 10; +RManModule = 0; +RMInit::logOut = cout.rdbuf(); +RMInit::dbgOut = cout.rdbuf(); +RMInit::tileSize = 12; +MDDStorage::DefaultIxType = MDDStorage::RPlusTreeNode; + + // variables representing O2 database, ta and session + DatabaseIf database; + + if( argc < 2 ) { + cout << "Usage: test_persmddcoll <database> [collName]" << endl; + return -1; + } + O2DBName = strdup( argv[1] ); + if ( argc == 3 ) collName = strdup( argv[2] ); + else + collName = defaultCollName; + + // don't forget to initialize before using AdminIf! + AdminIf* myAdmin = AdminIf::instance(); + + + // connect to the database + cout << "Connecting to database " << O2DBName + << "..." << endl; + int errorDBOpen; + try{ + errorDBOpen = database.open( O2DBName ); + } + catch( ...) + { + cout << "Caught Exception " << endl; + errorDBOpen = -6; + } + if ( errorDBOpen < 0 ) + { + cout << "Database doesn't exist. Create it new ... " << endl; + cout << "Creating new database " << O2DBName + << "..." << endl; + database.create( O2DBName, "TestSMSchema" ); + cout << "Connecting to database " << O2DBName + << "..." << endl; + try{ + errorDBOpen = database.open( O2DBName ); + } + catch(...) + { + errorDBOpen = -6; + } + } + if ( errorDBOpen < 0 ) + { + cout << "Failed at opening newly created database " << errorDBOpen << endl; + cout << "Exiting " << endl; + return errorDBOpen; + } + + ta.begin( &database ); + cout << endl << "Deleting root object from the database ..." <<endl; + int i = PersMDDColl::destroyRoot( collName, &database ); + cout << " i == " << i << endl; + // cout << " &database = " << long( &database) << endl; + ta.commit( ); + + char c; + int error; + + for( unsigned opt = getOption( ); opt != ExitNo ; opt = getOption( ) ) + { + cout <<"Transaction begin ... " << endl; + ta.begin( &database ); + switch ( opt ) + { + case 1: // 1 - Create MDD collection with name + // create root collection + cout << endl << "Creating mdd types and root collection..." << endl; + if ( createMDDColl( collName, &database ) != 0 ) + { + cout <<"Error caught ................."<< endl; + cout << endl << "Ending O2 session..." << endl; + ta.commit( ); + database.close( ); + delete myAdmin; + exit( 1 ); + } + break; + + case 2: // 2 - Populate collection with MDD objects (testConstructors) + // create objects and put them in the collection + cout << endl << "Populate collection ..." << endl; + testConstructors( collName ); + break; + + case 3: // 3 - Access MDD collection given name (testAccessing) + // read coll and print contents + cout << endl << "Read collection " << collName << " and print contents..." << endl; + testAccessing( collName ); + break; + + case 4: // 4 - Access MDD collection given OId (testAccessing) + cout << endl << "Read collection " << globalCollOId << " and print contents..." << endl; + testAccessing( globalCollOId ); + break; + + case 5: // 5 - Access MDD object given OId (testAccessingMDDObj) + cout << endl << "Test Accessing MDD with OId " << globalOId1 << " ... " << endl; + testAccessingMDDObj( globalOId1 ); + break; + + case 6: // 6 - Remove MDD object from the collection given OId (testRemove) + cout<< endl << "Remove MDD with OId " << globalOId1 << " ..." << endl; + testRemove( globalOId1 ); + break; + + case 7: // 7 - Test PersMDDObj::intersect( ) (testSearch) + cout << endl << "Test region search ..." << endl; + testSearch( ); + break; + + case 8: // 8 - Test PersMDDColl::getCardinality( ) + cout << endl << "Get cardinality of collection" << collName <<" ..." << endl; + testGetCardinality( collName ); + break; + + case 9: // 9 - Test PersMDDObj get functions + cout << endl <<"Test PersMDDObj get functions " << endl; + testGetFunctions( ); + break; + + case 10: // 10 - Remove MDD Collection given OId + cout << endl << "Remove MDD collection with OId "; + cout << globalCollOId << " ..." << endl; + error = PersMDDColl::destroyRoot( globalCollOId, &database ); + if (error ) + cout << " Error destroying root " << endl; + break; + + case 11: // 11 - Insert MDD given OId in a second collection + cout << endl << "Insert Object with OId " << globalOId1; + cout << " in collection Coleccao1 " << endl; + cout << "First, create collection" << endl; + if ( createMDDColl( "Coleccao1", &database ) != 0 ) + { + cout <<"Error caught ................."<< endl; + cout << endl << "Ending O2 session..." << endl; + ta.commit( ); + database.close( ); + delete myAdmin; + exit( 1 ); + } + cout << "Then insert object with OId "<< globalOId1 << endl; + testInsertMDDObjColl( globalOId1 , "Coleccao1"); + cout << endl; + break; + + case 12: // 12 - Insert new tiles in the MDD object + cout << endl << "Insert Tile in object with OId " << globalOId1; + testLaterInsert( globalOId1 ); + cout << endl; + break; + + case 13: // 13 - Remove a tile from the MDD object + cout << endl << "Remove Tile from object with OId " << globalOId1; + testRemoveTile( globalOId1 ); + cout << endl; + break; + + default: + break; + } + cout <<"Transaction abort (A/a) or commit (default)? "; + cin >> c; + if ( c == 'A' || c == 'a' ) + { + ta.abort( ); + cout <<"End of Transaction Abort..."<<endl; + } + else + { + ta.commit( ); + cout <<"End of Transaction Commit..."<<endl; + } + if ( opt == 6 ) + { + cout<<"Garbage ? ( y /n ) "; + cin >> c; + if (c =='y' || c == 'Y' ) + { + cout <<"Garbaging ..."<< endl; + ta.begin( &database ); + database.garbage( ); + ta.commit( ); + } + } + cout <<"End of transaction commit... "<<endl; + } // for opt + + + cout << endl << "Ending O2 session..." << endl; + database.close( ); + delete myAdmin; + + free( O2DBName ); + if ( collName != defaultCollName ) free( collName ); + return 0; + +} + +/************************************************************* + * Functions......: + * + * static void + * testInsertMDDObjColl( OId o, char* cn ) + * + * static void + * testConstructors( char* collName ) + * + ************************************************************/ +static void +testInsertMDDObjColl( OId o, char* cn ) +{ + cout << "....testInsertMDDObjColl "<< o <<","<< cn << endl; + PersMDDObj* obj = new PersMDDObj( O2DBName,o ); + PersMDDColl objsSet( cn ); + objsSet.insert( obj ); + delete obj; + +} + +static void testConstructors( char* collName ) +{ + + const BaseType* ulongTypeObj = TypeFactory::mapType("ULong"); + const BaseType* boolTypeObj = TypeFactory::mapType("Bool"); + const MDDBaseType* mType1 = (const MDDBaseType* ) TypeFactory::mapMDDType("TestSMDomainType2D"); + const MDDBaseType* mType2 = (const MDDBaseType* ) TypeFactory::mapMDDType("TestSMDomainType3D"); + + cout << "....testConstructors"<< endl; + + OId oid1; + if ( OId::allocateMDDOId( &oid1 ) == 0) + cout << "Successfull allocation of OId " << oid1 <<endl; + else + { + cout << "Error by allocation of OId" <<endl; + exit(1); + } + OId oid2; + if ( OId::allocateMDDOId( &oid2 ) == 0) + cout << "Successfull allocation of OId " << oid2 <<endl; + else + { + cout << "Error by allocation of OId" <<endl; + exit(1); + } + + globalOId1 = oid1; + globalOId2 = oid2; + + // read root object + + PersMDDColl objsSet(collName); + + + // create MDD Object 1 + + cout << "Creating mddObj1" << endl; + cout << "tile 1 = nil, 10-12, 20-24 "<< endl; + r_Sinterval limits1Obj1(10l,12l); + r_Sinterval limits2Obj1(20l,24l); + r_Minterval dom(2); + dom << limits1Obj1 << limits2Obj1; + + r_Minterval tmpInt = *( ( MDDDomainType* ) mType1 )->getDomain( ); + PersMDDObj* MDDObj1 = new PersMDDObj( mType1, tmpInt, O2DBName, oid1 ); + + char* test = (char*)mymalloc((dom.cell_count() + 1) * 4); + memset(test, 0, (dom.cell_count() + 1) * 4); + cout << "created new persmddobj" << endl; + PersTile* tile1Obj1 = new PersTile( dom, ulongTypeObj, test ); + cout << "created new perstile" << endl; + MDDObj1->insertTile(tile1Obj1); + cout << "inserted tile" << endl; + + cout << "tile 2 = nil, 0-400, 22-24 "<< endl; + dom[0].set_interval(0l,400l); + dom[1].set_interval(22l,24l); + test = (char*)mymalloc((dom.cell_count() + 1) * 4); + memset(test, 0, (dom.cell_count() + 1) * 4); + cout << "created new perstile" << endl; + PersTile* tile2Obj1 = new PersTile( dom, ulongTypeObj, test ); + cout << "insert tile" << endl; + MDDObj1->insertTile(tile2Obj1); + cout << "inserted tile" << endl; + + cout << "tile 3 = nil, 0-600, 10-1000 "<< endl; + dom[0].set_interval(0l,600l); + dom[1].set_interval(10l,1000l); + test = (char*)mymalloc((dom.cell_count() + 1) * 4); + memset(test, 0, (dom.cell_count() + 1) * 4); + cout << "created new perstile" << endl; + PersTile* tile3Obj1 = new PersTile( dom, ulongTypeObj, test ); + cout << "insert tile" << endl; + MDDObj1->insertTile(tile3Obj1); + cout << "inserted tile" << endl; + + cout << "MDDObj1 == isPersistent:" << MDDObj1->isPersistent( )<< ";" <<endl; + MDDObj1->printStatus( ); + cout << endl; + + objsSet.insert(MDDObj1); + + // create MDD Object + cout << "Creating mddObj2 "<< endl; + cout << "tile 1 = nil, 0-19, 20-59, 30-59 "<< endl; + r_Sinterval limits1Obj2(0l,19l); + r_Sinterval limits2Obj2(20l,59l); + r_Sinterval limits3Obj2(30l,59l); + r_Minterval dom2(3); + dom2 << limits1Obj2 << limits2Obj2 << limits3Obj2; + + tmpInt = *( ( MDDDomainType* ) mType2 )->getDomain( ); + PersMDDObj* MDDObj2 = new PersMDDObj( mType2, tmpInt, O2DBName, oid2 ); + + test = (char*)mymalloc((dom.cell_count() + 1) * 1); + memset(test, 0, (dom.cell_count() + 1) * 1); + PersTile* tile1Obj2 = new PersTile( dom2, boolTypeObj, test); + MDDObj2->insertTile( tile1Obj2 ); + + cout << "tile 2 = nil, 20-39, 60-79, 60-89 "<< endl; + dom2[0].set_interval(20l,39l); + dom2[1].set_interval(60l,79l); + dom2[2].set_interval(60l,89l); + test = (char*)mymalloc((dom.cell_count() + 1) * 1); + memset(test, 0, (dom.cell_count() + 1) * 1); + PersTile* tile2Obj2 = new PersTile( dom2, boolTypeObj, test); + + MDDObj2->insertTile(tile2Obj2); + + + cout << "MDDObj2 == isPersistent:" << MDDObj2->isPersistent( )<< ";" <<endl; + MDDObj2->printStatus( ); + cout << endl; + +/* + // This program doesn't work if the TA is aborted when OIds are + // allocated, even if all allocated OIds are binded. Question: is it + // because of dangling handles? This little test was done to + // check that. + // This without oids works with ta.abort + // conclusion: the problem with abort is not due to the handles + Handle hd; + d_Ref<DBMDDObj> refObj = MDDObj2->getDBMDDObjId(); + hd = refObj.o2_get_handle(); +*/ + + + objsSet.insert(MDDObj2); + numObjsCreated = 2; + + cout << "Release all " << endl; + + //( ( PersMDDColl ) objsSet ).releaseAll( ); + + cout << "Release all END" << endl; +} + + +/************************************************************* + * Function......: testAccessing( char* cn ) + * testAccessing( OId o ) + ************************************************************/ + +static void testAccessing( char* cn ) +{ + PersMDDObj* accessedObj; + + cout << "....testAccessing collection "<< cn << endl; + + try{ + PersMDDColl objsSet( cn ); + + // To test PersMDDColl::printStatus( ) + // objsSet.printStatus( ); + + // To test PersMDDObj::printStatus( ), MDDCollIter::createIterator( ) and + // MDDCollIter methods : + + cout << "Iterating through the collection with PersMDDCollIter " << endl; + MDDCollIter* objsIt = objsSet.createIterator( ); + + for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( )) + { + cout << i<<". MDD object in set:" << endl; + accessedObj = (PersMDDObj*) objsIt->getElement(); + accessedObj->printStatus(); + EOId eoid; + if ( accessedObj->getEOId( &eoid ) ==0 ) + cout <<"EOId: " << eoid; + // old version cout <<"EOId: " << eoid.getSystemName( ) << eoid.getBaseName( ) << eoid.getOId( ); + cout << endl << endl; + accessedObj->getEOId( &globalEOId[i-1] ); + } + delete objsIt; + objsSet.releaseAll( ); + } + catch ( r_Error& errObj) + { + cout <<"Error caught ................."<< endl; + } +} + +static void testAccessing( OId o ) +{ + PersMDDObj* accessedObj; + + cout << "....testAccessing collection "<< o << endl; + + try { + PersMDDColl objsSet( o, O2DBName ); + + OId o; + if ( objsSet.getOId( &o ) == 0 ) + cout <<"getOId " << o << endl; + else + cout <<"Error getOId " << endl; + + EOId eo; + if ( objsSet.getEOId( &eo ) == 0 ) + cout << "getEOId " << eo <<endl; + // cout << "getEOId " << eo.getSystemName( ) <<":"<<eo.getBaseName( )<<":"<<eo.getOId( ) << endl; + else + cout <<"Error getEOId " << endl; + + // To test PersMDDColl::printStatus( ) + objsSet.printStatus( ); + + // To test PersMDDObj::printStatus( ), MDDCollIter::createIterator( ) and + // MDDCollIter methods : + + cout << "Iterating through the collection with PersMDDCollIter " << endl; + MDDCollIter* objsIt = objsSet.createIterator( ); + + for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( )) + { + cout << i<<". MDD object in set:" << endl; + accessedObj = (PersMDDObj*) objsIt->getElement(); + accessedObj->printStatus(); + EOId eoid; + if ( accessedObj->getEOId( &eoid ) ==0 ) + cout <<"EOId: " << eoid ; + // cout <<"EOId: " << eoid.getSystemName( ) << eoid.getBaseName() << eoid.getOId( ); + cout << endl << endl; + accessedObj->getEOId( &globalEOId[i-1] ); + } + delete objsIt; + objsSet.releaseAll( ); + } + catch ( r_Error& errObj) + { + cout <<"Error caught ................."<< endl; + } + +} + +/************************************************************* + * Function......: testAccessingMDDObj(OId o ) + * testAccessingOId( ) + * + ************************************************************/ +static void testAccessingMDDObj(OId o) +{ + PersMDDObj *mObj; + + cout << "....testAccessingMDDObj"<<endl; + + try{ + mObj = new PersMDDObj( O2DBName, o); + mObj->printStatus( ); + delete mObj; + } + catch (...) + { + cout <<" Object not found..." << endl; + + } +} + +static void testAccessingOId() +{ + PersMDDObj *mObj1, *mObj2, *mObj; + int result; + OId o(70000); + OId o1(5010); + OId o2(0); + OId o3(5); + + cout << "....testAccessingOId"<<endl; + + + cout << "Test OIdIf::getType( )..."<<endl; + cout << "1.st MDDObj " << endl; + cout << "getType " << globalOId1.getType( O2DBName ) << endl; + + cout << "2.nd MDDObj " << endl; + cout << "getType " << globalOId2.getType( O2DBName ) << endl; + + // This crashes + // cout << "OId == 0 " << endl; + // cout << "getType " << o2.getType( O2DBName ) << endl; + + cout << "OId == 5 " << endl; + cout << "getType " << o3.getType( O2DBName ) << endl; + + cout << "MDDCollection " << endl; + cout << "getType " << globalCollOId.getType( O2DBName ) << endl; + // mObj2 = new PersMDDObj( O2DBName, globalOId2); + // mObj2->printStatus( ); + + cout << "Not used OId " << endl; + cout << "getType " << o1.getType( O2DBName ) << endl; + + cout << "Nonexistent OId " << endl; + cout << "getType " << o.getType( O2DBName ) << endl; + // mObj2 = new PersMDDObj( O2DBName, globalOId2); + // mObj2->printStatus( ); + + cout <<"Loading PersMDDObjs from OIds " << endl; + mObj1 = new PersMDDObj( O2DBName, globalOId1); + mObj1->printStatus( ); + mObj2 = new PersMDDObj( O2DBName, globalOId2); + mObj2->printStatus( ); + + delete mObj1; + delete mObj2; + + + for ( int i = 0; i < numObjsCreated; i++ ) + { + cout << "Reading with " << i+1<< ".th EOId " ; + cout << globalEOId[i]; + // cout << globalEOId[i].getSystemName( ); + // cout << " ; "<< globalEOId[i].getBaseName( ) << ";" << globalEOId[i].getOId( ); + cout << endl; + + + // result = o2_externalNameGetObject( &globalEOId[i], &hdObj ); +/* + result = globalEOId[i].getObject( &hdObj ); + if ( result == 0 ) + { + DBMDDObjId obj1(hdObj); + mObj = new PersMDDObj(obj1); + mObj->printStatus( ); + } + else + cout << "No such object!!" << endl; + // o2_unref_handle( ); + delete mObj; +*/ + } + +} + +/************************************************************* + * Function......: testLaterInsert() + * + ************************************************************/ + +static void testLaterInsert( OId o ) +{ + PersMDDObj* accessedObj; + + cout << "....testLaterInsert"<<endl; + + try{ + accessedObj = new PersMDDObj( O2DBName, o); + } + catch (...) + { + cout <<" Object not found..." << endl; + return; + } + + cout << "Current status of MDD object : " << endl; + accessedObj->printStatus( ); + cout << endl << "Inserting new Tile ..."<< endl; + + PersTile *t, *t2, *t3; + switch( accessedObj->getDimension( ) ) + { + case 2 : + t2 = new PersTile( r_Minterval("[40:60,80:1200]"), + accessedObj->getCellType( ) ); + t = t2; + break; + case 3 : + t3 = new PersTile(r_Minterval("[40:60,80:100,0:20]"), + accessedObj->getCellType( ) ); + t = t3; + break; + default: + cout << "Error Dimensionality not expected" << endl; + break; + } + accessedObj->insertTile(t); + cout << " New status after insertion:" << endl; + accessedObj->printStatus(); + cout << endl << endl; + + delete accessedObj; +} + + +/************************************************************* + * Function......: testSearch() + * + ************************************************************/ +static void testSearch() +{ + + MDDObj* accessedObj; + + cout << "....testSearch"<<endl; + + PersMDDColl objsSet(collName); + + MDDCollIter* objsIt = objsSet.createIterator( ); + + for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( )) + { + accessedObj = objsIt->getElement(); + + cout << "Accessed Object " << endl; + accessedObj->printStatus( ); + cout << endl; + + if (i == 1 || i == 2) + { + r_Minterval searchInt1(2); + r_Minterval searchInt2(3); + vector< Tile* >* entriesList; + + cout << " -- " << i << ". MDD object in list. Search for:"; + switch (i) { + case 1: searchInt1[0].set_interval(10l,20l); + searchInt1[1].set_interval(10l,30l); + cout << " 10-20, 10-30" << endl; + entriesList = accessedObj->intersect(searchInt1); + break; + case 2: searchInt2[0].set_interval(10l,20l); + searchInt2[1].set_interval(10l,30l); + searchInt2[2].set_interval(40l,50l); + cout << " 10-20, 10-30, 40-50" <<endl; + entriesList = accessedObj->intersect(searchInt2); + break; + default: break; + } + cout << " -- Search result: " << endl; + vector<Tile*>::iterator entryIt = entriesList->begin(); + + while (entryIt != entriesList->end()) + { + // (*entryIt)->printStatus(); + r_Minterval tileInterval = (*entryIt)->getDomain(); + int dimensionality = tileInterval.dimension(); + + cout << " PersTile printStatus"; + cout << " domain == " << dimensionality << ": "; + for (int i = 0; i <dimensionality; i++) + cout << tileInterval[i].low() << "-" + << tileInterval[i].high() <<", "; + cout << endl; + + entryIt++; + } + delete entriesList; + } + } + delete objsIt; + // objsSet.releaseAll( ); +} + +/************************************************************* + * Function......: testRemoveTile(OId o ) + * + ************************************************************/ +static void testRemoveTile(OId o) +{ + PersMDDObj *mObj; + + cout << "....testRemoveTile from MDD Obj "<< o << endl; + + try{ + mObj = new PersMDDObj( O2DBName, o); + mObj->printStatus( ); + } + catch (...) + { + cout <<" Object not found..." << endl; + return; + } + + vector<Tile*>* tiles = mObj->getTiles( ); + + if ( tiles->size( ) == 0 ) + { + cout <<"MDD object has no tiles !! "<< endl; + return; + } + else + { + int ix = tiles->size( )/2; + + cout << "Removing "<< ix <<". tile from MDD Obj "<< endl; + cout << "Tile Description: " << (*tiles)[ix]->getDomain( ) << endl; + + PersTile* t = (PersTile*) (*tiles)[ix]; + + mObj->removeTile( (*tiles)[ix] ); + + delete tiles; + delete mObj; + } +} + +/************************************************************* + * Function......: testGetCardinality( const char* cn ) + * testGetFunctions() + * + ************************************************************/ +static void testGetCardinality( char* cn ) +{ + cout << "....testGetCardinality( "<< cn << " )" << endl; + + try{ + PersMDDColl objsSet( cn ); + cout<< "Cardinality of collection " << objsSet.getCardinality( ) <<endl; + } + catch( r_Error& errObj) + { + cout <<"Error caught ................."<< endl; + } +} + +static void testGetFunctions() +{ + PersMDDObj* accessedObj; + + cout << "....testGetFunctions"<<endl; + + PersMDDColl objsSet(collName); + + MDDCollIter* objsIt = objsSet.createIterator( ); + + vector< Tile* >* entriesList; + + for( int i = 1 ; objsIt->notDone( ); i++, objsIt->advance( )) + { + r_Minterval currDom; + r_Minterval defDom; + + cout << " " << i << ". Object" << endl; + accessedObj = (PersMDDObj*) objsIt->getElement(); + + + defDom = accessedObj->getDefinitionDomain( ); + cout << " GetDefinitionDomain result: "; + defDom.print_status( ); + cout << endl; + + currDom = accessedObj->getCurrentDomain( ); + cout << " GetCurrentDomain result: "; + currDom.print_status( ); + cout << endl; + + entriesList = accessedObj->getTiles( ); + cout << " -- GetTiles result: " << endl; + vector<Tile*>::iterator entryIt = entriesList->begin(); + + while (entryIt != entriesList->end()) + { + // (*entryIt)->printStatus(); + r_Minterval tileInterval = (*entryIt)->getDomain(); + int dimensionality = tileInterval.dimension(); + + cout << " PersTile "; + cout << " domain == " << dimensionality << ": "; + for (int i = 0; i <dimensionality; i++) + cout << tileInterval[i].low() << "-" << tileInterval[i].high() <<", "; + cout << endl; + entryIt++; + } + delete entriesList; + } + delete objsIt; + objsSet.releaseAll( ); +} + +/************************************************************* + * Function......: testRemove() + * testRemove( OId o ) + * + ************************************************************/ + +static void testRemove() +{ + PersMDDObj* accessedObj; + + cout << "....testRemove"<<endl; + + PersMDDColl objsSet(collName); + // PersMDDColl objsSet("Qualquercoisa"); + // To test PersMDDColl::printStatus and PersMDDColl::remove + + + MDDCollIter* objsIt = objsSet.createIterator( ); + + cout << "-- Remove second element from collection " << endl; + + for( int i = 1 ; objsIt->notDone( ) && i < 2; i++, objsIt->advance( )) + { + accessedObj = (PersMDDObj*) objsIt->getElement(); + } + cout << "Delete of objsIt:" << endl; + delete objsIt; + cout << "Finished Delete of objsIt." << endl; + cout << "Remove accessedObj:" << endl; + objsSet.remove( accessedObj ); + cout << "Finished Remove accessedObj." << endl; +} + +static void testRemove( OId o ) +{ + + cout << "....testRemove( OId == " << o <<" ) "<< endl; + + PersMDDColl objsSet(collName); + objsSet.remove( o, O2DBName ); +} + + +/************************************************************* + * Function......: createMDDColl( ) + ************************************************************/ +static int +createMDDColl( const char* collName, DatabaseIf* db ) +{ +cout << "createMDDColl(" << collName << ", " << db->getName() << ")" << endl; + MDDDomainType* mType1 = 0; + MDDDomainType* mType2 = 0; + MDDType* mt = 0; + CollectionType* collType1 = 0; + + const BaseType* ulongTypeObj = TypeFactory::mapType("ULong"); + + const MDDDomainType* cmType1 = + ( MDDDomainType* ) TypeFactory::mapMDDType( "TestSMDomainType2D" ); + if (cmType1) + cout << "cmType1 " << cmType1->getName() << endl; + const MDDDomainType* cmType2 = + ( MDDDomainType* ) TypeFactory::mapMDDType( "TestSMDomainType3D" ); + if (cmType2) + cout << "cmType1 " << cmType2->getName() << endl; + + const CollectionType* collType = + (CollectionType*)TypeFactory::mapSetType( "ObjsContainerType" ); + if (collType) + cout << "collType " << collType->getName() << endl; + + + if( !cmType1 || !cmType2 || !collType ) + { + cout << "types not found!" << endl; + char name1[] = "TestSMDomainType2D"; + char name2[] = "TestSMDomainType3D"; + + r_Sinterval limits1Obj1(0l,1000l); + r_Sinterval limits2Obj1(0l,800l); + r_Minterval dom1(2); + dom1 << limits1Obj1 << limits2Obj1; + cout << "MDD Type 1 , domain "<< dom1 << endl; + + cout << " tile 1 = nil, 0-19, 20-59, 30-59 "<< endl; + r_Sinterval limits1Obj2(0l,19l); + r_Sinterval limits2Obj2(20l,59l); + r_Sinterval limits3Obj2(30l,59l); + r_Minterval dom2(3); + dom2 << limits1Obj2 << limits2Obj2 << limits3Obj2; + cout << "MDD Type 2 , domain "<< dom2 << endl; + + // MDDDomainType* mType1 = + mType1 = + new MDDDomainType((char*) name1, ( BaseType* ) ulongTypeObj, dom1 ); + // MDDDomainType* mType2 = + mType2 = + new MDDDomainType((char*) name2, ( BaseType* ) ulongTypeObj, dom2 ); + + cout << "MDD Type1 == "; + mType1->print_status( cout ); + cout << endl; + cout << "MDD Type2 == "; + mType2->print_status( cout ); + cout << endl; + + TypeFactory::addMDDType( mType1 ); + TypeFactory::addMDDType( mType2 ); + + if ( !collType ) + { + cout << "Collection type newly created " << endl; + // MDDType* mt = new MDDType( ); + mt = new MDDType( ); + cout << "MDDtype created "<< endl; + collType1 = new SetType( "ObjsContainerType", mType1 ); + cout << "Set Type created ... "; + collType = collType1; + TypeFactory::addSetType( (SetType*) collType ); + cout <<" and added "<< endl; + + } + + } + else + cout << "types were found!" << endl; + //ta.commit( ); + + //ta.begin( ); + + cout << "Creating root collection" << endl; + + // cout << " &database = " << long( db ) << endl; + + OId oColl; + if( OId::allocateMDDCollOId( &oColl ) == 0 ) + cout <<"Successfully allocated OId for collection " << oColl << endl; + else + cout <<"Error allocating OId for collection " << endl; + globalCollOId = oColl; + + PersMDDColl* col; + try { + // CollectionType* ct = TypeFactory::mapSetType( "ObjsContainerType" ); + col = PersMDDColl::createRoot( collName, oColl, collType, db ); + } + catch (...) + { + cout <<"Error caught ................."<< endl; + return -1; + } + + cout << "Committing TA ..."<< endl; + ta.commit( ); + + /* + + cout <<"Freeing types ... "<< endl; + + // if ( mType1 ) delete mType1; + cout << "Type 1 freed . "<< endl; + // if ( mType2 ) delete mType2; + cout << "Type 2 freed . "<< endl; + // if ( mt ) delete mt; + cout << "Type mt freed . "<< endl; + // if ( collType1 ) delete collType1; + cout << "Types collType1 freed . "<< endl; + */ + if ( col ) delete col; + cout << "Col freed . "<< endl; + + + ta.begin( db ); + return 0; +} diff --git a/reladminif/test/test_databaseif.cc b/reladminif/test/test_databaseif.cc new file mode 100644 index 0000000..46caa5f --- /dev/null +++ b/reladminif/test/test_databaseif.cc @@ -0,0 +1,203 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * test class DatabaseIf. + * + * + * PREREQUISITES: + * - needs COMPDATE (compilation date) defined, eg. cc -DCOMPDATE=\"`date`\" + * + * COMMENTS: + * + ***********************************************************************/ + +static const char rcsid[] = "@(#)reladminif,DatabaseIf: $Id: databaseif.ec,v 1.9 2003/12/27 23:11:43 rasdev Exp $"; + +using namespace std; + +#include <iostream.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "error.hh" +#include "adminif.hh" +#include "databaseif.hh" +#include "externs.h" + +#include "raslib/rmdebug.hh" +#define DEBUG_MAIN +#include "debug.hh" + + +RMINITGLOBALS('C') + + +// test environment: +#include "testcenter.h" + +#define ELLIPSIS "..." +/// test macro for checking error condition, printing result, and aborting on error +#define CHECK(p) { cout << "CHECKING " << "p"; \ + if (!(p)) \ + { cout << TEST_ERROR << endl; \ + return false; \ + } \ + else \ + { \ + cout << TEST_OK << endl; \ + } \ + } + +/// ObjectBroker: dummy class to satisfy linker; real ObjectBroker functionality never used here. +class ObjectBroker +{ + public: + void init(); + void deinit(); + bool freeMemory(); +}; + +void ObjectBroker::init() +{ +} +void ObjectBroker::deinit() +{ +} +bool ObjectBroker::freeMemory() +{ + return true; +} + +/// from server/rasserver_main.cc: +char globalConnectId[256]; + +/// doTest(): run the test cases +/// preconditions: +/// database does NOT yet exist +/// @params: +/// dbname name of database +/// @returns: +/// true if all tests succeeded +/// false if some test failed + +bool doTest( const char *dbname ) +{ + bool result = false; // overall test result + DatabaseIf *db = NULL; // our test candidate + + try // capture eny eventual exception for reporting + { + // --- (1) good scenario + + cout << "DatabaseIf constructor" << ELLIPSIS << flush; + db = new DatabaseIf(); + cout << "new state is: " << *db; + CHECK( db != NULL ); + + cout << "create" << ELLIPSIS << endl; + db->createDB( dbname, NULL, NULL ); + CHECK( db->isConnected() ); + CHECK( db->isOpen() ); + + cout << "db open" << ELLIPSIS << endl; + db->open( dbname ); + CHECK( db->isConnected() ); + CHECK( db->isOpen() ); + + cout << "db close" << ELLIPSIS << endl; + db->close(); + CHECK( db->isConnected() ); + CHECK( db->isOpen() ); + + cout << "db destroy" << ELLIPSIS << endl; + db->destroyDB( dbname ); + CHECK( db->isConnected() ); + CHECK( db->isOpen() ); + + result = true; + } + // FIXME: what else should be caught explicitly? + catch(r_Error& myErr) + { + cout << "caught r_Error exception #" << myErr.get_errorno() << ": " << myErr.what() << endl; + result = false; + } + catch(bad_alloc) + { + cout << "caught bad_alloc exception" << endl; + result = false; + } + catch(...) + { + cout << "caught unknown exception" << endl; + result = false; + } + + return result; +} + +int +main(int argc, char *argv[]) +{ + const char *progName = argv[0]; // name of this test program + + int RManDebug2 = 5; // debug trace settings + int RManModule = 1; // dito + + char* dbName = "RASBASE"; // default database name + int result = RC_ERROR; // overall test exit code + char *resultText = NULL; // overall test status string + + // --- parameter evaluation, launch msg + if (argc == 2) + dbName = argv[1]; + else if (argc > 2) + { + cout << "usage: " << progName << " [dbname]" << endl; + return( RC_USAGE ); + } + cout << progName << ", generated on " << COMPDATE << " for rasdaman version " << RMANVERSION << " and base DBMS " << BASEDBSTRING << "; using database '" << dbName << "'" << endl; + + // --- all is fine, let's do the test + bool allFine = doTest( dbName ); + + if (allFine) + { + resultText = TEST_OK; + result = RC_OK; + } + else + { + resultText = TEST_ERROR; + result = RC_ERROR; + } + + // --- done, epilogue + cout << progName << ": overall test result is " << resultText << endl; + + return( result ); +} + diff --git a/reladminif/test/testcenter.h b/reladminif/test/testcenter.h new file mode 100644 index 0000000..c17d94f --- /dev/null +++ b/reladminif/test/testcenter.h @@ -0,0 +1,47 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * provide global settings for running system tests. + * + * + * COMMENTS: + * + ***********************************************************************/ + +#ifndef _TESTCENTER_H_ + +/// program exit codes +#define RC_OK 0 +#define RC_USAGE 2 +#define RC_ERROR -1 + +/// protocol output, must be canonical for automatic & regression testing +#define TEST_OK "OK" +#define TEST_ERROR "ERROR" + +#define _TESTCENTER_H_ +#endif _TESTCENTER_H_ + diff --git a/reladminif/test/testconnect.c b/reladminif/test/testconnect.c new file mode 100644 index 0000000..70215b7 --- /dev/null +++ b/reladminif/test/testconnect.c @@ -0,0 +1,395 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include <sqlhdr.h> +#include <sqliapi.h> +#line 1 "testconnect.ec" +/* testconnect.ec +test connection to Informix database +*/ + +#include <iostream> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <minmax.h> + +/* + * EXEC SQL INCLUDE SQLCA; + */ +#line 11 "testconnect.ec" + +#line 11 "testconnect.ec" +#line 1 "/opt/informix/incl/esql/sqlca.h" +/**************************************************************************** + * + * IBM INC. + * + * PROPRIETARY DATA + * + * Licensed Material - Property Of IBM + * + * "Restricted Materails of IBM" + * + * IBM Informix Client SDK + * + * (c) Copyright IBM Corporation 2002. All rights reserved. + * + * + * Title: sqlca.h + * Sccsid: @(#)sqlca.h 9.4 1/18/93 11:09:48 + * Description: + * SQL Control Area + * + *************************************************************************** + */ + +#ifndef SQLCA_INCL +#define SQLCA_INCL + +#include "ifxtypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct sqlca_s + { + int4 sqlcode; + char sqlerrm[72]; /* error message parameters */ + char sqlerrp[8]; + int4 sqlerrd[6]; + /* 0 - estimated number of rows returned */ + /* 1 - serial value after insert or ISAM error code */ + /* 2 - number of rows processed */ + /* 3 - estimated cost */ + /* 4 - offset of the error into the SQL statement */ + /* 5 - rowid after insert */ +#ifdef _FGL_ + char sqlawarn[8]; +#else + struct sqlcaw_s + { + char sqlwarn0; /* = W if any of sqlwarn[1-7] = W */ + char sqlwarn1; /* = W if any truncation occurred or + database has transactions or + no privileges revoked */ + char sqlwarn2; /* = W if a null value returned or + ANSI database */ + char sqlwarn3; /* = W if no. in select list != no. in into list or + turbo backend or no privileges granted */ + char sqlwarn4; /* = W if no where clause on prepared update, delete or + incompatible float format */ + char sqlwarn5; /* = W if non-ANSI statement */ + char sqlwarn6; /* = W if server is in data replication secondary mode */ + char sqlwarn7; /* = W if database locale is different from proc_locale + */ + } sqlwarn; +#endif + } ifx_sqlca_t; + +/* NOTE: 4gl assumes that the sqlwarn structure can be defined as + * sqlawarn -- an 8 character string, because single-char + * variables are not recognized in 4gl. + * + * If this structure should change, the code generated by 4gl compiler + * must also change + */ + +#ifdef VMS +noshare +#endif /* VMS */ + +#define SQLNOTFOUND 100 + +#ifndef IFX_THREAD +extern struct sqlca_s sqlca; + +extern int4 SQLCODE; + +extern char SQLSTATE[]; +#else /* IFX_THREAD */ +extern int4 * ifx_sqlcode(); +extern struct sqlca_s * ifx_sqlca(); +#define SQLCODE (*(ifx_sqlcode())) +#define SQLSTATE ((char *)(ifx_sqlstate())) +#define sqlca (*(ifx_sqlca())) +#endif /* IFX_THREAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* SQLCA_INCL */ + +#line 101 "/opt/informix/incl/esql/sqlca.h" +/* + * EXEC SQL define SUCCESS 0; + */ +#line 12 "testconnect.ec" + +/* + * EXEC SQL define WARNING 1; + */ +#line 13 "testconnect.ec" + +/* + * EXEC SQL define NODATA 100; + */ +#line 14 "testconnect.ec" + +/* + * EXEC SQL define RTERROR -1; + */ +#line 15 "testconnect.ec" + +#line 16 "testconnect.ec" + +/* + * The sqlstate_err() function checks the SQLSTATE status variable to see + * if an error or warning has occurred following an SQL statement. + */ +int4 sqlstate_err() +{ + int4 err_code = -1; + + if(SQLSTATE[0] == '0') /* trap '00', '01', '02' */ + { + switch(SQLSTATE[1]) + { + case '0': /* success - return 0 */ + err_code = 0; + break; + case '1': /* warning - return 1 */ + err_code = 1; + break; + case '2': /* end of data - return 100 */ + err_code = 100; + break; + default: /* error - return SQLCODE */ + break; + } + } + return(err_code); +} + +/* + * The disp_sqlstate_err() function executes the GET DIAGNOSTICS + * statement and prints the detail for each exception that is returned. + */ +void disp_sqlstate_err() +{ + mint j; + +/* + * EXEC SQL BEGIN DECLARE SECTION; + */ +#line 53 "testconnect.ec" +#line 54 "testconnect.ec" +#line 54 "testconnect.ec" +mint exception_count; +#line 55 "testconnect.ec" + char overflow[2]; +#line 56 "testconnect.ec" +mint exception_num = 1; +#line 57 "testconnect.ec" + char class_id[255]; +#line 58 "testconnect.ec" + char subclass_id[255]; +#line 59 "testconnect.ec" + char message[255]; +#line 60 "testconnect.ec" +mint messlen; +#line 61 "testconnect.ec" + char sqlstate_code[6]; +#line 62 "testconnect.ec" +mint i; +/* + * EXEC SQL END DECLARE SECTION; + */ +#line 63 "testconnect.ec" + + + printf("SQLSTATE: %s\n",SQLSTATE); + printf("SQLCODE: %d\n", SQLCODE); + +/* + * EXEC SQL get diagnostics :exception_count = NUMBER, :overflow = MORE; + */ +#line 68 "testconnect.ec" + { +#line 68 "testconnect.ec" + static ifx_hostvar_t _SQhtab[] = + { + { 0, 1, 102, sizeof(exception_count), 0, 0, 0, 0 }, + { 0, 2, 100, 2, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } +#line 68 "testconnect.ec" + }; + _SQhtab[0].hostaddr = (char *)&exception_count; + _SQhtab[1].hostaddr = (overflow); +#line 68 "testconnect.ec" + sqli_diag_get(ESQLINTVERSION, _SQhtab, -1); +#line 68 "testconnect.ec" + } + + printf("EXCEPTIONS: Number=%d\t", exception_count); + printf("More? %s\n", overflow); + + for (i = 1; i <= exception_count; i++) + { +/* + * EXEC SQL get diagnostics exception :i + * :sqlstate_code = RETURNED_SQLSTATE, + * :class_id = CLASS_ORIGIN, :subclass_id = SUBCLASS_ORIGIN, + * :message = MESSAGE_TEXT, :messlen = MESSAGE_LENGTH; + */ +#line 75 "testconnect.ec" + { +#line 78 "testconnect.ec" + static ifx_hostvar_t _SQhtab[] = + { + { 0, 3, 100, 6, 0, 0, 0, 0 }, + { 0, 4, 100, 255, 0, 0, 0, 0 }, + { 0, 5, 100, 255, 0, 0, 0, 0 }, + { 0, 6, 100, 255, 0, 0, 0, 0 }, + { 0, 7, 102, sizeof(messlen), 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } +#line 78 "testconnect.ec" + }; + _SQhtab[0].hostaddr = (sqlstate_code); + _SQhtab[1].hostaddr = (class_id); + _SQhtab[2].hostaddr = (subclass_id); + _SQhtab[3].hostaddr = (message); + _SQhtab[4].hostaddr = (char *)&messlen; +#line 78 "testconnect.ec" + sqli_diag_get(ESQLINTVERSION, _SQhtab, i); +#line 78 "testconnect.ec" + } + + printf("EXCEPTION %d: SQLSTATE=%s\n", i, sqlstate_code); + message[messlen-1] = '\0'; + printf("MESSAGE TEXT: %s\n", message); + j = byleng(class_id, stleng(class_id)); + class_id[j] = '\0'; + printf("CLASS ORIGIN: %s\n",class_id); + j = byleng(subclass_id, stleng(subclass_id)); + subclass_id[j] = '\0'; + printf("SUBCLASS ORIGIN: %s\n",subclass_id); + } +} + +void disp_error(char* stmt) +{ +} + +void disp_exception(char* stmt, int4 sqlerr_code, mint warn_flg) +{ + switch (sqlerr_code) + { + case 0: + case 100: + break; + case 1: + if(warn_flg) + { + printf("Warning encountered in %s\n", stmt); + disp_sqlstate_err(); + } + break; + case -1: + printf("Error encountered in %s\n", stmt); + disp_sqlstate_err(); + break; + default: + printf("INVALID EXCEPTION STATE for %s\n", stmt); + break; + } +} + +int +check() +{ + mint warn_flg = 1; + int4 sqlerr_code = 0; + + sqlerr_code = sqlstate_err(); + disp_exception((char*)"error", sqlerr_code, warn_flg); + + return SQLCODE; +} + + +int +main(int argc, char** argv) +{ + cout << argv[0] << " Informix database access test" << endl; + if (argc != 2) + { + cout << "Usage: " << argv[0] << " connectstring" << endl; + return 2; + } + +/* + * EXEC SQL BEGIN DECLARE SECTION; + */ +#line 143 "testconnect.ec" +#line 144 "testconnect.ec" +#line 144 "testconnect.ec" + char id[256]; +/* + * EXEC SQL END DECLARE SECTION; + */ +#line 145 "testconnect.ec" + + + strcpy( id, argv[1] ); + cout << "using connect string: " << id << endl; + +/* + * EXEC SQL CONNECT TO :id; + */ +#line 150 "testconnect.ec" + { +#line 150 "testconnect.ec" + sqli_connect_open(ESQLINTVERSION, 0, id, (char *) 0, (ifx_conn_t *) 0, 0); +#line 150 "testconnect.ec" + } + check(); + +/* + * EXEC SQL DISCONNECT CURRENT; + */ +#line 153 "testconnect.ec" + { +#line 153 "testconnect.ec" + sqli_connect_close(3, (char *) 0, 0, 0); +#line 153 "testconnect.ec" + } + check(); + + cout << argv[0] << ": done." << endl; + return 0; +} + + +#line 159 "testconnect.ec" diff --git a/reladminif/test/testta.pgc b/reladminif/test/testta.pgc new file mode 100644 index 0000000..38a994c --- /dev/null +++ b/reladminif/test/testta.pgc @@ -0,0 +1,281 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * test class TransactionIF. + * + * + * COMMENTS: + * none + * + * PRECONDITIONS: + * - database exists and is accessible (PG & rasdaman server running) + * - reladminif/DatabaseIF works + * + ***********************************************************************/ + +static const char rcsid[] = "@(#)reladminif,TransactionIf: $Id: testta.pgc,v 1.6 2003/12/27 23:11:43 rasdev Exp $"; + +#define DEBUG_MAIN +#include "debug.hh" + +// constants: +#define DATABASE "RASBASE" + +// pointers representing O2, database, ta and session +AdminIf* admin = NULL; +DatabaseIf* db = NULL; +TransactionIf* ta = NULL; + +int main() +{ + const char *prog = argv[0]; // this program's name + + cout << prog << ": test for transactionif, generated on " << COMPDATE << endl; + + // --- outmost exception catcher ------------------------ + try + { + + // --- (1) preparation: open connection + admin = AdminIf::instance(); + if( !admin ) + { + cout << prog << ": cannot create adminIf instance" << endl; + throw r_Error(); + } + // connect to the database + db = new DatabaseIf(); + if( !admin ) + { + cout << prog << ": cannot create DatabaseIf instance" << endl; + throw r_Error(); + } + db->open( DATABASE ); + + ta = new TransactionIf(); + if( !admin ) + { + cout << prog << ": cannot create TransactionIf instance" << endl; + throw r_Error(); + } + ta->begin( db ); + ta->abort( db ); + ta->commit( db ); + + db->close(); + } + catch(...) + { + cout << prog << ": error abort." << endl; + } + + cout << prog << ": test for transactionif done." << endl; +} + + +void +TransactionIf::begin( bool readOnly ) throw ( r_Error ) +{ + RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ")"); + ENTER( "TransactionIf::begin, readOnly=" << readOnly ); + + isReadOnly = readOnly; + AdminIf::setAborted(false); + AdminIf::setReadOnlyTA(readOnly); + + TALK( "EXEC SQL BEGIN WORK" ); + EXEC SQL BEGIN WORK; + if (sqlca.sqlwarn[2] == 'W') // real error, not just a warning + { + SQLCODE = 0; // FIXME: bad hack, as PG can't reset error state and SQLCODE is queried in many places -- PB 2005-jan-09 + } + else + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing BEGIN"); + LEAVE( "TransactionIf::begin(): error during BEGIN: " << SQLCODE ); + generateException(); + } + + if (readOnly) + { + TALK( "EXEC SQL SET TRANSACTION READ ONLY" ); + EXEC SQL SET TRANSACTION READ ONLY; + // no error check, as this doesn't inhibit work + } + + // prelim.:have additional libpq TA -- PB 2005-jan-09 + TALK( "PQexec( pgConn, BEGIN )" ); + PGresult *pgResult = PQexec( pgConn, "BEGIN" ); + if (PQresultStatus(pgResult) != PGRES_COMMAND_OK) + { + LEAVE( "TransactionIf::begin() Error: cannot open libpq TA: " << PQerrorMessage(pgConn) ); + generateException(); + } + +#ifdef RMANBENCHMARK + DBObject::readTimer.start(); + DBObject::readTimer.pause(); + + DBObject::updateTimer.start(); + DBObject::updateTimer.pause(); + + DBObject::deleteTimer.start(); + DBObject::deleteTimer.pause(); + + DBObject::insertTimer.start(); + DBObject::insertTimer.pause(); + + OId::oidAlloc.start(); + OId::oidAlloc.pause(); + + OId::oidResolve.start(); + OId::oidResolve.pause(); +#endif + + OId::initialize(); + TypeFactory::initialize(); + + LEAVE( "TransactionIf::begin, SQLCODE=" << SQLCODE ); + RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ") "); +} + +void +TransactionIf::commit() throw ( r_Error ) +{ + RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "commit()"); + ENTER( "TransactionIf::commit" ); + + if (isReadOnly) + { + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "read only: aborting"); + TALK( "TA is readonly: aborting" ); + abort(); + } + else + { + AdminIf::setAborted(false); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "set aborted false"); + TypeFactory::freeTempTypes(); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "freed temp types"); + ObjectBroker::clearBroker(); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "cleared broker"); + OId::deinitialize(); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "wrote oid counters"); + AdminIf::setReadOnlyTA(false); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "committing"); + + TALK( "EXEC SQL COMMIT WORK" ); + EXEC SQL COMMIT WORK; + if (check("TransactionIf::begin() COMMIT\0")) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing COMMIT"); + LEAVE( "TransactionIf::commit(): error during COMMIT:" << SQLCODE ); + generateException(); + } + + // prelim.:have additional libpq TA -- PB 2005-jan-09 + TALK( "PQexec( pgConn, END )" ); + PGresult *pgResult = PQexec( pgConn, "END" ); + if (PQresultStatus(pgResult) != PGRES_COMMAND_OK) + { + LEAVE( "TransactionIf::commit() Error: cannot commit libpq TA: " << PQerrorMessage(pgConn) ); + generateException(); + } + + if (lastBase) + { + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "closing dbms"); + lastBase->baseDBMSClose(); + } + } + +#ifdef RMANBENCHMARK + DBObject::readTimer.stop(); + + DBObject::updateTimer.stop(); + + DBObject::deleteTimer.stop(); + + DBObject::insertTimer.stop(); + + OId::oidAlloc.stop(); + + OId::oidResolve.stop(); +#endif + + LEAVE( "TransactionIf::commit" ); + RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "commit() " << endl << endl); +} + +void +TransactionIf::abort() +{ + RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "abort()"); + ENTER( "TransactionIf::abort" ); + + // prelim.:have additional libpq TA -- PB 2005-jan-09 + TALK( "PQexec( pgConn, ABORT )" ); + PGresult *pgResult = PQexec( pgConn, "ABORT" ); + if (PQresultStatus(pgResult) != PGRES_COMMAND_OK) + { + LEAVE( "TransactionIf::abort() Error: cannot abort libpq TA: " << PQerrorMessage(pgConn) ); + generateException(); + } + + AdminIf::setAborted(true); + TypeFactory::freeTempTypes(); + ObjectBroker::clearBroker(); + OId::deinitialize(); + AdminIf::setReadOnlyTA(false); + + TALK( "EXEC SQL ROLLBACK WORK" ); + EXEC SQL ROLLBACK WORK; + if (check("TransactionIf::abort() ROLLBACK\0")) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing ROLLBACK"); + TALK( "TransactionIf::abort(): error during ROLLBACK, still continuing: " << SQLCODE ); + } + if(lastBase) + lastBase->baseDBMSClose(); + +#ifdef RMANBENCHMARK + DBObject::readTimer.stop(); + + DBObject::updateTimer.stop(); + + DBObject::deleteTimer.stop(); + + DBObject::insertTimer.stop(); + + OId::oidAlloc.stop(); + + OId::oidResolve.stop(); +#endif + + LEAVE( "TransactionIf::abort, SQLCODE=" << SQLCODE ); + RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "abort() " << endl << endl); +} + diff --git a/reladminif/transactionif.hh b/reladminif/transactionif.hh new file mode 100644 index 0000000..757325d --- /dev/null +++ b/reladminif/transactionif.hh @@ -0,0 +1,107 @@ +#ifndef _TRANSACTIONIF_HH_ +#define _TRANSACTIONIF_HH_ + +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************ + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ***********************************************************************/ + +//@ManMemo: Module: {\bf transactionif}. + +/*@Doc: +TransactionIf has the functionality to begin, commit and abort a base +DBMS transaction. +*/ + +class TransactionIf; +class DatabaseIf; + +#include <iostream> + +#include "raslib/error.hh" + +class TransactionIf + { + public: + void begin(DatabaseIf* currBase, bool readOnly = false) throw ( r_Error ); + /*@Doc: + begin a TA. + By default, the TA started is a write TA. If {\tt readOnly} is set to 1, + the TA will be read only. + */ + + void commit() throw ( r_Error ); + /*@Doc: + commit a transaction. make all changes permanent. + r_Error is thrown when any objects have problems + writting themselves to the database. + AdminIf::compCompTiles(), TypeFactory::freeTempTypes, + ObjectBroker::clearBroker, OId::deinitialize are called. + COMMIT is issued. the database is closed. + the benchmark timers are stopped. + */ + + void abort(); + /*@Doc: + abort a TA. don't make changes permanent. + AdminIf::compCompTiles(), TypeFactory::freeTempTypes, + ObjectBroker::clearBroker, OId::deinitialize are called. + ROLLBACK is issued. the database is closed. + the benchmark timers are stopped. + */ + + DatabaseIf* getDatabaseIf(); + /*@Doc: + returns the DatabaseIf object associated with this transaction. + */ + + private: + void begin( bool readOnly = false ) throw ( r_Error ); + /*@Doc: + begin a TA. Internal usage only. + This function does not work if the appropriate initializations have'nt + been done. For that reason, it is only appropriate for internal usage. + By default, the TA started is a write TA. If {\tt readOnly} is set to 1, + the TA will be read only. + benchmark timers are started. + */ + + bool isReadOnly; + /*@Doc: + keeps track if the current TA is read only or not + */ + + static DatabaseIf* lastBase; + /*@Doc: + stores the last base used in begin(); + */ + }; + +#endif diff --git a/reladminif/transactionif.pgc b/reladminif/transactionif.pgc new file mode 100644 index 0000000..6bd16f7 --- /dev/null +++ b/reladminif/transactionif.pgc @@ -0,0 +1,242 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * Code with embedded SQL for relational DBMS + * + * + * COMMENTS: + * - reconsider this 604 ignorance! + * + ***********************************************************************/ + +static const char rcsid[] = "@(#)reladminif,TransactionIf: $Id: transactionif.ec,v 1.6 2003/12/27 23:11:43 rasdev Exp $"; + +#include "debug.hh" + +// general embedded SQL related definitions +EXEC SQL include sqlglobals.h; + +#include "transactionif.hh" +#include "raslib/rmdebug.hh" +#include "adminif.hh" +#include "oidif.hh" +#include "catalogmgr/typefactory.hh" +#include "sqlerror.hh" +#include "objectbroker.hh" +#include "databaseif.hh" + +// PG stuff for libpg connection maintenance +#include "libpq-fe.h" +extern PGconn *pgConn; + + +void +TransactionIf::begin( bool readOnly ) throw ( r_Error ) +{ + RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ")"); + ENTER( "TransactionIf::begin, readOnly=" << readOnly ); + + isReadOnly = readOnly; + AdminIf::setAborted(false); + AdminIf::setReadOnlyTA(readOnly); + + TALK( "EXEC SQL BEGIN WORK" ); + EXEC SQL BEGIN WORK; + if (sqlca.sqlwarn[2] == 'W') // real error, not just a warning + { + SQLCODE = 0; // FIXME: bad hack, as PG can't reset error state and SQLCODE is queried in many places -- PB 2005-jan-09 + } + else + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing BEGIN"); + LEAVE( "TransactionIf::begin(): error during BEGIN: " << SQLCODE ); + generateException(); + } + + if (readOnly) + { + TALK( "EXEC SQL SET TRANSACTION READ ONLY" ); + EXEC SQL SET TRANSACTION READ ONLY; + // no error check, as this doesn't inhibit work + } + + // prelim.:have additional libpq TA -- PB 2005-jan-09 + TALK( "PQexec( pgConn, BEGIN )" ); + PGresult *pgResult = PQexec( pgConn, "BEGIN" ); + if (PQresultStatus(pgResult) != PGRES_COMMAND_OK) + { + LEAVE( "TransactionIf::begin() Error: cannot open libpq TA: " << PQerrorMessage(pgConn) ); + generateException(); + } + +#ifdef RMANBENCHMARK + DBObject::readTimer.start(); + DBObject::readTimer.pause(); + + DBObject::updateTimer.start(); + DBObject::updateTimer.pause(); + + DBObject::deleteTimer.start(); + DBObject::deleteTimer.pause(); + + DBObject::insertTimer.start(); + DBObject::insertTimer.pause(); + + OId::oidAlloc.start(); + OId::oidAlloc.pause(); + + OId::oidResolve.start(); + OId::oidResolve.pause(); +#endif + + OId::initialize(); + TypeFactory::initialize(); + + LEAVE( "TransactionIf::begin, SQLCODE=" << SQLCODE ); + RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ") "); +} + +void +TransactionIf::commit() throw ( r_Error ) +{ + RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "commit()"); + ENTER( "TransactionIf::commit" ); + + if (isReadOnly) + { + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "read only: aborting"); + TALK( "TA is readonly: aborting" ); + abort(); + } + else + { + AdminIf::setAborted(false); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "set aborted false"); + TypeFactory::freeTempTypes(); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "freed temp types"); + ObjectBroker::clearBroker(); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "cleared broker"); + OId::deinitialize(); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "wrote oid counters"); + AdminIf::setReadOnlyTA(false); + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "committing"); + + // prelim.:have additional libpq TA -- PB 2005-jan-09 + TALK( "PQexec( pgConn, END )" ); + PGresult *pgResult = PQexec( pgConn, "END" ); + if (PQresultStatus(pgResult) != PGRES_COMMAND_OK) + { + LEAVE( "TransactionIf::commit() Error: cannot commit libpq TA: " << PQerrorMessage(pgConn) ); + generateException(); + } + + TALK( "EXEC SQL COMMIT WORK" ); + EXEC SQL COMMIT WORK; + if (SQLCODE == -604) // = "no TA open" - seems to be a hickup from our double transaction + // so we ignore it; FIXME: reinvestigate! -- PB 25-aug-2005 + { + TALK( "TransactionIf::commit(): ignoring 'no TA open' error (SQLCODE -604) during COMMIT." ); + } + else if (check("TransactionIf::begin() COMMIT\0")) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing COMMIT"); + LEAVE( "TransactionIf::commit(): error during COMMIT:" << SQLCODE ); + generateException(); + } + if (lastBase) + { + RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "closing dbms"); + lastBase->baseDBMSClose(); + } + } + +#ifdef RMANBENCHMARK + DBObject::readTimer.stop(); + + DBObject::updateTimer.stop(); + + DBObject::deleteTimer.stop(); + + DBObject::insertTimer.stop(); + + OId::oidAlloc.stop(); + + OId::oidResolve.stop(); +#endif + + LEAVE( "TransactionIf::commit" ); + RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "commit() " << endl << endl); +} + +void +TransactionIf::abort() +{ + RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "abort()"); + ENTER( "TransactionIf::abort" ); + + // prelim.:have additional libpq TA -- PB 2005-jan-09 + TALK( "PQexec( pgConn, ABORT )" ); + PGresult *pgResult = PQexec( pgConn, "ABORT" ); + if (PQresultStatus(pgResult) != PGRES_COMMAND_OK) + { + LEAVE( "TransactionIf::abort() Error: cannot abort libpq TA: " << PQerrorMessage(pgConn) ); + generateException(); + } + + AdminIf::setAborted(true); + TypeFactory::freeTempTypes(); + ObjectBroker::clearBroker(); + OId::deinitialize(); + AdminIf::setReadOnlyTA(false); + + TALK( "EXEC SQL ROLLBACK WORK" ); + EXEC SQL ROLLBACK WORK; + if (check("TransactionIf::abort() ROLLBACK\0")) + { + RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing ROLLBACK"); + TALK( "TransactionIf::abort(): error during ROLLBACK, still continuing: " << SQLCODE ); + } + if(lastBase) + lastBase->baseDBMSClose(); + +#ifdef RMANBENCHMARK + DBObject::readTimer.stop(); + + DBObject::updateTimer.stop(); + + DBObject::deleteTimer.stop(); + + DBObject::insertTimer.stop(); + + OId::oidAlloc.stop(); + + OId::oidResolve.stop(); +#endif + + LEAVE( "TransactionIf::abort, SQLCODE=" << SQLCODE ); + RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "abort() " << endl << endl); +} + diff --git a/reladminif/transactionifcommon.cc b/reladminif/transactionifcommon.cc new file mode 100644 index 0000000..730b5b7 --- /dev/null +++ b/reladminif/transactionifcommon.cc @@ -0,0 +1,69 @@ +/* +* This file is part of rasdaman community. +* +* Rasdaman community is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* Rasdaman community 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with rasdaman community. If not, see <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * Code common to all DBMS interface implementations + */ + +#include <iostream> + +#include "transactionif.hh" +#include "adminif.hh" +#include "catalogmgr/typefactory.hh" +#include "oidif.hh" +#include "raslib/rmdebug.hh" +#include "databaseif.hh" +#include "externs.h" +#include "objectbroker.hh" +#include "raslib/error.hh" +#include "dbobject.hh" +#include "sqlerror.hh" + +DatabaseIf* TransactionIf::lastBase = NULL; + +DatabaseIf* +TransactionIf::getDatabaseIf() + { + RMDBGONCE(2, RMDebug::module_adminif, "TransactionIf", "getDatabaseIf() " << lastBase << endl); + return lastBase; + } + +void +TransactionIf::begin( DatabaseIf* currBase, bool readOnly ) throw ( r_Error ) + { + RMDBGENTER(4, RMDebug::module_adminif, "TransactionIf", "begin(" << currBase->getName() << ", " << readOnly << ")"); + try { + currBase->baseDBMSOpen(); + } + catch(r_Error& err) { + currBase->baseDBMSClose(); + throw err; + } + lastBase = currBase; + begin(readOnly); + RMDBGEXIT(4, RMDebug::module_adminif, "TransactionIf", "begin(" << currBase->getName() << ", " << readOnly << ") "); + } + + |