summaryrefslogtreecommitdiffstats
path: root/servercomm/servercomm2.cc
diff options
context:
space:
mode:
Diffstat (limited to 'servercomm/servercomm2.cc')
-rw-r--r--servercomm/servercomm2.cc4051
1 files changed, 4051 insertions, 0 deletions
diff --git a/servercomm/servercomm2.cc b/servercomm/servercomm2.cc
new file mode 100644
index 0000000..7fcbef2
--- /dev/null
+++ b/servercomm/servercomm2.cc
@@ -0,0 +1,4051 @@
+/*
+* 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>.
+/
+/**
+ * SOURCE: servercomm2.cc
+ *
+ * MODULE: servercomm
+ * CLASS: ServerComm
+ *
+ * PURPOSE:
+ *
+ * COMMENTS:
+ * - FIXME: catch exceptions in all operations
+ * - return values & their meaning see servercomm.hh
+ * - FIXME: "client not registered" delivers sometimes 1, sometimes 3
+ *
+*/
+
+#include "mymalloc/mymalloc.h"
+
+static const char rcsid[] = "@(#)servercomm2, ServerComm: $Id: servercomm2.cc,v 1.121 2005/09/07 23:23:31 rasdev Exp $";
+
+// after some time please take this and everything related to it out (26.06.2001)
+#define ANDREAS_2306
+
+#include <iostream>
+#include <malloc.h>
+#include <string.h>
+#include <math.h> // for log(), exp(), floor()
+#include <ctime> // time
+#include <iomanip>
+
+#ifdef PURIFY
+#include <purify.h>
+#endif
+
+#ifdef RMANBENCHMARK
+ // to control GenericCompression::decompTimer and GenericCompression::compTimer
+ #include "gencompression.hh"
+ #include "zlibcompression.hh"
+#endif
+
+#ifdef SOLARIS
+ #define PORTMAP // define to use function declarations for old interfaces
+ #include <rpc/rpc.h>
+
+ extern int _rpcpmstart;
+
+ // function prototype with C linkage
+ extern "C" int gethostname(char *name, int namelen);
+#else // HPUX
+ #include <rpc/rpc.h>
+#endif
+
+#include <rpc/pmap_clnt.h>
+
+#include "raslib/rmdebug.hh"
+#include "debug.hh"
+#include "raslib/rminit.hh"
+#include "raslib/error.hh"
+#include "raslib/minterval.hh"
+#include "raslib/mddtypes.hh"
+#include "raslib/basetype.hh"
+#include "raslib/endian.hh"
+#include "raslib/odmgtypes.hh"
+#include "raslib/parseparams.hh"
+// for transfer compression
+#include "compression/tilecompression.hh"
+
+#include "servercomm/servercomm.hh"
+#include "catalogmgr/typefactory.hh"
+
+#include "mddmgr/mddcoll.hh"
+#include "mddmgr/mddobj.hh"
+#include "mddmgr/mddcolliter.hh"
+#include "tilemgr/tile.hh"
+
+#include "relcatalogif/mddtype.hh"
+#include "relcatalogif/mdddomaintype.hh"
+#include "relcatalogif/settype.hh"
+#include "reladminif/eoid.hh"
+
+#include "qlparser/qtmdd.hh"
+#include "qlparser/qtatomicdata.hh"
+#include "qlparser/qtcomplexdata.hh"
+#include "qlparser/qtintervaldata.hh"
+#include "qlparser/qtmintervaldata.hh"
+#include "qlparser/qtpointdata.hh"
+#include "qlparser/qtstringdata.hh"
+
+// console output describing successful/unsuccessful actions
+#define MSG_OK "ok"
+#define MSG_FAILED "failed"
+
+// include and extern declarations for the query parsing
+#include "qlparser/querytree.hh"
+extern int yyparse(void *);
+extern void yyreset();
+#ifdef NOPRE
+char* ppInBuf = 0;
+char* ppOutBuf = 0;
+void ppreset()
+{
+ RMInit::logOut << "Error: Preprocessor not compiled in." << std::endl;
+ RMInit::dbgOut << "Error: Preprocessor not compiled in." << std::endl;
+ throw r_Error(ILLEGALSTATEREACHED);
+}
+
+int ppparse()
+{
+ RMInit::logOut << "Error: Preprocessor not compiled in." << std::endl;
+ RMInit::dbgOut << "Error: Preprocessor not compiled in." << std::endl;
+ throw r_Error(ILLEGALSTATEREACHED);
+}
+#else
+extern char* ppInBuf;
+extern char* ppOutBuf;
+extern void ppreset();
+extern int ppparse();
+#endif
+extern bool udfEnabled;
+
+extern QueryTree* parseQueryTree;
+extern ParseInfo* parseError;
+extern char* beginParseString;
+extern char* iterParseString;
+extern unsigned long maxTransferBufferSize;
+extern char* dbSchema;
+
+MDDColl* mddConstants=0;
+
+ServerComm::ClientTblElt* currentClientTblElt=0;
+
+// Once again a function prototype. The first one is for the RPC dispatcher
+// function located in the server stub file rpcif_svc.c and the second one
+// is for the garbage collection function pointed to by the signal handler.
+extern "C"
+{
+ // static void rpcif_1( struct svc_req*, register SVCXPRT* );
+ char* rpcif_1( struct svc_req*, register SVCXPRT* );
+ void garbageCollection( int );
+}
+
+// this is a temporary thing
+extern int globalOptimizationLevel;
+
+// This is needed in httpserver.cc
+char globalHTTPSetTypeStructure[4096];
+
+// constant for clientID
+const char* ServerComm::HTTPCLIENT = "HTTPClient";
+
+///ensureTileFormat returns the following:
+const int ServerComm::ENSURE_TILE_FORMAT_OK=0;
+const int ServerComm::ENSURE_TILE_FORMAT_BAD=-1;
+
+/*************************************************************************
+ * Method name...: openDB( unsigned long callingClientId,
+ * const char* dbName ,
+ * const char* userName )
+ ************************************************************************/
+unsigned short
+ServerComm::openDB( unsigned long callingClientId,
+ const char* dbName,
+ const char* userName )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "openDB" )
+
+ unsigned short returnValue=0;
+
+ RMInit::logOut << "Request: openDB '" << dbName << "'..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // release transfer collection/iterator
+ context->releaseTransferStructures();
+
+ // open the database
+ try
+ {
+ context->database.open( dbName );
+ }
+ catch(r_Error& err)
+ {
+ if(err.get_kind() == r_Error::r_Error_DatabaseUnknown)
+ {
+ RMInit::logOut << "Error: database does not exist." << endl;
+ returnValue = 2;
+ }
+ else if(err.get_kind() == r_Error::r_Error_DatabaseOpen)
+ {
+ // ignore re-open to be fault tolerant -- PB 2004-dec-16
+ // RMInit::logOut << "Error: database is already open." << endl;
+ returnValue = 3;
+ }
+ else
+ {
+ RMInit::logOut << "Error: exception " << err.get_errorno() << ": " << err.what() << endl;
+ //should be something else. but better than no message about the problem at all
+ returnValue = 2;
+ }
+ }
+
+ if( returnValue == 0 )
+ {
+ // database was successfully opened, so assign db and user name
+ delete[] context->baseName;
+ context->baseName = new char[strlen( dbName )+1];
+ strcpy( context->baseName, dbName );
+
+ delete[] context->userName;
+ context->userName = new char[strlen( userName )+1];
+ strcpy( context->userName, userName );
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+
+ context->release();
+
+ // ignore "already open" error to be more fault tolerant -- PB 2004-dec-16
+ if( returnValue == 3 )
+ {
+ RMInit::logOut << "Warning: database already open for user '" << userName << "', ignoring command." << endl;
+ returnValue = 0;
+ }
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "openDB" )
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: closeDB( unsigned long callingClientId )
+ ************************************************************************/
+unsigned short
+ServerComm::closeDB( unsigned long callingClientId )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "closeDB" )
+ unsigned short returnValue;
+
+ RMInit::logOut << "Request: closeDB..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // release transfer collection/iterator
+ context->releaseTransferStructures();
+
+ // If the current transaction belongs to this client, abort it.
+ if( transactionActive == callingClientId )
+ {
+ RMInit::logOut << "Warning: transaction is open; aborting this transaction..." << std::flush;
+
+ context->transaction.abort();
+ transactionActive = 0;
+ }
+
+ // close the database
+ context->database.close();
+
+ // reset database name
+ delete[] context->baseName;
+ context->baseName = new char[5];
+ strcpy( context->baseName, "none" );
+
+ returnValue = 0;
+
+ context->release();
+
+#ifdef PURIFY
+ purify_new_leaks();
+#endif
+
+ RMInit::logOut << MSG_OK << endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "closeDB" )
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: createDB( char* name )
+ ************************************************************************/
+unsigned short
+ServerComm::createDB( char* name )
+{
+ unsigned short returnValue;
+
+ // FIXME: what about client id? -- PB 2005-aug-27
+
+ RMInit::logOut << "Request: createDB '" << name << "'..." << std::flush;
+
+ DatabaseIf* tempDbIf = new DatabaseIf;
+
+ // create the database
+ try
+ {
+ tempDbIf->createDB( name, dbSchema );
+ RMInit::logOut << MSG_OK << endl;
+ }
+ catch(r_Error& myErr)
+ {
+ RMInit::logOut << "Error: exception " << myErr.get_errorno() << ": " << myErr.what() << std::endl;
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ throw;
+ }
+ catch(...)
+ {
+ RMInit::logOut << std::endl << "Error: Unspecified exception." << std::endl;
+ }
+
+ delete tempDbIf;
+
+ // FIXME: set proper return value on failure (update .hh!) -- PB 2005-aug-27
+ returnValue = 0;
+
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: destroyDB( char* name )
+ ************************************************************************/
+unsigned short
+ServerComm::destroyDB( char* name )
+{
+ // Note: why no check for client id here? -- PB 2005-aug-25
+
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: destroyDB '" << name << "'..." << std::flush;
+
+ DatabaseIf* tempDbIf = new DatabaseIf;
+
+ // begin a temporary transaction because persistent data (as databases)
+ // can only be manipulated within active transactions.
+ // tempTaIf->begin(tempDbIf);
+
+ // destroy the database
+ tempDbIf->destroyDB( name );
+
+ // commit the temporary transaction
+ // tempTaIf->commit();
+
+ delete tempDbIf;
+
+ RMInit::logOut << MSG_OK << std::endl;
+
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: beginTA( unsigned long callingClientId )
+ ************************************************************************/
+unsigned short
+ServerComm::beginTA( unsigned long callingClientId,
+ unsigned short readOnly )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "beginTA" )
+ unsigned short returnValue;
+
+ RMInit::logOut << "Request: beginTA (" << ( readOnly ? "read" : "write" ) << ")..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context == 0 )
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+ else if ( transactionActive )
+ {
+ RMInit::logOut << "Error: transaction already active." << std::endl;
+ returnValue = 2;
+ context->release();
+ }
+ else
+ {
+ // release transfer collection/iterator
+ context->releaseTransferStructures();
+
+#ifdef RMANBENCHMARK
+ if( RManBenchmark > 0 )
+ context->taTimer = new RMTimer("ServerComm", "transaction time ");
+#endif
+ try
+ {
+ // start the transaction
+ context->transaction.begin( &(context->database), readOnly );
+ RMInit::logOut << MSG_OK << endl;
+ }
+ catch(r_Error& err)
+ {
+ RMInit::logOut << "Error: exception " << err.get_errorno() << ": " << err.what() << std::endl;
+ context->release();
+ throw;
+ }
+
+ // lock the semaphor
+ transactionActive = callingClientId;
+ returnValue = 0;
+
+ context->release();
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "beginTA" )
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: commitTA( unsigned long callingClientId )
+ ************************************************************************/
+unsigned short
+ServerComm::commitTA( unsigned long callingClientId )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "commitTA" )
+ unsigned short returnValue;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ RMInit::logOut << "Request: commitTA..." << std::flush;
+
+ if( context != 0 )
+ {
+#ifdef RMANBENCHMARK
+ RMTimer* commitTimer = 0;
+
+ if( RManBenchmark > 0 )
+ commitTimer = new RMTimer("ServerComm", "commit time ");
+#endif
+
+ // release transfer collection/iterator within the transaction they are created
+ context->releaseTransferStructures();
+
+ // commit the transaction
+ context->transaction.commit();
+
+ // unlock the semaphor
+ transactionActive = 0;
+
+ returnValue = 0;
+
+#ifdef RMANBENCHMARK
+ if( commitTimer ) delete commitTimer;
+#endif
+
+ context->release();
+
+ RMInit::logOut << MSG_OK << endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+#ifdef RMANBENCHMARK
+ if( context->taTimer )
+ delete context->taTimer;
+ context->taTimer = 0;
+#endif
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "commitTA" )
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: abortTA( unsigned long callingClientId )
+ ************************************************************************/
+unsigned short
+ServerComm::abortTA( unsigned long callingClientId )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "abortTA" )
+ unsigned short returnValue;
+
+ RMInit::logOut << "Request: abortTA..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // release transfer collection/iterator within the transaction they are created
+ context->releaseTransferStructures();
+
+ // abort the transaction
+ context->transaction.abort();
+
+ // unlock the semaphor
+ transactionActive = 0;
+
+ returnValue = 0;
+
+ context->release();
+
+ RMInit::logOut << MSG_OK << endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+#ifdef RMANBENCHMARK
+ if( context->taTimer ) delete context->taTimer;
+ context->taTimer = 0;
+#endif
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "abortTA" )
+ return returnValue;
+}
+
+
+/*************************************************************************
+ * Method name...: isTAOpen()
+ * as right now only one transaction can be active per server,
+ * we only have to check the sema.
+ * returns:
+ * true iff a transaction is open
+ ************************************************************************/
+bool
+ServerComm::isTAOpen( unsigned long callingClientId )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "isTAOpen" )
+
+ RMInit::logOut << "Request: isTAOpen..." << std::flush;
+
+ bool returnValue = transactionActive;
+
+ RMInit::logOut << MSG_OK << (transactionActive?", is active.":", is not active.") << endl;
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "isTAOpen" )
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::insertColl( unsigned long callingClientId,
+ const char* collName,
+ const char* typeName,
+ r_OId& oid )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "insertColl" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: insertColl '" << collName << "' with type '" << typeName << "'..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer structures
+ context->releaseTransferStructures();
+
+ //
+ // create the collenction
+ //
+
+ // get collection type
+ CollectionType* collType = (CollectionType*)TypeFactory::mapSetType( typeName );
+
+ if( collType )
+ {
+ try
+ {
+ MDDColl* coll = MDDColl::createMDDCollection(collName, OId(oid.get_local_oid()), collType);
+ delete coll;
+ RMInit::logOut << MSG_OK << endl;
+ }
+ catch( r_Error& obj )
+ {
+ if (obj.get_kind() == r_Error::r_Error_NameNotUnique)
+ {
+ RMInit::logOut << "Error: collection exists already." << std::endl;
+ returnValue = 3;
+ }
+ else
+ {
+ RMInit::logOut << "Error: cannot create collection: " << obj.get_errorno() << " " << obj.what() << std::endl;
+ //this should be another code...
+ returnValue = 3;
+ }
+ }
+
+ }
+ else
+ {
+ RMInit::logOut << "Error: unknown collection type: '" << typeName << "'." << std::endl;
+ returnValue = 2;
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "insertColl" )
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: deleteCollByName( unsigned long callingClientId,
+ * const char* collName )
+ ************************************************************************/
+unsigned short
+ServerComm::deleteCollByName( unsigned long callingClientId,
+ const char* collName )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "deleteCollByName(" << callingClientId << ", " << collName << ")")
+ unsigned short returnValue;
+
+ RMInit::logOut << "Request: deleteCollByName '" << collName << "'..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer structures
+ context->releaseTransferStructures();
+
+ //
+ // delete collenction
+ //
+
+ // delete root object with collection name
+ if (MDDColl::dropMDDCollection(collName))
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "collection dropped")
+ RMInit::logOut << MSG_OK << std::endl;
+ returnValue = 0;
+ }
+ else
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "did not drop collection")
+ RMInit::logOut << "Error: collection does not exist." << std::endl;
+ returnValue = 2;
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "deleteCollByName(" << callingClientId << ", " << collName << ") " << returnValue)
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::deleteObjByOId( unsigned long callingClientId,
+ r_OId& oid )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "deleteObjByOId(" << callingClientId << ", " << oid << ")");
+ unsigned short returnValue;
+
+ RMInit::logOut << "Request: deleteObjByOId " << oid << "..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer structures
+ context->releaseTransferStructures();
+
+ // determine type of object
+ OId oidIf( oid.get_local_oid() );
+
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "OId of object " << oidIf)
+ OId::OIdType objType = oidIf.getType();
+
+ switch( objType )
+ {
+ case OId::MDDOID:
+ // FIXME: why not deleted?? -- PB 2005-aug-27
+ RMInit::logOut << "found MDD object; NOT deleted yet..." << MSG_OK << std::endl;
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "not deleting mdd object")
+ returnValue = 0;
+ break;
+ case OId::MDDCOLLOID:
+ RMInit::logOut << "deleting collection..." << std::flush;
+ // delete root object with collection name
+ if (MDDColl::dropMDDCollection(oidIf))
+ {
+ RMInit::logOut << MSG_OK << std::endl;
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "deleted mdd coll")
+ returnValue = 0;
+ }
+ else
+ {
+ RMInit::logOut << "Error: Collection does not exist." << std::endl;
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "did not delete mdd coll")
+ returnValue = 2;
+ }
+ break;
+ default:
+ RMInit::logOut << "Error: object has unknown type: " << objType << std::endl;
+ returnValue = 2;
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "deleteObjByOId(" << callingClientId << ", " << oid << ")" << returnValue)
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::removeObjFromColl( unsigned long callingClientId,
+ const char* collName,
+ r_OId& oid )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "removeObjFromColl(" << callingClientId << ", " << collName << ", " << oid << ")")
+ unsigned short returnValue;
+
+ RMInit::logOut << "Request: removeObjFromColl '" << collName << "', oid " << oid << "..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer structures
+ context->releaseTransferStructures();
+
+ OId oidIf( oid.get_local_oid() );
+
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "mdd object oid " << oidIf)
+
+ // open collection
+ MDDColl* coll = 0;
+
+ try
+ {
+ coll = MDDColl::getMDDCollection(collName);
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "retrieved mdd coll")
+ }
+ catch(r_Error& obj)
+ {
+ // collection name invalid
+ if (obj.get_kind() == r_Error::r_Error_ObjectUnknown)
+ {
+ RMInit::logOut << "Error: collection not found." << std::endl;
+ returnValue = 2;
+ }
+ else
+ {
+ RMInit::logOut << "Error " << obj.get_errorno() << ": " << obj.what() << std::endl;
+ // there should be another return code
+ returnValue = 2;
+ }
+ coll = NULL;
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ throw;
+ }
+ catch(...)
+ {
+ // collection name invalid
+ RMInit::logOut << "Error: unspecified exception." << std::endl;
+ returnValue = 2;
+ }
+
+ if( coll )
+ {
+ if (coll->isPersistent())
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "retrieved persistent mdd coll")
+
+ OId collId;
+ coll->getOId(collId);
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "mdd coll oid " << collId)
+ MDDColl::removeMDDObject(collId, oidIf);
+
+ // no error management yet -> returnValue = 3
+
+ RMInit::logOut << MSG_OK << std::endl;
+ returnValue = 0;
+
+ delete coll;
+ }
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "removeObjFromColl(" << callingClientId << ", " << collName << ", " << oid << ") " << returnValue)
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::insertMDD( unsigned long callingClientId,
+ const char* collName,
+ RPCMarray* rpcMarray,
+ const char* typeName,
+ r_OId& oid )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "insertMDD" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: insertMDD type='" << typeName << "' into collection '" << collName << "'..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+ r_Data_Format myDataFmt = r_Array;
+ r_Data_Format myCurrentFmt = r_Array;
+
+ if( context != 0 )
+ {
+ // delete old transfer structures
+ context->releaseTransferStructures();
+
+ //
+ // insert the object into the collection
+ //
+
+ // Determine the type of the MDD to be inserted.
+ const MDDType* mddType = TypeFactory::mapMDDType( typeName );
+ if( mddType )
+ {
+ if( mddType->getSubtype() != MDDType::MDDONLYTYPE )
+ {
+ //
+ // open the collection
+ //
+
+ MDDColl* collection=0;
+ MDDColl* almost = 0;
+
+ try
+ {
+ almost = MDDColl::getMDDCollection( collName );
+ if (almost->isPersistent())
+ collection = (MDDColl*)almost;
+ else
+ {
+ RMInit::logOut << "Error: inserting into system collection is illegal." << std::endl;
+ context->release(); //!!!
+ throw r_Error(SYSTEM_COLLECTION_NOT_WRITABLE);
+ }
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error " << err.get_errorno() << ": " << err.what() << std::endl;
+ returnValue = 5;
+ context->release(); //!!!
+ throw;
+ }
+ catch(...)
+ {
+ returnValue = 5;
+ RMInit::logOut << "Error: unspecific exception during collection read." << std::endl;
+ context->release();
+ return returnValue;
+ }
+
+ //
+ // check MDD and collection type for compatibility
+ //
+
+ r_Minterval domain( rpcMarray->domain );
+
+ RMDBGIF(4, RMDebug::module_servercomm, "ServerComm", \
+ char* collTypeStructure = collection->getCollectionType()->getTypeStructure(); \
+ char* mddTypeStructure = mddType->getTypeStructure(); \
+ RMInit::dbgOut << std::endl << "Collection type structure.: " << collTypeStructure << std::endl \
+ << "MDD type structure........: " << mddTypeStructure << std::endl \
+ << "MDD domain................: " << domain << std::endl; \
+ free( collTypeStructure ); \
+ free( mddTypeStructure ); )
+
+ if( !mddType->compatibleWithDomain( &domain ) )
+ {
+ // free resources
+ collection->releaseAll();
+ delete collection;
+
+ // return error
+ returnValue = 4;
+ RMInit::logOut << "Error: MDD type is not compatible wrt. its domain: " << domain << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ if( !collection->getCollectionType()->compatibleWith( mddType ) )
+ {
+ // free resources
+ collection->releaseAll();
+ delete collection;
+
+ // return error
+ returnValue = 3;
+ RMInit::logOut << "Error: MDD and collection types are incompatible." << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ //
+ // create persistent MDD object
+ //
+
+ MDDBaseType* mddBaseType = (MDDBaseType*)mddType;
+ char* dataPtr = rpcMarray->data.confarray_val;
+ unsigned long dataSize = rpcMarray->data.confarray_len;
+ // reset data area from rpc structure so that it is not deleted
+ // deletion is done by TransTile resp. Tile
+ rpcMarray->data.confarray_len = 0;
+ rpcMarray->data.confarray_val = 0;
+ int getMDDData=0;
+ const BaseType* baseType = mddBaseType->getBaseType();
+ unsigned long byteCount = domain.cell_count() * rpcMarray->cellTypeLength;
+ //r_Data_Format storageFormat = (r_Data_Format)(rpcMarray->storageFormat);
+
+ MDDObj* mddObj=0;
+ StorageLayout ms;
+ ms.setTileSize(StorageLayout::DefaultTileSize);
+ ms.setIndexType(StorageLayout::DefaultIndexType);
+ ms.setTilingScheme(StorageLayout::DefaultTilingScheme);
+ if (domain.dimension() == StorageLayout::DefaultTileConfiguration.dimension())
+ ms.setTileConfiguration(StorageLayout::DefaultTileConfiguration);
+
+ try
+ {
+ mddObj = new MDDObj(mddBaseType, domain, OId(oid.get_local_oid()), ms);
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error " << obj.get_errorno() << ": " << obj.what() << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch(...)
+ {
+ returnValue = 6;
+ RMInit::logOut << "Error: unspecific exception during creation of persistent object." << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ myDataFmt = (r_Data_Format)(rpcMarray->storageFormat);
+ myCurrentFmt = (r_Data_Format)(rpcMarray->currentFormat);
+ RMInit::dbgOut << "oid " << oid
+ << ", domain " << domain
+ << ", cell length " << rpcMarray->cellTypeLength
+ << ", data size " << dataSize
+ << ", rpc storage " << myDataFmt
+ << ", rpc transfer " << myCurrentFmt << " " << std::flush;
+
+ // store in the specified storage format; the current tile format afterwards will be the
+ // requested format if all went well, but use the (new) current format to be sure.
+ // Don't repack here, however, because it might be retiled before storage.
+ if(ensureTileFormat(myCurrentFmt, myDataFmt, domain,
+ baseType, dataPtr, dataSize, 0, 1, context->storageFormatParams) != ENSURE_TILE_FORMAT_OK)
+ {
+ //FIXME returnValue
+ returnValue = 6;
+ RMInit::logOut << "Error: illegal tile format for creating object." << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ // if compressed, getMDDData is != 0
+ if (myCurrentFmt != r_Array)
+ getMDDData = dataSize;
+
+ // This should check the compressed size rather than the raw data size
+ if( RMInit::tiling && dataSize > StorageLayout::DefaultTileSize )
+ {
+ r_Range edgeLength = (r_Range)floor(exp((1/(r_Double)domain.dimension())*
+ log((r_Double)StorageLayout::DefaultTileSize/rpcMarray->cellTypeLength)));
+
+ if (edgeLength <1)
+ edgeLength=1;
+
+ r_Minterval tileDom( domain.dimension() );
+ for( int i=0; i<tileDom.dimension(); i++ )
+ tileDom << r_Sinterval( (r_Range)0, (r_Range)(edgeLength-1) );
+
+ Tile* entireTile = 0;
+
+ // compression intelligence moved somewhere else, but creation of
+ // compression object in tile constructor might throw an error.
+
+ if (r_Tile_Compression::check_data_format(myDataFmt) == r_Tile_Compression::COMPRESSION)
+ {
+ RMInit::dbgOut << "insertTile created new TransTile (" << myDataFmt << "), ";
+ }
+ else
+ {
+ RMInit::logOut << "Warning: unsupported data format '" << myCurrentFmt << "', falling back to 'r_Array'..." << std::flush;
+ myCurrentFmt = r_Array;
+ }
+ entireTile = new Tile( domain, baseType, dataPtr, getMDDData, myDataFmt );
+
+ entireTile->setParameters(context->storageFormatParams);
+ vector< Tile *>* tileSet = entireTile->splitTile( tileDom );
+ if (entireTile->isPersistent())
+ entireTile->setPersistent(0);
+ delete entireTile;
+
+ RMInit::logOut << "creating " << tileSet->size() << " tile(s)..." << std::flush;
+
+ for( vector<Tile*>::iterator iter = tileSet->begin(); iter != tileSet->end(); iter++ )
+ mddObj->insertTile( *iter );
+
+ // delete the vector again
+ delete tileSet;
+ }
+ else
+ {
+ Tile* tile = 0;
+
+ if (r_Tile_Compression::check_data_format(myDataFmt) == r_Tile_Compression::COMPRESSION)
+ {
+ tile = new Tile( domain, baseType, dataPtr, getMDDData, myDataFmt );
+ RMInit::dbgOut << "insertTile created new TransTile (" << myDataFmt << "), ";
+ }
+ else
+ {
+ RMInit::logOut << "Error: Unsupported data format '" << myCurrentFmt << "', will ingore it..." << std::flush;
+ tile = new Tile( domain, baseType, dataPtr, getMDDData );
+ }
+
+ tile->setParameters(context->storageFormatParams);
+ RMInit::dbgOut << "one tile..." << std::flush;
+ mddObj->insertTile( tile );
+ }
+
+ collection->insert( mddObj );
+
+ // free transient memory
+ collection->releaseAll();
+
+ delete collection;
+
+ //
+ // done
+ //
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: MDD type name '" << typeName << "' has no base type." << std::endl;
+ returnValue = 2;
+ }
+ }
+ else
+ {
+ RMInit::logOut << "Error: MDD type name '" << typeName << "' not found." << std::endl;
+ returnValue = 2;
+ }
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "insertMDD " << returnValue)
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::insertTileSplitted( unsigned long callingClientId,
+ int isPersistent,
+ RPCMarray* rpcMarray,
+ r_Minterval* tileSize)
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "insertTileSplitted" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: insertTile..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ BaseType* baseType = NULL;
+
+ if( isPersistent )
+ baseType = (BaseType*)context->assembleMDD->getCellType();
+ else
+ baseType = (BaseType*)context->transferMDD->getCellType();
+
+ // The type of the tile has to be the one of the MDD.
+ // type check missing
+
+ if( baseType != NULL )
+ {
+ r_Minterval domain( rpcMarray->domain );
+ char* dataPtr = rpcMarray->data.confarray_val;
+ unsigned long dataSize = rpcMarray->data.confarray_len;
+ // reset data area from rpc structure so that it is not deleted
+ // deletion is done by TransTile resp. Tile
+ rpcMarray->data.confarray_len = 0;
+ rpcMarray->data.confarray_val = 0;
+ int getMDDData = 0;
+ r_Data_Format myDataFmt = (r_Data_Format)(rpcMarray->storageFormat);
+ r_Data_Format myCurrentFmt = (r_Data_Format)(rpcMarray->currentFormat);
+ RMDBGMIDDLE( 2, RMDebug::module_server, "ServerComm", "insertTileSplitted - rpc storage format : " << myDataFmt)
+ RMDBGMIDDLE( 2, RMDebug::module_server, "ServerComm", "insertTileSplitted - rpc transfer format : " << myCurrentFmt)
+ // store in specified storage format; use (new) current format afterwards
+ // Don't repack here because of possible retiling.
+ if(ensureTileFormat(myCurrentFmt, myDataFmt, domain,
+ baseType, dataPtr, dataSize, 0, 1, context->storageFormatParams) != ENSURE_TILE_FORMAT_OK)
+ {
+ //FIXME returnValue
+ returnValue = 1;
+
+ context->release();
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "insertTileSplitted - ensureTileFormat Failed" )
+
+ return returnValue;
+ }
+
+ if (myCurrentFmt != r_Array)
+ getMDDData = dataSize;
+
+ Tile* tile = 0;
+
+ if (r_Tile_Compression::check_data_format(myDataFmt) == r_Tile_Compression::COMPRESSION)
+ {
+ RMInit::dbgOut << "insertTile created new TransTile (" << myDataFmt << "), ";
+ }
+ else
+ {
+ RMInit::logOut << "Warning: Unsupported data format '" << myCurrentFmt << "', will be ignored..." << std::flush;
+ myDataFmt = r_Array;
+ }
+ tile = new Tile( domain, baseType, dataPtr, getMDDData, myDataFmt );
+
+ // for java clients only: check endianness and split tile if necessary
+ if(strcmp(context->clientIdText, ServerComm::HTTPCLIENT) == 0)
+ {
+ // check endianess
+ r_Endian::r_Endianness serverEndian = r_Endian::get_endianness();
+ if(serverEndian != r_Endian::r_Endian_Big)
+ {
+ RMInit::dbgOut << "changing endianness..." << std::flush;
+
+ // we have to swap the endianess
+ char *tpstruct;
+ r_Base_Type *useType;
+ tpstruct = baseType->getTypeStructure();
+ useType = (r_Base_Type*)(r_Type::get_any_type(tpstruct));
+
+ char* tempT = (char*)mymalloc(sizeof(char) * tile->getSize());
+
+ // change the endianness of the entire tile for identical domains for src and dest
+ r_Endian::swap_array(useType, domain, domain, tile->getContents(), tempT);
+ tile->setContents(tempT);
+
+ delete useType;
+ free(tpstruct);
+ }
+
+ // Split the tile!
+ vector< Tile *>* tileSet = tile->splitTile( *tileSize );
+ RMInit::dbgOut << "Now inserting splitted tile...";
+ for( vector<Tile*>::iterator iter = tileSet->begin(); iter != tileSet->end(); iter++ )
+ {
+ (*iter)->setParameters(context->storageFormatParams);
+ if( isPersistent )
+ context->assembleMDD->insertTile( *iter );
+ else
+ context->transferMDD->insertTile( *iter );
+ }
+ // delete the vector again
+ delete tile;
+ delete tileSet;
+ }
+ // for c++ clients: insert tile
+ else
+ {
+ //insert one single tile
+ // later, we should take into consideration the default server tile-size!
+ RMInit::logOut << "Now inserting single tile...";
+ tile->setParameters(context->storageFormatParams);
+ if( isPersistent )
+ context->assembleMDD->insertTile( tile );
+ else
+ context->transferMDD->insertTile( tile );
+ //do not access tile again, because it was already deleted in insertTile
+ }
+ //
+ // done
+ //
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ RMInit::logOut << "Error: tile and MDD base type do not match." << std::endl;
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "insertTileSplitted" )
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::insertTile( unsigned long callingClientId,
+ int isPersistent,
+ RPCMarray* rpcMarray )
+{
+ // no log here, is done in RNP comm.
+
+ unsigned short returnValue = insertTileSplitted(callingClientId, isPersistent, rpcMarray, NULL);
+
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::startInsertPersMDD( unsigned long callingClientId,
+ const char* collName,
+ r_Minterval &domain,
+ unsigned long typeLength,
+ const char* typeName,
+ r_OId& oid )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "startInsertPersMDD" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: startInsertPersMDD type '" << typeName
+ << "', collection '" << collName << "', domain " << domain << ", cell length " << typeLength
+ << ", " << domain.cell_count()*typeLength << " bytes..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer structures
+ context->releaseTransferStructures();
+
+ // Determine the type of the MDD to be inserted.
+ const MDDType* mddType = TypeFactory::mapMDDType( typeName );
+
+ if( mddType )
+ {
+ if( mddType->getSubtype() != MDDType::MDDONLYTYPE )
+ {
+ MDDBaseType* mddBaseType = (MDDBaseType*)mddType;
+
+ try
+ {
+ // store PersMDDColl for insert operation at the end of the transfer
+ context->transferColl = MDDColl::getMDDCollection( collName );
+ if (!context->transferColl->isPersistent())
+ {
+ RMInit::logOut << "Error: inserting into system collection is illegal." << std::endl;
+ context->release(); //!!!
+ throw r_Error(SYSTEM_COLLECTION_NOT_WRITABLE);
+ }
+ }
+ catch (r_Error& obj)
+ {
+ RMInit::logOut << "Error " << obj.get_errorno() << ": " << obj.what() << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch(...)
+ {
+ returnValue = 5;
+ RMInit::logOut << "Error: unspecific exception while opening collection." << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ //
+ // check MDD and collection type for compatibility
+ //
+
+ RMDBGIF(4, RMDebug::module_servercomm, "ServerComm", \
+ char* collTypeStructure = context->transferColl->getCollectionType()->getTypeStructure(); \
+ char* mddTypeStructure = mddType->getTypeStructure(); \
+ RMInit::dbgOut << std::endl << "Collection type structure.: " << collTypeStructure << std::endl \
+ << "MDD type structure........: " << mddTypeStructure << std::endl \
+ << "MDD domain................: " << domain << std::endl; \
+ free( collTypeStructure ); \
+ free( mddTypeStructure ); )
+
+ if( !mddType->compatibleWithDomain( &domain ) )
+ {
+ // free resources
+ context->transferColl->releaseAll();
+ delete context->transferColl;
+ context->transferColl = 0;
+
+ // return error
+ returnValue = 4;
+ RMInit::logOut << "Error: MDD type not compatible wrt. its domain: " << domain << MSG_FAILED << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ if( !context->transferColl->getCollectionType()->compatibleWith( mddType ) )
+ {
+ // free resources
+ context->transferColl->releaseAll();
+ delete context->transferColl;
+ context->transferColl = 0;
+
+ // return error
+ returnValue = 3;
+ RMInit::logOut << "Error: incompatible MDD and collection types." << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ //
+ // Create persistent MDD for further tile insertions
+ //
+
+ StorageLayout ms;
+ ms.setTileSize(StorageLayout::DefaultTileSize);
+ ms.setIndexType(StorageLayout::DefaultIndexType);
+ ms.setTilingScheme(StorageLayout::DefaultTilingScheme);
+ if (domain.dimension() == StorageLayout::DefaultTileConfiguration.dimension())
+ ms.setTileConfiguration(StorageLayout::DefaultTileConfiguration);
+ try
+ {
+ context->assembleMDD = new MDDObj( mddBaseType, domain, OId( oid.get_local_oid() ), ms );
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error: while creating persistent tile: " << err.get_errorno() << ": " << err.what() << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch(...)
+ {
+ returnValue = 6;
+ RMInit::logOut << "Error: unspecific exception during creation of persistent object." << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: MDD type '" << typeName << "' has no base type..." << std::endl;
+ returnValue = 2;
+ }
+ }
+ else
+ {
+ RMInit::logOut << "Error: MDD type name '" << typeName << "' not found." << std::endl;
+ returnValue = 2;
+ }
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "startInsertPersMDD" )
+ return returnValue;
+}
+
+
+/*************************************************************************
+ * Method name...: executeQuery( unsigned long callingClientId,
+ * const char* query
+ * ExecuteQueryRes &returnStructure )
+ ************************************************************************/
+unsigned short
+ServerComm::executeQuery( unsigned long callingClientId,
+ const char* query,
+ ExecuteQueryRes &returnStructure )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "executeQuery" )
+ unsigned short returnValue=0;
+
+ // set all to zero as default. They are not really applicable here.
+ returnStructure.errorNo = 0;
+ returnStructure.lineNo = 0;
+ returnStructure.columnNo = 0;
+
+ RMInit::logOut << "Request: executeQquery '" << query << "'..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+#ifdef RMANBENCHMARK
+ RMTimer* queryOptimizationTimer = 0;
+
+ Tile::relTimer.start();
+ Tile::relTimer.pause();
+ Tile::opTimer.start();
+ Tile::opTimer.pause();
+ ZLibCompression::decompTimer.start();
+ ZLibCompression::decompTimer.pause();
+ ZLibCompression::compTimer.start();
+ ZLibCompression::compTimer.pause();
+
+ if( RManBenchmark > 0 )
+ RMInit::bmOut << "Query: " << query << std::endl;
+#endif
+
+#ifdef PURIFY
+ purify_printf( "%s\n", query );
+#endif
+
+ // delete old transfer collection/iterator
+ context->releaseTransferStructures();
+
+ //
+ // execute the query
+ //
+
+#ifdef RMANBENCHMARK
+ if( RManBenchmark > 0 )
+ queryOptimizationTimer = new RMTimer("ServerComm", "optimization time");
+#endif
+
+
+
+ QueryTree* qtree = new QueryTree(); // create a query tree object...
+ parseQueryTree = qtree; // ...and assign it to the global parse query tree pointer;
+
+ currentClientTblElt = context; // assign current client table element (temporary)
+
+ int ppRet = 0;
+ int parserRet = 0;
+
+ udfEnabled = 0; // Forced for RNP, but only temporary...
+ if(udfEnabled)
+ {
+ //
+ // preprocess
+ //
+ RMInit::logOut << "preprocessing..." << std::flush;
+ ppInBuf = (char *)query;
+ ppreset();
+ ppRet = ppparse();
+
+ RMInit::dbgOut << "new query: '" << ppOutBuf << "'..." << std::flush;
+
+ // initialize the input string parameters
+ beginParseString = ppOutBuf;
+ iterParseString = ppOutBuf;
+ }
+ else
+ {
+ beginParseString = (char*)query;
+ iterParseString = (char*)query;
+ }
+
+ yyreset();
+
+ RMInit::logOut << "parsing..." << std::flush;
+
+ parserRet=yyparse(0);
+ if((ppRet == 0) && (parserRet == 0))
+ {
+ try
+ {
+ RMDBGIF(1, RMDebug::module_servercomm, "ServerComm::executeQuery", \
+ qtree->printTree( 2, RMInit::logOut);
+ );
+
+ RMInit::logOut << "checking semantics..." << std::flush;
+ qtree->checkSemantics();
+
+ unsigned int localOptimizationLevel = globalOptimizationLevel < qtree->getOptimizationLevel() ?
+ globalOptimizationLevel : qtree->getOptimizationLevel();
+
+ RMInit::logOut << "optimizing (level " << localOptimizationLevel << ")..." << std::flush;
+ qtree->optimize( localOptimizationLevel );
+
+ RMDBGIF(1, RMDebug::module_servercomm, "ServerComm::executeQuery", \
+ qtree->printTree( 2, RMInit::logOut );
+ );
+
+#ifdef RMANBENCHMARK
+ if( queryOptimizationTimer )
+ {
+ delete queryOptimizationTimer;
+ queryOptimizationTimer = 0;
+ }
+
+ if( RManBenchmark > 0 )
+ context->evaluationTimer = new RMTimer("ServerComm", "evaluation time ");
+#endif
+ qtree->printTree( 2, std::cout );
+ //qtree->checkSemantics();
+ //qtree->printTree( 2, std::cout );
+ RMInit::logOut << "evaluating..." << std::flush;
+ context->transferData = qtree->evaluateRetrieval();
+ }
+ catch( ParseInfo& info )
+ {
+ // this is the old error handling which has been here for quite some time
+ // dealing with errors when release data
+ context->releaseTransferStructures();
+
+ returnValue = 5; // execution error
+
+ // set the error values of the return structure
+ returnStructure.errorNo = info.getErrorNo();
+ returnStructure.lineNo = info.getLineNo();
+ returnStructure.columnNo = info.getColumnNo();
+ returnStructure.token = strdup( info.getToken().c_str() );
+
+ RMInit::logOut << "Error: cannot parse query (1)." << std::endl;
+ info.printStatus( RMInit::logOut );
+ }
+ catch( r_Ebase_dbms& myErr )
+ {
+ RMInit::logOut << "Error: base DBMS exception: " << myErr.what() << std::endl;
+
+ // release data
+ context->releaseTransferStructures();
+ context->release(); //!!!
+
+ //delete parser data
+ parseQueryTree = 0;
+ currentClientTblElt = 0;
+ delete qtree;
+
+ returnValue = 42; // general serialisable exception
+
+ throw;
+ }
+ catch( r_Error& myErr )
+ {
+ RMInit::logOut << "Error: " << myErr.get_errorno() << " " << myErr.what() << std::endl;
+
+ // release data
+ context->releaseTransferStructures();
+ context->release(); //!!!
+
+ //delete parser data
+ parseQueryTree = 0;
+ currentClientTblElt = 0;
+ delete qtree;
+
+ returnValue = 5;
+
+ throw;
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+
+ // release data
+ context->releaseTransferStructures();
+ context->release(); //!!!
+
+ //delete parser data
+ parseQueryTree = 0;
+ currentClientTblElt = 0;
+ delete qtree;
+
+ throw;
+ }
+ catch(...)
+ {
+ RMInit::logOut << "Error: unspecific exception." << std::endl;
+
+ context->releaseTransferStructures();
+ context->release(); //!!!
+
+ //delete parser data
+ parseQueryTree = 0;
+ currentClientTblElt = 0;
+ delete qtree;
+
+ returnValue = 5;
+
+ throw;
+ }
+
+ if( returnValue == 0 )
+ {
+ if( context->transferData != 0 )
+ {
+ // create the transfer iterator
+ context->transferDataIter = new vector<QtData*>::iterator;
+ *(context->transferDataIter) = context->transferData->begin();
+
+ //
+ // set typeName and typeStructure
+ //
+
+ // The type of first result object is used to determine the type of the result
+ // collection.
+ if( *(context->transferDataIter) != context->transferData->end() )
+ {
+ QtData* firstElement = (**(context->transferDataIter));
+
+ if( firstElement->getDataType() == QT_MDD )
+ {
+ QtMDD* mddObj = (QtMDD*)firstElement;
+ const BaseType* baseType = mddObj->getMDDObject()->getCellType();
+ r_Minterval domain = mddObj->getLoadDomain();
+
+ MDDType* mddType = new MDDDomainType( "tmp", (BaseType*)baseType, domain );
+ SetType* setType = new SetType( "tmp", mddType );
+
+ returnStructure.typeName = strdup( setType->getTypeName() );
+ returnStructure.typeStructure = setType->getTypeStructure(); // no copy
+
+ TypeFactory::addTempType( setType );
+ TypeFactory::addTempType( mddType );
+ }
+ else
+ {
+ returnValue = 1; // evaluation ok, non-MDD elements
+
+ returnStructure.typeName = strdup("");
+
+ // hack set type
+ char* elementType = firstElement->getTypeStructure();
+ returnStructure.typeStructure = (char*)mymalloc( strlen(elementType) + 6 );
+ sprintf( returnStructure.typeStructure, "set<%s>", elementType );
+ free( elementType );
+ }
+
+ strcpy(globalHTTPSetTypeStructure, returnStructure.typeStructure);
+
+ RMInit::logOut << MSG_OK << ", result type '" << returnStructure.typeStructure << "', " << context->transferData->size() << " element(s)." << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << MSG_OK << ", result is empty." << std::endl;
+ returnValue = 2; // evaluation ok, no elements
+
+ returnStructure.typeName = strdup("");
+ returnStructure.typeStructure = strdup("");
+ }
+ }
+ else
+ {
+ RMInit::logOut << MSG_OK << ", result is empty." << std::endl;
+ returnValue = 2; // evaluation ok, no elements
+ }
+ }
+ }
+ else
+ {
+ if(ppRet)
+ {
+ RMInit::logOut << MSG_OK << ",result is empty." << std::endl;
+ returnValue = 2; // evaluation ok, no elements
+ }
+ else // parse error
+ {
+ if( parseError )
+ {
+ returnStructure.errorNo = parseError->getErrorNo();
+ returnStructure.lineNo = parseError->getLineNo();
+ returnStructure.columnNo = parseError->getColumnNo();
+ returnStructure.token = strdup( parseError->getToken().c_str() );
+
+ delete parseError;
+ parseError = 0;
+ }
+ else
+ {
+ returnStructure.errorNo = 309;
+ RMInit::logOut << "Internal Error: Unknown parse error.";
+ }
+
+ yyreset(); // reset the input buffer of the scanner
+
+ RMInit::logOut << "Error: cannot parse query (2)." << std::endl;
+ returnValue = 4;
+ }
+ }
+
+ parseQueryTree = 0;
+ currentClientTblElt = 0;
+ delete qtree;
+
+ //
+ // done
+ //
+
+#ifdef RMANBENCHMARK
+ if( queryOptimizationTimer )
+ delete queryOptimizationTimer;
+
+ // Evaluation timer can not be stopped because some time spent in the transfer
+ // module is added to this phase.
+ if( context->evaluationTimer )
+ context->evaluationTimer->pause();
+
+ if( RManBenchmark > 0 )
+ context->transferTimer = new RMTimer("ServerComm", "transfer time ");
+#endif
+
+ // In case of an error or the result set is empty, no endTransfer()
+ // is called by the client.
+ // Therefore, some things have to be release here.
+ if( returnValue >= 2)
+ {
+#ifdef RMANBENCHMARK
+ Tile::o2Timer.stop();
+ Tile::opTimer.stop();
+ Tile::relTimer.stop();
+ Tile::opTimer.stop();
+ ZLibCompression::decompTimer.stop();
+ ZLibCompression::compTimer.stop();
+ if( context->evaluationTimer )
+ delete context->evaluationTimer;
+ context->evaluationTimer = 0;
+
+ if( context->transferTimer )
+ delete context->transferTimer;
+ context->transferTimer = 0;
+
+ RMTimer* releaseTimer = 0;
+
+ if( RManBenchmark > 0 )
+ releaseTimer = new RMTimer("ServerComm", "release time ");
+#endif
+
+ // release transfer collection/iterator
+ context->releaseTransferStructures();
+
+#ifdef RMANBENCHMARK
+ if( releaseTimer )
+ delete releaseTimer;
+#endif
+ }
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 3;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "executeQuery" )
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::initExecuteUpdate( unsigned long callingClientId )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "initExecuteUpdate" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: initExecuteUpdate..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer structures
+ context->releaseTransferStructures();
+
+ MDDType* mddType = new MDDType( "tmp" );
+ SetType* setType = new SetType( "tmp", mddType );
+
+ TypeFactory::addTempType( mddType );
+ TypeFactory::addTempType( setType );
+
+ // create a transient collection for storing MDD constants
+ context->transferColl = new MDDColl( setType );
+
+ context->release();
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "initExecuteUpdate" )
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::startInsertTransMDD( unsigned long callingClientId,
+ r_Minterval &domain, unsigned long typeLength,
+ const char* typeName )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "startInsertTransMDD" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: startInsertTransMDD type '"
+ << typeName <<"', domain " << domain << ", cell length " << typeLength << ", "
+ << domain.cell_count()*typeLength << " bytes..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+
+ RMDBGMIDDLE(1, RMDebug::module_servercomm, "ServerComm", "startInsertTransMDD(...) TRANSFER " << context->transferFormat << ", EXACT " << (bool)context->exactFormat);
+
+ // Determine the type of the MDD to be inserted.
+ const MDDType* mddType = TypeFactory::mapMDDType( typeName );
+
+ if( mddType )
+ {
+ if( mddType->getSubtype() != MDDType::MDDONLYTYPE )
+ {
+ MDDBaseType* mddBaseType = (MDDBaseType*)mddType;
+
+ if( !mddType->compatibleWithDomain( &domain ) )
+ {
+ // return error
+ returnValue = 3;
+ RMInit::logOut << "Error: MDD type incompatible wrt. domain: " << domain << std::endl;
+
+ context->release();
+
+ return returnValue;
+ }
+
+ // create for further insertions
+ context->transferMDD = new MDDObj( mddBaseType, domain );
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: MDD type has no base type." << std::endl;
+ returnValue = 2;
+ }
+ }
+ else
+ {
+ RMInit::logOut << "Error: MDD type not found." << std::endl;
+ returnValue = 2;
+ }
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "startInsertTransMDD" )
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::endInsertMDD( unsigned long callingClientId,
+ int isPersistent )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "endInsertMDD" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: endInsertMDD..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ if( isPersistent )
+ {
+ // we are finished with this MDD Object, so insert it into the collection
+ context->transferColl->insert( context->assembleMDD );
+
+ // reset assembleMDD, because otherwise it is tried to be freed
+ context->assembleMDD = 0;
+
+ // free transfer structure
+ context->releaseTransferStructures();
+
+ // old: context->transferColl->releaseAll(); caused a crash because releaseAll() is not idempotent
+ }
+ else
+ {
+ // we are finished with this MDD Object, so insert it into the collection
+ context->transferColl->insert( context->transferMDD );
+
+ // reset transferMDD
+ context->transferMDD = 0;
+
+ // Do not delete the transfer structure because the transient set
+ // of MDD objects will be used as constants for executeUpdate().
+ }
+
+ RMInit::logOut << MSG_OK << std::endl;
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "endInsertMDD" )
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::executeUpdate( unsigned long callingClientId,
+ const char* query,
+ ExecuteUpdateRes &returnStructure )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "executeUpdate" )
+
+ RMInit::logOut << "Request: executeUpdate query '" << query << "'..." << std::flush;
+
+#ifdef RMANBENCHMARK
+ RMTimer* queryOptimizationTimer = 0;
+ Tile::relTimer.start();
+ Tile::relTimer.pause();
+ Tile::opTimer.start();
+ Tile::opTimer.pause();
+ ZLibCompression::decompTimer.start();
+ ZLibCompression::decompTimer.pause();
+ ZLibCompression::compTimer.start();
+ ZLibCompression::compTimer.pause();
+
+ if( RManBenchmark > 0 )
+ RMInit::bmOut << "Query (update): " << query << std::endl;
+#endif
+
+ unsigned short returnValue = 0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+#ifdef PURIFY
+ purify_printf( "%s\n", query );
+#endif
+
+ //
+ // execute the query
+ //
+
+#ifdef RMANBENCHMARK
+ if( RManBenchmark > 0 )
+ queryOptimizationTimer = new RMTimer("ServerComm", "optimization time");
+#endif
+
+ QueryTree* qtree = new QueryTree(); // create a query tree object...
+ parseQueryTree = qtree; // ...and assign it to the global parse query tree pointer;
+
+ mddConstants = context->transferColl; // assign the mdd constants collection to the global pointer (temporary)
+ currentClientTblElt = context; // assign current client table element (temporary)
+
+ int ppRet = 0;
+ udfEnabled = false; // forced for RNP tests
+ if(udfEnabled)
+ {
+ //
+ // preprocess
+ //
+ RMInit::logOut << "preprocessing..." << std::flush;
+ ppInBuf = (char *)query;
+ ppreset();
+ ppRet = ppparse();
+
+ if(ppOutBuf)
+ RMInit::dbgOut << "new query: '" << ppOutBuf << "'" << std::endl;
+ else
+ RMInit::dbgOut << "new query: empty." << std::endl;
+
+ // initialize the input string parameters
+ beginParseString = ppOutBuf;
+ iterParseString = ppOutBuf;
+ }
+ else
+ {
+ beginParseString = (char*)query;
+ iterParseString = (char*)query;
+ }
+
+ yyreset();
+
+ RMInit::logOut << "parsing..." << std::flush;
+
+ if( ppRet == 0 && yyparse(0) == 0 )
+ {
+ try
+ {
+ RMDBGIF(1, RMDebug::module_servercomm, "ServerComm::executeUpdate", \
+ qtree->printTree( 2, RMInit::logOut );
+ );
+
+ RMInit::logOut << "checking semantics..." << std::flush;
+
+ qtree->checkSemantics();
+
+ // coman: Why is disabled optimization for update query?
+ // unsigned int localOptimizationLevel = globalOptimizationLevel < qtree->getOptimizationLevel() ?
+ // globalOptimizationLevel : qtree->getOptimizationLevel();
+
+ unsigned int localOptimizationLevel = 0;
+
+ RMInit::logOut << "optimizing (level " << localOptimizationLevel << ")..." << std::flush;
+ qtree->optimize( localOptimizationLevel );
+
+ RMDBGIF(1, RMDebug::module_servercomm, "ServerComm::executeUpdate", \
+ qtree->printTree( 2, RMInit::logOut );
+ );
+
+#ifdef RMANBENCHMARK
+ if( queryOptimizationTimer )
+ {
+ delete queryOptimizationTimer;
+ queryOptimizationTimer = 0;
+ }
+
+ if( RManBenchmark > 0 )
+ context->evaluationTimer = new RMTimer("ServerComm", "evaluation time ");
+#endif
+
+ RMInit::logOut << "evaluating..." << std::flush;
+ qtree->evaluateUpdate();
+
+ // release data
+ context->releaseTransferStructures();
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ catch( ParseInfo& info )
+ {
+ // release data
+ context->releaseTransferStructures();
+
+ returnValue = 3; // evaluation error
+
+ // set the error values of the return structure
+ returnStructure.errorNo = info.getErrorNo();
+ returnStructure.lineNo = info.getLineNo();
+ returnStructure.columnNo = info.getColumnNo();
+ returnStructure.token = strdup( info.getToken().c_str() );
+
+ RMInit::logOut << "Error: cannot parse query (1)." << std::endl;
+ info.printStatus( RMInit::logOut );
+ }
+ catch(r_Error &err)
+ {
+ context->releaseTransferStructures();
+ context->release();
+ RMInit::logOut << "Error: " << err.get_errorno() << " " << err.what() << std::endl;
+ throw;
+ }
+ }
+ else
+ {
+ if(ppRet)
+ {
+ RMInit::logOut << MSG_OK << std::endl;
+ returnValue = 0;
+ }
+ else // parse error
+ {
+ if( parseError )
+ {
+ returnStructure.errorNo = parseError->getErrorNo();
+ returnStructure.lineNo = parseError->getLineNo();
+ returnStructure.columnNo = parseError->getColumnNo();
+ returnStructure.token = strdup( parseError->getToken().c_str() );
+
+ delete parseError;
+
+ RMInit::logOut << "Error: cannot parse query (2)." << std::endl;
+ parseError = 0;
+ }
+ else
+ {
+ returnStructure.errorNo = 309;
+ RMInit::logOut << "Error: unspecific internal parser error." << endl;
+ }
+
+ yyreset(); // reset the input buffer of the scanner
+
+ returnValue = 2;
+ }
+ }
+
+ parseQueryTree = 0;
+ mddConstants = 0;
+ currentClientTblElt = 0;
+ delete qtree;
+
+ // delete set of mdd constants
+ context->releaseTransferStructures();
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+
+#ifdef RMANBENCHMARK
+ if( queryOptimizationTimer )
+ delete queryOptimizationTimer;
+
+ // stop evaluation timer
+ if( context->evaluationTimer )
+ {
+ delete context->evaluationTimer;
+ context->evaluationTimer = 0;
+ }
+
+ Tile::opTimer.stop();
+ Tile::relTimer.stop();
+ ZLibCompression::decompTimer.stop();
+ ZLibCompression::compTimer.stop();
+#endif
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "executeUpdate" )
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getCollByName( unsigned long callingClientId,
+ const char* collName,
+ char* &typeName,
+ char* &typeStructure,
+ r_OId &oid )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "ServerComm::getCollByName" )
+
+ RMInit::logOut << "Request: getCollByName '" << collName << "'..." << std::flush;
+
+ unsigned short returnValue=0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ //
+ // create the actual transfer collenction
+ //
+
+ // delete old transfer collection/iterator
+ context->releaseTransferStructures();
+
+ // create the transfer collection
+ try
+ {
+ context->transferColl = MDDColl::getMDDCollection( collName );
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "retrieved mdd collection" )
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error " << err.get_errorno() << " " << err.what() << std::endl;
+ context->release(); //!!!
+ throw;
+ }
+ catch(...)
+ {
+ returnValue = 2; // collection name invalid
+ RMInit::logOut << "Error: unspecific exception." << std::endl;
+ }
+
+ if( returnValue == 0 )
+ {
+ // create the transfer iterator
+ context->transferCollIter = context->transferColl->createIterator();
+ context->transferCollIter->reset();
+
+ // set typeName and typeStructure
+ CollectionType* collectionType = (CollectionType*) context->transferColl->getCollectionType();
+
+ if( collectionType )
+ {
+ typeName = strdup( collectionType->getTypeName() );
+ typeStructure = collectionType->getTypeStructure(); // no copy !!!
+
+ // set oid in case of a persistent collection
+ if( context->transferColl->isPersistent() )
+ {
+ EOId eOId;
+ if (context->transferColl->isPersistent())
+ {
+ if (context->transferColl->getEOId(eOId) == true)
+ oid = r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() );
+ }
+ }
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Warning: cannot obtain collection type information." << endl;
+ typeName = strdup("");
+ typeStructure = strdup("");
+ }
+
+ if( !context->transferCollIter->notDone() )
+ {
+ RMInit::logOut << MSG_OK << ", result empty.";
+ returnValue = 1;
+
+ // delete transfer collection/iterator
+ context->releaseTransferStructures();
+ }
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 3;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", " ServerComm::getCollByName" )
+
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getCollByOId( unsigned long callingClientId,
+ r_OId &oid,
+ char* &typeName,
+ char* &typeStructure,
+ char* &collName )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", " ServerComm::getCollByOId" )
+
+ RMInit::logOut << "Request: getCollByOId " << oid << "..." << std::flush;
+
+ unsigned short returnValue=0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer collection/iterator
+ context->releaseTransferStructures();
+
+ // check type and existence of oid
+ OId oidIf( oid.get_local_oid() );
+ OId::OIdType objType = oidIf.getType();
+
+ if( objType == OId::MDDCOLLOID )
+ {
+ //
+ // get collection
+ //
+
+ try
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm",
+ std::endl << " execute new PersMDDColl(" << oid << ")" )
+ context->transferColl = MDDColl::getMDDCollection(oidIf);
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", " ok" )
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ throw;
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error " << err.get_errorno() << " " << err.what() << std::endl;
+ throw;
+ }
+ catch(...) // not found (?)
+ {
+ returnValue = 2;
+ RMInit::logOut << "Error: unspecific exception." << endl;
+ }
+
+ //
+ // create the actual transfer collenction
+ //
+
+ if( returnValue == 0 )
+ {
+ // get collection name
+ collName = strdup(context->transferColl->getName());
+
+ // create the transfer iterator
+ context->transferCollIter = context->transferColl->createIterator();
+ context->transferCollIter->reset();
+
+ // set typeName and typeStructure
+ CollectionType* collectionType = (CollectionType*) context->transferColl->getCollectionType();
+
+ if( collectionType )
+ {
+ typeName = strdup( collectionType->getTypeName() );
+ typeStructure = collectionType->getTypeStructure(); // no copy !!!
+
+ // set oid in case of a persistent collection
+ if( context->transferColl->isPersistent() )
+ {
+ EOId eOId;
+
+ if (context->transferColl->getEOId(eOId) == true)
+ oid = r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() );
+ }
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << MSG_OK << ", but warning: cannot obtain type information." << endl;
+ typeName = strdup("");
+ typeStructure = strdup("");
+ }
+
+ if( !context->transferCollIter->notDone() )
+ {
+ RMInit::logOut << MSG_OK << ", result empty." << endl;
+ returnValue = 1;
+
+ // delete transfer collection/iterator
+ context->releaseTransferStructures();
+ }
+ }
+
+ }
+ else
+ {
+ returnValue = 2; // oid does not belong to a collection object
+ RMInit::logOut << "Error: oid does not belong to a collection object." << std::endl;
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 3;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", " ServerComm::getCollByOId" )
+
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getCollOIdsByName( unsigned long callingClientId,
+ const char* collName,
+ char* &typeName,
+ char* &typeStructure,
+ r_OId &oid,
+ RPCOIdEntry* &oidTable,
+ unsigned int &oidTableSize )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getCollOIdsByName" )
+
+ RMInit::logOut << "Request: getCollOIdsByName '" << collName << "'..." << std::flush;
+
+ unsigned short returnValue=0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ //
+ // get collection
+ //
+
+ MDDColl* coll = 0;
+ MDDColl* almost = 0;
+
+ try
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "retrieving collection " << collName)
+ almost = MDDColl::getMDDCollection( collName );
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "retrieved collection " << collName)
+ if (!almost->isPersistent())
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "retrieved system collection")
+ RMInit::logOut << "Error: trying to get oid of system collection: " << collName << std::endl;
+ throw r_Error(SYSTEM_COLLECTION_HAS_NO_OID);
+ }
+ else
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "retrieved persistent collection")
+ coll = (MDDColl*)almost;
+ }
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ throw;
+ }
+ catch (r_Error& err)
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "caught exception")
+ RMInit::logOut << "Error " << err.get_errorno() << ": " << err.what() << std::endl;
+ returnValue = 2; // collection name invalid
+ }
+ catch(...)
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "caught exception")
+ returnValue = 2; // collection name invalid
+ RMInit::logOut << "Error: unspecific exception." << std::endl;
+ }
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "after exception catching")
+
+ if( returnValue == 0 )
+ {
+ // set typeName and typeStructure
+ CollectionType* collectionType = (CollectionType*) coll->getCollectionType();
+
+ if( collectionType )
+ {
+ typeName = strdup( collectionType->getTypeName() );
+ typeStructure = collectionType->getTypeStructure(); // no copy !!!
+
+ // set oid
+ EOId eOId;
+
+ if (coll->getEOId(eOId) == true)
+ oid = r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() );
+ }
+ else
+ {
+ RMInit::logOut << "Warning: no type information available..." << std::flush;
+ typeName = strdup("");
+ typeStructure = strdup("");
+ }
+
+ if( coll->getCardinality() )
+ {
+ // create iterator
+ MDDCollIter* collIter = coll->createIterator();
+ int i;
+
+ oidTableSize = coll->getCardinality();
+ oidTable = (RPCOIdEntry*) mymalloc( sizeof(RPCOIdEntry) * oidTableSize );
+
+ TALK( oidTableSize << " elements..." );
+
+ for( collIter->reset(), i=0; collIter->notDone(); collIter->advance(), i++ )
+ {
+ MDDObj* mddObj = collIter->getElement();
+
+ if( mddObj->isPersistent() )
+ {
+ EOId eOId;
+
+ if( ((MDDObj*)mddObj)->getEOId( &eOId ) == 0 )
+ oidTable[i].oid = strdup( r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() ).get_string_representation() );
+ else
+ oidTable[i].oid = strdup("");
+ mddObj = 0;
+ }
+ else
+ oidTable[i].oid = strdup("");
+ }
+
+ delete collIter;
+
+ RMInit::logOut << MSG_OK << ", " << coll->getCardinality() << " result(s)." << endl;
+ }
+ else
+ {
+ RMInit::logOut << MSG_OK << ", result empty." << endl;
+ returnValue = 1;
+ }
+
+ delete coll;
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 3;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getCollOIdsByName " << returnValue)
+
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::getCollOIdsByOId( unsigned long callingClientId,
+ r_OId &oid,
+ char* &typeName,
+ char* &typeStructure,
+ RPCOIdEntry* &oidTable,
+ unsigned int &oidTableSize,
+ char* &collName )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getCollOIdsByOId" )
+
+ RMInit::logOut << "Request: getCollOIdsByOId " << oid << "..." << std::flush;
+
+ unsigned short returnValue=0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // check type and existence of oid
+ OId oidIf( oid.get_local_oid() );
+ OId::OIdType objType = oidIf.getType();
+
+ if( objType == OId::MDDCOLLOID )
+ {
+ //
+ // get collection
+ //
+
+ MDDColl* coll = 0;
+
+ try
+ {
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "get mdd coll by oid " << oidIf)
+ coll = MDDColl::getMDDCollection(oidIf);
+ RMDBGMIDDLE( 4, RMDebug::module_server, "ServerComm", "retrieved mdd coll" )
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ throw;
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error " << err.get_errorno() << ": " << err.what() << std::endl;
+ returnValue = 2; // collection name invalid
+ if (err.get_kind() != r_Error::r_Error_RefNull)
+ throw;
+ }
+ catch(...)
+ {
+ returnValue = 2; // collection name invalid
+ RMInit::logOut << "Error: unknown collection name." << std::endl;
+ }
+
+ if( returnValue == 0 )
+ {
+ // get collection name
+ collName = strdup(coll->getName());
+
+ // set typeName and typeStructure
+ CollectionType* collectionType = (CollectionType*) coll->getCollectionType();
+
+ if( collectionType )
+ {
+ typeName = strdup( collectionType->getTypeName() );
+ typeStructure = collectionType->getTypeStructure(); // no copy !!!
+
+ // set oid
+ EOId eOId;
+
+ if (coll->getEOId(eOId) == true)
+ oid = r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() );
+ }
+ else
+ {
+ RMInit::logOut << "Warning: no type information available..." << std::flush;
+ typeName = strdup("");
+ typeStructure = strdup("");
+ }
+
+ if( coll->getCardinality() )
+ {
+ // create iterator
+ MDDCollIter* collIter = coll->createIterator();
+ int i;
+
+ oidTableSize = coll->getCardinality();
+ oidTable = (RPCOIdEntry*) mymalloc( sizeof(RPCOIdEntry) * oidTableSize );
+
+ TALK( oidTableSize << " elements..." );
+
+ for( collIter->reset(), i=0; collIter->notDone(); collIter->advance(), i++ )
+ {
+ MDDObj* mddObj = collIter->getElement();
+
+ if( mddObj->isPersistent() )
+ {
+ EOId eOId;
+
+ if( ((MDDObj*)mddObj)->getEOId( &eOId ) == 0 )
+ oidTable[i].oid = strdup( r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() ).get_string_representation() );
+ else
+ oidTable[i].oid = strdup("");
+ }
+ else
+ oidTable[i].oid = strdup("");
+ }
+
+ delete collIter;
+ //coll->releaseAll();
+
+ RMInit::logOut << MSG_OK << ", " << coll->getCardinality() << " result(s)." << endl;
+ }
+ else
+ {
+ RMInit::logOut << MSG_OK << ", result empty." << endl;
+ returnValue = 1;
+ }
+
+ delete coll;
+ }
+ }
+ else
+ {
+ returnValue = 2; // oid does not belong to a collection object
+ RMInit::logOut << "Error: not a collection oid: " << oid << std::endl;
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 3;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getCollOIdsByOId " << returnValue)
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getNextMDD( unsigned long callingClientId,
+ r_Minterval &mddDomain,
+ char* &typeName,
+ char* &typeStructure,
+ r_OId &oid,
+ unsigned short &currentFormat )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getNextMDD" )
+
+ RMInit::logOut << "Request: getNextMDD..." << std::flush;
+
+ unsigned short returnValue = 0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ try
+ {
+ if( context->transferData && context->transferDataIter && *(context->transferDataIter) != context->transferData->end() )
+ {
+ //
+ // convert the mdd to transfer to rpc data structures
+ //
+
+ // get the MDD object to be transfered
+ QtMDD* mddData = (QtMDD*) **(context->transferDataIter);
+ MDDObj* mddObj = mddData->getMDDObject();
+
+ // initialize mddDomain to give it back
+ mddDomain = mddData->getLoadDomain();
+
+ TALK( "domain " << mddDomain );
+
+ //
+ // initialize tiles to transfer
+ //
+
+#ifdef RMANBENCHMARK
+ // pause transfer timer and resume evaluation timer
+ if( context->transferTimer )
+ context->transferTimer->pause();
+ if( context->evaluationTimer )
+ context->evaluationTimer->resume();
+#endif
+
+ if( mddObj->getCurrentDomain() == mddData->getLoadDomain() )
+ context->transTiles = mddObj->getTiles();
+ else
+ {
+ // If the load domain is different from the current domain, we have
+ // a persitent MDD object. The border tiles have to be cut (and
+ // therefore copied) in order to be ready for transfering them.
+ // These temporary border tiles are added to the deletableTiles list
+ // which is deleted at the end.
+
+ context->transTiles = mddObj->intersect( mddData->getLoadDomain() );
+
+ // iterate over the tiles
+ for( vector<Tile*>::iterator iter = context->transTiles->begin(); iter != context->transTiles->end(); iter++ )
+ {
+ // get relevant area of source tile
+ r_Minterval sourceTileDomain( mddData->getLoadDomain().create_intersection( (*iter)->getDomain() ) );
+
+ if( sourceTileDomain != (*iter)->getDomain() )
+ {
+ // create a new transient tile and copy the transient data
+ Tile* newTransTile = new Tile( sourceTileDomain, mddObj->getCellType() );
+ newTransTile->copyTile( sourceTileDomain, *iter, sourceTileDomain );
+
+ // replace the tile in the list with the new one
+ *iter = newTransTile;
+
+ // add the new tile to deleteableTiles
+ if( !(context->deletableTiles) )
+ context->deletableTiles = new vector<Tile*>();
+ context->deletableTiles->push_back( newTransTile );
+ }
+ }
+ }
+
+#ifdef RMANBENCHMARK
+ // In order to be sure that reading tiles from disk is done
+ // in the evaluation phase, the contents pointers of each tile
+ // are got.
+ char* benchmarkPointer;
+
+ for( vector<Tile*>::iterator benchmarkIter = context->transTiles->begin();
+ benchmarkIter != context->transTiles->end(); benchmarkIter++ )
+ benchmarkPointer = (*benchmarkIter)->getContents();
+
+ // pause evaluation timer and resume transfer timer
+ if( context->evaluationTimer )
+ context->evaluationTimer->pause();
+ if( context->transferTimer )
+ context->transferTimer->resume();
+#endif
+
+ // initialize tile iterator
+ context->tileIter = new vector<Tile*>::iterator;
+ *(context->tileIter) = context->transTiles->begin();
+
+ const BaseType* baseType = mddObj->getCellType();
+
+ TALK( "cell length " << baseType->getSize() );
+
+ //
+ // set typeName and typeStructure
+ //
+ // old: typeName = strdup( mddObj->getCellTypeName() ); not known for the moment being
+ typeName = strdup("");
+
+ // create a temporary mdd type for the moment being
+ r_Minterval typeDomain( mddData->getLoadDomain() );
+ MDDType* mddType = new MDDDomainType( "tmp", (BaseType*)baseType, typeDomain );
+ TypeFactory::addTempType( mddType );
+
+ typeStructure = mddType->getTypeStructure(); // no copy !!!
+
+ // I'm not sure about this code...
+#if 0
+ // determine data format from the 1st tile
+ if( context->transTiles->size() && (*(context->transTiles))[0]->getDataFormat() == r_TIFF )
+ currentFormat = r_TIFF;
+ else
+ currentFormat = r_Array;
+#else
+ if (context->transTiles->size())
+ currentFormat = (*(context->transTiles))[0]->getDataFormat();
+ else
+ currentFormat = r_Array;
+#endif
+
+ // set oid in case of persistent MDD objects
+ if( mddObj->isPersistent() )
+ {
+ EOId eOId;
+
+ if( ((MDDObj*)mddObj)->getEOId( &eOId ) == 0 )
+ oid = r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() );
+ }
+
+ //
+ //
+ //
+
+ if( context->transTiles->size() > 0 )
+ {
+ RMInit::logOut << MSG_OK << ", " << context->transTiles->size() << " more tile(s)" << endl;
+ }
+ else // context->transTiles->size() == 0
+ {
+ returnValue = 2;
+ RMInit::logOut << "Error: no tiles in MDD object." << std::endl;
+ }
+
+ context->totalTransferedSize = 0;
+ context->totalRawSize = 0;
+ }
+ else
+ {
+ if( context->transferDataIter && *(context->transferDataIter) == context->transferData->end() )
+ {
+ returnValue = 1; // nothing left in the collection
+ RMInit::logOut << MSG_OK << ", no more tiles." << std::endl;
+ context->releaseTransferStructures();
+ }
+ else
+ {
+ returnValue = 2; // no actual transfer collection
+ RMInit::logOut << "Error: no transfer collection. " << std::endl;
+ }
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ catch( r_Ebase_dbms& myErr )
+ {
+ RMInit::logOut << "Error: base DBMS exception (kind " << myErr.get_kind() << ", errno " << myErr.get_errorno() << ") " << myErr.what() << std::endl;
+ returnValue = 42;
+ throw;
+ }
+ catch( r_Error& myErr )
+ {
+ RMInit::logOut << "Error: (kind " << myErr.get_kind() << ", errno " << myErr.get_errorno() << ") " << myErr.what() << std::endl;
+ throw;
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ throw;
+ }
+ catch(...)
+ {
+ RMInit::logOut << "Error: unspecified exception." << std::endl;
+ }
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 2;
+ }
+
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getNextMDD" )
+
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::getNextElement( unsigned long callingClientId,
+ char* &buffer,
+ unsigned int &bufferSize)
+{
+ RMDBGENTER(1, RMDebug::module_servercomm, "ServerComm", "getNextElement(...)")
+
+ RMInit::logOut << "Request: getNextElement..." << std::flush;
+
+ unsigned short returnValue = 0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ RMDBGMIDDLE(1, RMDebug::module_servercomm, "ServerComm", "getNextElement(...) TRANSFER " << context->transferFormat << ", EXACT " << (bool)context->exactFormat);
+
+ if( context->transferData && context->transferDataIter &&
+ *(context->transferDataIter) != context->transferData->end() )
+ {
+
+ //
+ // convert data element to rpc data structures
+ //
+ // Buffer is allocated and has to be freed by the caller using free().
+
+ // get next object to be transfered
+ try
+ {
+ QtData* dataObj = **(context->transferDataIter);
+
+ switch( dataObj->getDataType() )
+ {
+ case QT_STRING:
+ {
+ QtStringData* stringDataObj = (QtStringData*)dataObj;
+ bufferSize = stringDataObj->getStringData().length();
+ buffer = (char*)mymalloc( bufferSize );
+ memcpy( (void*)buffer, (void*)stringDataObj->getStringData().c_str(), bufferSize );
+ }
+ break;
+ case QT_INTERVAL:
+ {
+ QtIntervalData* intervalDataObj = (QtIntervalData*)dataObj;
+ char* stringData = intervalDataObj->getIntervalData().get_string_representation();
+ bufferSize = strlen( stringData );
+ buffer = (char*)mymalloc( bufferSize );
+ memcpy( (void*)buffer, (void*)stringData, bufferSize );
+ free( stringData );
+ }
+ break;
+ case QT_MINTERVAL:
+ {
+ QtMintervalData* mintervalDataObj = (QtMintervalData*)dataObj;
+ char* stringData = mintervalDataObj->getMintervalData().get_string_representation();
+ bufferSize = strlen( stringData );
+ buffer = (char*)mymalloc( bufferSize );
+ memcpy( (void*)buffer, (void*)stringData, bufferSize );
+ free( stringData );
+ }
+ break;
+ case QT_POINT:
+ {
+ QtPointData* pointDataObj = (QtPointData*)dataObj;
+ char* stringData = pointDataObj->getPointData().get_string_representation();
+ bufferSize = strlen( stringData );
+ buffer = (char*)mymalloc( bufferSize );
+ memcpy( (void*)buffer, (void*)stringData, bufferSize );
+
+ free( stringData );
+ }
+ break;
+ default:
+ if( dataObj->isScalarData() )
+ {
+ QtScalarData* scalarDataObj = (QtScalarData*)dataObj;
+ bufferSize = scalarDataObj->getValueType()->getSize();
+ buffer = (char*)mymalloc( bufferSize );
+ memcpy( (void*)buffer, (void*)scalarDataObj->getValueBuffer(), bufferSize );
+ // server endianess
+ r_Endian::r_Endianness serverEndian = r_Endian::get_endianness();
+
+ // change endianess if necessary
+ // currently only one client is active at one time
+ // if((context->clientId == 1) && (strcmp(context->clientIdText, ServerComm::HTTPCLIENT) == 0) && (serverEndian != r_Endian::r_Endian_Big))
+ if( (strcmp(context->clientIdText, ServerComm::HTTPCLIENT) == 0) && (serverEndian != r_Endian::r_Endian_Big))
+ {
+ RMInit::logOut << "changing endianness..." << std::flush;
+ // calling client is a http-client(java -> always BigEndian) and server has LittleEndian
+ switch(scalarDataObj->getDataType())
+ {
+ case QT_USHORT:
+ {
+ r_UShort tmp = *(r_UShort*)buffer;
+ *(r_UShort*)buffer = r_Endian::swap(tmp);
+ }
+ break;
+
+ case QT_SHORT:
+ {
+ r_Short tmp = *(r_Short*)buffer;
+ *(r_Short*)buffer = r_Endian::swap(tmp);
+ }
+ break;
+
+ case QT_LONG:
+ {
+ r_Long tmp = *(r_Long*)buffer;
+ *(r_Long*)buffer = r_Endian::swap(tmp);
+ }
+ break;
+
+ case QT_ULONG:
+ {
+ r_ULong tmp = *(r_ULong*)buffer;
+ *(r_ULong*)buffer = r_Endian::swap(tmp);
+ }
+ break;
+
+ case QT_FLOAT:
+ {
+ r_Float tmp = *(r_Float*)buffer;
+ *(r_Float*)buffer = r_Endian::swap(tmp);
+ }
+ break;
+
+ case QT_DOUBLE:
+ {
+ r_Double tmp = *(r_Double*)buffer;
+ *(r_Double*)buffer = r_Endian::swap(tmp);
+ }
+ break;
+
+ default:
+ {
+ RMDBGENTER( 0, RMDebug::module_servercomm, "ServerComm", "getNextElement(...) bad dataType " << scalarDataObj->getDataType());
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ catch( r_Ebase_dbms& myErr)
+ {
+ RMInit::logOut << "Error: base BMS exception (kind " << myErr.get_kind() << ", errno " << myErr.get_errorno() << ") " << myErr.what() << std::endl;
+ throw;
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error: exception (kind " << err.get_kind() << ", errno " << err.get_errorno() << ") " << err.what() << std::endl;
+ throw;
+ }
+
+ // increment list iterator
+ (*(context->transferDataIter))++;
+
+ if( *(context->transferDataIter) != context->transferData->end() )
+ {
+ returnValue = 0;
+ RMInit::logOut << MSG_OK << ", some more tile(s) left." << endl;
+ }
+ else
+ {
+ returnValue = 1;
+ RMInit::logOut << MSG_OK << ", no more tiles." << std::endl;
+ }
+ }
+ else
+ {
+ if( context->transferDataIter && *(context->transferDataIter) == context->transferData->end() )
+ {
+ returnValue = 1; // nothing left in the collection
+ TALK( "nothing left..." << MSG_OK );
+ context->releaseTransferStructures();
+ }
+ else
+ {
+ returnValue = 2; // no actual transfer collection
+ RMInit::logOut << "Error: no transfer collection." << endl;
+ }
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 2;
+ }
+
+ RMDBGEXIT(1, RMDebug::module_servercomm, "ServerComm", "getNextElement(...)")
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getMDDByOId( unsigned long callingClientId,
+ r_OId &oid,
+ r_Minterval &mddDomain,
+ char* &typeName,
+ char* &typeStructure,
+ unsigned short &currentFormat )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getMDDByOId" )
+
+ RMInit::logOut << "Request: getMDDByOId with oid " << oid << "..." << std::flush;
+
+ unsigned short returnValue = 0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ // delete old transfer collection/iterator
+ context->releaseTransferStructures();
+
+ // check type and existence of oid
+ OId oidIf( oid.get_local_oid() );
+ OId::OIdType objType = oidIf.getType();
+
+ if( objType == OId::MDDOID )
+ {
+ // get MDD object
+ try
+ {
+ context->transferMDD = new MDDObj( oidIf );
+ }
+ catch(std::bad_alloc)
+ {
+ RMInit::logOut << "Error: cannot allocate memory." << std::endl;
+ context->release();
+ throw;
+ }
+ catch (r_Error& err)
+ {
+ RMInit::logOut << "Error: (kind " << err.get_kind() << ", errno " << err.get_errorno() << ") " << err.what() << std::endl;
+ context->release();
+ throw;
+ }
+ catch(...)
+ {
+ returnValue = 2;
+ RMInit::logOut << "Error: unspecified exception." << endl;
+ }
+
+ if( !returnValue )
+ {
+ //
+ // convert the mdd to transfer to rpc data structures
+ //
+
+ // initialize mddDomain to give it back
+ mddDomain = context->transferMDD->getCurrentDomain();
+
+ TALK( "domain " << mddDomain );
+
+ // initialize context fields
+ context->transTiles = context->transferMDD->getTiles();
+ context->tileIter = new vector<Tile*>::iterator;
+ *(context->tileIter) = context->transTiles->begin();
+
+ const BaseType* baseType = context->transferMDD->getCellType();
+
+ TALK( "cell length " << baseType->getSize() );
+
+ //
+ // set typeName and typeStructure
+ //
+ // old: typeName = strdup( context->transferMDD->getCellTypeName() ); not known for the moment being
+
+ typeName = strdup("");
+
+ // create a temporary mdd type for the moment being
+ MDDType* mddType = new MDDDomainType( "tmp", (BaseType*)baseType, context->transferMDD->getCurrentDomain() );
+ TypeFactory::addTempType( mddType );
+
+ typeStructure = mddType->getTypeStructure(); // no copy !!!
+
+ // I'm not sure about this code either
+#if 0
+ // determine data format from the 1st tile
+ if( context->transTiles->size() && (*(context->transTiles))[0]->getDataFormat() == r_TIFF )
+ currentFormat = r_TIFF;
+ else
+ currentFormat = r_Array;
+#else
+ if (context->transTiles->size())
+ currentFormat = (*(context->transTiles))[0]->getDataFormat();
+ else
+ currentFormat = r_Array;
+#endif
+
+ // set oid in case of persistent MDD objects
+ if( context->transferMDD->isPersistent() )
+ {
+ EOId eOId;
+
+ if( ((MDDObj*)(context->transferMDD))->getEOId( &eOId ) == 0 )
+ oid = r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() );
+ }
+
+ //
+ //
+ //
+
+ if( context->transTiles->size() > 0 )
+ {
+ RMInit::logOut << MSG_OK << ", got " << context->transTiles->size() << " tile(s)." << endl;
+ }
+ else // context->transTiles->size() == 0
+ {
+ returnValue = 3;
+ RMInit::logOut << "Error: no tiles in MDD object." << endl;
+ }
+ }
+ }
+ else
+ {
+ returnValue = 2; // oid does not belong to an MDD object
+ RMInit::logOut << "Error: oid does not belong to an MDD object." << endl;
+ }
+
+ //
+ // done
+ //
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1; // client context not found
+ }
+
+ context->totalRawSize = 0;
+ context->totalTransferedSize = 0;
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getMDDByOId" )
+
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getNextTile( unsigned long callingClientId,
+ RPCMarray** rpcMarray )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getNextTile" )
+
+ RMInit::logOut << "Request: getNextTile..." << std::flush;
+
+ unsigned long transOffset = 0;
+ unsigned long transSize = 0;
+ unsigned short statusValue = 0;
+ unsigned short returnValue = 0;
+
+ // initialize the result parameter for failure cases
+ *rpcMarray = 0;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ if( context->transTiles && context->tileIter )
+ {
+ Tile* resultTile = **(context->tileIter);
+ r_Minterval mddDomain = resultTile->getDomain();
+ void* useTransData;
+ unsigned long totalSize;
+
+ // allocate memory for the output parameter rpcMarray
+ *rpcMarray = (RPCMarray*)mymalloc( sizeof( RPCMarray ) );
+
+ if ( context->bytesToTransfer == 0 )
+ {
+ // free old data
+ if (context->encodedData != NULL)
+ {
+ free(context->encodedData);
+ context->encodedData = NULL;
+ context->encodedSize = 0;
+ }
+
+ // Transfer compression...
+ // we have to repack the data if ((tf != cf) && exact) or ((tf != Array) && (cf == Array))
+ // where tf = transferFormat, cf = currentFormat.
+ r_Data_Format tf = context->transferFormat;
+ r_Data_Format cf = resultTile->getDataFormat();
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "getNextTile CURRENT " << cf << ", TRANSFER " << tf << ", EXACT " << (bool)context->exactFormat);
+ if (((tf != cf) && (context->exactFormat != 0)) || ((tf != r_Array) && (cf == r_Array)))
+ {
+ RMDBGMIDDLE(4, RMDebug::module_servercomm, "ServerComm", "repack data from " << cf << " to " << tf)
+
+ //the cast from const char* to char* is okay because the owner flag is set correctly
+ char *encData = (char*)resultTile->getCompressedContents();
+ unsigned long encSize = resultTile->getCompressedSize();
+ //the data format could have changed during compression
+ cf = resultTile->getDataFormat();
+ // this method actually repacks everything as needed
+ if(ensureTileFormat(cf, tf, mddDomain, resultTile->getType(),
+ encData, encSize, 1, 0, context->transferFormatParams) != ENSURE_TILE_FORMAT_OK)
+ {
+ //FIXME returnValue
+ returnValue = 4;
+
+ RMInit::logOut << "Error: tile format mismatch while fetching next tile." << endl;
+ (*rpcMarray)->domain = mddDomain.get_string_representation();
+
+ // allocate memory for the output parameter data and assign its fields
+ (*rpcMarray)->data.confarray_len = 0;
+ (*rpcMarray)->data.confarray_val = NULL;
+ // 3. store cell type length
+ (*rpcMarray)->cellTypeLength = 0;
+
+ context->release();
+ return returnValue;
+ }
+ // if the new format is bigger than the old one and we're allowed to, revert to the old one
+ if ((encSize >= resultTile->getCompressedSize()) && (context->exactFormat == 0))
+ {
+ free( encData );
+ }
+ else
+ {
+ context->encodedData = encData;
+ context->encodedSize = encSize;
+ }
+ }
+ }
+
+ // note: transfer compression affects the current format, not the storage format.
+ if ( context->encodedData == NULL )
+ {
+ totalSize = resultTile->getCompressedSize();
+ //this is bad because useTransData is char* although it is not modified
+ useTransData = (char*)resultTile->getCompressedContents();
+ (*rpcMarray)->currentFormat = resultTile->getDataFormat();
+ RMDBGMIDDLE(4, RMDebug::module_servercomm, "ServerComm", "using tile format " << (r_Data_Format)(*rpcMarray)->currentFormat)
+ }
+ else
+ {
+ totalSize = context->encodedSize;
+ useTransData = context->encodedData;
+ (*rpcMarray)->currentFormat = context->transferFormat;
+ //FILE *fp = fopen("trans_data.raw", "wb"); fwrite(useTransData, 1, totalSize, fp); fclose(fp);
+ RMDBGMIDDLE(4, RMDebug::module_servercomm, "ServerComm", "using transfer format " << (r_Data_Format)(*rpcMarray)->currentFormat)
+ }
+ // Preserve storage format
+ (*rpcMarray)->storageFormat = resultTile->getDataFormat();
+ RMDBGMIDDLE(4, RMDebug::module_servercomm, "ServerComm", "rpc storage " << (r_Data_Format)(*rpcMarray)->storageFormat)
+ RMDBGMIDDLE(4, RMDebug::module_servercomm, "ServerComm", "rpc current " << (r_Data_Format)(*rpcMarray)->currentFormat)
+
+ transSize = totalSize;
+
+ if( totalSize > maxTransferBufferSize )
+ {
+ // if there is the rest of a tile to transfer, do it!
+ if( context->bytesToTransfer )
+ {
+ TALK( " resuming block transfer..." );
+ transOffset = totalSize - context->bytesToTransfer;
+ if( context->bytesToTransfer > maxTransferBufferSize )
+ {
+ transSize = maxTransferBufferSize;
+ statusValue = 1;
+ }
+ else
+ {
+ transSize = context->bytesToTransfer;
+ statusValue = 2;
+ }
+
+ context->bytesToTransfer -= transSize;
+ }
+ else // transfer first block of too large tile
+ {
+ TALK( " has to be split..." );
+ transSize = maxTransferBufferSize;
+ context->bytesToTransfer = totalSize - transSize;
+ statusValue = 1;
+ }
+ }
+ else // resultTile->getSize() <= maxTransferBufferSize
+ statusValue = 3;
+
+ context->totalTransferedSize += transSize;
+
+ // 1. convert domain
+ (*rpcMarray)->domain = mddDomain.get_string_representation();
+
+ // 2. copy data pointers
+ TALK( " domain " << mddDomain << ", " << transSize << " bytes" );
+
+ // allocate memory for the output parameter data and assign its fields
+ (*rpcMarray)->data.confarray_len = (unsigned int)transSize;
+ (*rpcMarray)->data.confarray_val = ((char*)useTransData) + transOffset;
+
+ // 3. store cell type length
+ (*rpcMarray)->cellTypeLength = resultTile->getType()->getSize();
+
+ // increment iterator only if tile is transferred completely
+ if( statusValue > 1 )
+ {
+ context->totalRawSize += resultTile->getSize();
+ (*context->tileIter)++;
+ }
+
+ // delete tile vector and increment transfer collection iterator if tile iterator is exhausted
+ if( (*context->tileIter) == context->transTiles->end() )
+ {
+
+ // delete tile vector transTiles (tiles are deleted when the object is deleted)
+ if( context->transTiles )
+ {
+ delete context->transTiles;
+ context->transTiles = 0;
+ }
+
+ // delete tile iterator
+ if( context->tileIter )
+ {
+ delete context->tileIter;
+ context->tileIter = 0;
+ }
+
+ if( context->transferDataIter )
+ {
+ (*(context->transferDataIter))++;
+
+ if( *(context->transferDataIter) != context->transferData->end() )
+ {
+ returnValue = 1;
+ TALK( " some MDDs left..." );
+ RMInit::logOut << MSG_OK << ", some MDD(s) left." << endl;
+ }
+ else
+ {
+ // no elements left -> delete collection and iterator
+
+ // Memory of last tile is still needed for the last byte transfer,
+ // therefore, do not release memory now, but with any next RPC call.
+ // context->releaseTransferStructures();
+
+ returnValue = 0;
+ RMInit::logOut << MSG_OK << ", all MDDs fetched." << endl;
+ }
+ }
+ else
+ {
+ returnValue = 0;
+ RMInit::logOut << MSG_OK << ", MDD transfer complete." << endl;
+ }
+
+ if ((context->totalTransferedSize != context->totalRawSize) && (context->totalRawSize != 0))
+ {
+ TALK( "(compressed using " << context->transferFormat << " to " << ((r_Double)(100 * context->totalTransferedSize)) / context->totalRawSize << "%) " );
+ }
+ }
+ else
+ {
+ if( statusValue == 1 ) // at least one block in actual tile is left
+ {
+ RMInit::logOut << MSG_OK << ", some block(s) left." << endl;
+ returnValue = 3;
+ }
+ else // tiles left in actual MDD
+ {
+ RMInit::logOut << MSG_OK << ", some tile(s) left." << endl;
+ returnValue = 2;
+ }
+ }
+ }
+ else // no actual transfer collection or nothing left in the collection
+ {
+ returnValue = 4;
+ RMInit::logOut << "Error: no transfer collection or nothing left in collection." << endl;
+ }
+
+ context->release();
+ }
+ else
+ { // client context not found
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 4;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getNextTile" )
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::endTransfer( unsigned long client )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "endTransfer" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Client " << client << " called: endTransfer..." << std::flush;
+
+ ClientTblElt* context = getClientContext( client );
+
+ if( context )
+ {
+#ifdef RMANBENCHMARK
+ Tile::relTimer.stop();
+ Tile::opTimer.stop();
+ ZLibCompression::decompTimer.stop();
+ ZLibCompression::compTimer.stop();
+ if( context->evaluationTimer ) delete context->evaluationTimer;
+ context->evaluationTimer = 0;
+ if( context->transferTimer ) delete context->transferTimer;
+ context->transferTimer = 0;
+ RMTimer* releaseTimer = 0;
+
+ if( RManBenchmark > 0 )
+ releaseTimer = new RMTimer("ServerComm", "release time ");
+#endif
+ // release transfer collection/iterator
+ context->releaseTransferStructures();
+
+#ifdef RMANBENCHMARK
+ if( releaseTimer ) delete releaseTimer;
+#endif
+
+ context->release();
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "endTransfer" )
+ return returnValue;
+}
+
+
+
+/*************************************************************************
+ * Method name...: aliveSignal( unsigned long client )
+ ************************************************************************/
+unsigned short
+ServerComm::aliveSignal( unsigned long client )
+{
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Client " << client << " called: endTransfer..." << std::flush;
+
+ ClientTblElt* context = getClientContext( client );
+
+ if( context )
+ {
+ // set the time of the client's last action to now
+ context->lastActionTime = time( NULL );
+
+ returnValue = 1;
+
+ context->release();
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ }
+
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getNewOId( unsigned long callingClientId,
+ unsigned short objType,
+ r_OId& oid )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getNewOId" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: getNewOId of type "
+ << (objType==1?"MDD":"collection") << "..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ EOId eOId;
+
+ if( objType == 1 )
+ EOId::allocateEOId( eOId, OId::MDDOID );
+ else // objType == 2
+ EOId::allocateEOId( eOId, OId::MDDCOLLOID );
+
+ RMDBGMIDDLE( 4, RMDebug::module_servercomm, "ServerComm", "allocated " << eOId)
+ oid = r_OId( eOId.getSystemName(), eOId.getBaseName(), eOId.getOId() );
+
+ context->release();
+
+ RMInit::logOut << MSG_OK << std::endl;
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getNewOId " << returnValue)
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getObjectType( unsigned long callingClientId,
+ r_OId& oid,
+ unsigned short &objType )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getObjectType" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: getObjectType by oid " << oid << "..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if( context != 0 )
+ {
+ OId oidIf( oid.get_local_oid() );
+
+ objType = oidIf.getType();
+
+ if( objType == OId::INVALID )
+ {
+ // oid not found
+ RMInit::logOut << "Error: no type for this oid." << std::endl;
+ returnValue = 2;
+ }
+ else
+ {
+ RMInit::logOut << "type is " << (objType==1?"MDD":"collection") << "..." << MSG_OK << endl;
+ }
+
+ context->release();
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << endl;
+ returnValue = 1;
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getObjectType" )
+ return returnValue;
+}
+
+
+
+unsigned short
+ServerComm::getTypeStructure( unsigned long callingClientId,
+ const char* typeName,
+ unsigned short typeType,
+ char* &typeStructure )
+{
+ RMDBGENTER( 4, RMDebug::module_servercomm, "ServerComm", "getTypeStructure" )
+ unsigned short returnValue = 0;
+
+ RMInit::logOut << "Request: getTypeStructure of type '" << typeName << "'..." << std::flush;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+ if (context == 0)
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ returnValue = 1;
+ }
+
+ if (returnValue==0 && !transactionActive)
+ {
+ RMInit::logOut << "Error: no transaction open." << endl;
+ returnValue = 1;
+ }
+
+ if (returnValue==0)
+ {
+ if( typeType == 1 )
+ {
+ // get collection type
+ CollectionType* collType = (CollectionType*)TypeFactory::mapSetType( (char*)typeName );
+
+ if( collType )
+ typeStructure = collType->getTypeStructure(); // no copy
+ else
+ returnValue = 2;
+ }
+ else if( typeType == 2 )
+ {
+ // get MDD type
+ const MDDType* mddType = TypeFactory::mapMDDType( typeName );
+
+ if( mddType )
+ typeStructure = mddType->getTypeStructure(); // no copy
+ else
+ returnValue = 2;
+ }
+ else // base type not implemented
+ {
+ returnValue = 2;
+ }
+
+ if( returnValue == 2 )
+ RMInit::logOut << "Error: unknown type." << endl;
+ else
+ RMInit::logOut << MSG_OK << endl;
+
+ context->release();
+ }
+
+ RMDBGEXIT( 4, RMDebug::module_servercomm, "ServerComm", "getTypeStructure" )
+ return returnValue;
+}
+
+
+unsigned short
+ServerComm::setTransferMode( unsigned long callingClientId,
+ unsigned short format,
+ const char* formatParams )
+{
+ RMDBGENTER(4, RMDebug::module_servercomm, "ServerComm", "setTransferMode(" << callingClientId << ", " << format << ", " << formatParams)
+
+ RMInit::logOut << "Request: setTransferMode..." << std::flush;
+
+ unsigned short retval = 1;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if (context != 0)
+ {
+ r_Data_Format fmt = (r_Data_Format)format;
+ // query compression module whether this is a legal format for transfer compression
+ if (r_Tile_Compression::check_data_format(fmt) == r_Tile_Compression::INVALID)
+ {
+ RMInit::logOut << "Error: invalid transfer compression format: " << format << std::endl;
+ retval = 2;
+ }
+ else
+ {
+ if (context->transferFormatParams != NULL)
+ {
+ delete [] context->transferFormatParams;
+ context->transferFormatParams = NULL;
+ // revert the transfer format strictness
+ context->exactFormat = 0;
+ }
+ if (formatParams != NULL)
+ {
+ context->transferFormatParams = new char[strlen(formatParams)+1];
+ strcpy(context->transferFormatParams, formatParams);
+ // extract any occurrences of ``exactformat''
+ context->clientParams->process(context->transferFormatParams);
+ }
+ context->transferFormat = fmt;
+
+ RMInit::logOut << MSG_OK << std::endl;
+ retval = 0;
+ }
+ context->release();
+ RMDBGMIDDLE(1, RMDebug::module_servercomm, "ServerComm", "setTransferMode(...) current transfer format :" << context->transferFormat)
+ RMDBGMIDDLE(1, RMDebug::module_servercomm, "ServerComm", "setTransferMode(...)current transfer params :" << context->transferFormatParams );
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ retval = 1;
+ }
+
+ RMDBGEXIT(4, RMDebug::module_servercomm, "ServerComm", "setTransferMode " << retval)
+ return retval;
+}
+
+unsigned short
+ServerComm::setStorageMode( unsigned long callingClientId,
+ unsigned short format,
+ const char* formatParams )
+{
+ RMDBGENTER(4, RMDebug::module_servercomm, "ServerComm", "setStorageMode(" << callingClientId << ", " << format << ", " << formatParams)
+
+ RMInit::logOut << "Request: setStorageMode..." << std::flush;
+
+ unsigned short retval = 1;
+
+ ClientTblElt* context = getClientContext( callingClientId );
+
+ if (context != 0)
+ {
+ r_Data_Format fmt = (r_Data_Format)format;
+ if (r_Tile_Compression::check_data_format(fmt) == r_Tile_Compression::INVALID)
+ {
+ RMInit::logOut << "Error: invalid storage compression format: " << format << std::endl;
+ retval = 2;
+ }
+ else
+ {
+ if (context->storageFormatParams != NULL)
+ {
+ delete [] context->storageFormatParams;
+ context->storageFormatParams = NULL;
+ }
+ if (formatParams != NULL)
+ {
+ context->storageFormatParams = new char[strlen(formatParams)+1];
+ strcpy(context->storageFormatParams, formatParams);
+ }
+ context->storageFormat = fmt;
+
+ RMInit::logOut << MSG_OK << std::endl;
+ retval = 0;
+ }
+ context->release();
+ RMDBGMIDDLE(1, RMDebug::module_servercomm, "ServerComm", "setStorageMode(...) current storage format :" << context->storageFormat)
+ RMDBGMIDDLE(1, RMDebug::module_servercomm, "ServerComm", "setStorageMode(...) current storage params :" << context->storageFormatParams)
+ }
+ else
+ {
+ RMInit::logOut << "Error: client not registered." << std::endl;
+ retval = 1;
+ }
+
+ RMDBGEXIT(4, RMDebug::module_servercomm, "ServerComm", "setStorageMode " << retval)
+ return retval;
+}
+
+int
+ServerComm::ensureTileFormat( r_Data_Format &hasFmt,
+ r_Data_Format needFmt,
+ const r_Minterval &dom,
+ const BaseType *type,
+ char *&data,
+ unsigned long &size,
+ int repack,
+ int owner,
+ const char *params )
+{
+ RMDBGENTER(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(" << hasFmt << ", " << needFmt << ", " << dom << ", " << type->getName() << ", data, " << size << ", repack " << repack << ", owner " << owner << ", params " << params << ")")
+ int status = ENSURE_TILE_FORMAT_OK;
+
+ RMDBGMIDDLE(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(...) #Size 1=" << size);
+
+ // convert to storage format (this should go into a separate function)
+ if (hasFmt != needFmt)
+ {
+ r_Tile_Compression *engine = NULL;
+ r_ULong newSize=0;
+ char *newData=NULL;
+
+ char *tpstruct = type->getTypeStructure();
+ r_Base_Type *compType = (r_Base_Type*)(r_Type::get_any_type(tpstruct));
+
+ // decompress
+ try
+ {
+ engine = r_Tile_Compression::create(hasFmt, dom, compType);
+ // decompression doesn't change the size variable!
+ newData = (char*)(engine->decompress(data, size, params));
+ delete engine;
+
+ if (newData == NULL)
+ {
+ RMInit::logOut << "Error: decompression failed for format '" << hasFmt << "'." << endl;
+ size = dom.cell_count() * compType->size();
+ newData = (char*)mymalloc(size * sizeof(char));
+ memset(newData, 0, size);
+ // FIXME: make it an error!! --PB 2005-aug-25
+ RMInit::logOut << "Error fixed by returning empty data of length " << size << " bytes." << std::endl;
+ }
+ // do I actually own the data?
+ if (owner != 0)
+ free(data);
+ data = newData;
+ size = dom.cell_count() * (compType->size());
+ hasFmt = r_Array;
+ }
+ catch (r_Error &err)
+ {
+ RMInit::logOut << "Error: cannot decompress format '" << hasFmt << "' (" << err.get_errorno() << "): " << err.what() << endl;
+ RMDBGEXIT(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(...) " << ENSURE_TILE_FORMAT_BAD)
+ status = ENSURE_TILE_FORMAT_BAD;
+ }
+
+ RMDBGMIDDLE(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(...) #Size 2=" << size);
+
+ if ((status == ENSURE_TILE_FORMAT_OK) && (repack != 0) && (needFmt != r_Array))
+ {
+ try
+ {
+ newSize = size;
+ engine = r_Tile_Compression::create(needFmt, dom, compType);
+ newData = (char*)(engine->compress(data, newSize, params));
+ delete engine;
+
+ if (newData == NULL)
+ {
+ RMInit::logOut << "Error: recompression failed for format '" << needFmt << "'." << endl;
+ RMDBGEXIT(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(...) " << ENSURE_TILE_FORMAT_BAD)
+ status = ENSURE_TILE_FORMAT_BAD;
+ }
+ else
+ {
+ free(data);
+ data = newData; size = newSize;
+ hasFmt = needFmt;
+ RMDBGMIDDLE(2, RMDebug::module_servercomm, "ServerComm", "recompressed to " << hasFmt << " size " << size)
+ }
+ }
+ catch (r_Error &err)
+ {
+ RMInit::logOut << "Error: unsupported tile format '" << needFmt << "' (" << err.get_errorno() << "): " << err.what() << endl;
+ RMDBGEXIT(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat " << ENSURE_TILE_FORMAT_BAD)
+ status = ENSURE_TILE_FORMAT_BAD;
+ }
+ }
+ else
+ {
+ RMDBGMIDDLE(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(...) do not recompress")
+ }
+ delete compType;
+ free(tpstruct);
+ }
+
+ RMDBGMIDDLE(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(...) #Size 3=" << size);
+ RMDBGEXIT(2, RMDebug::module_servercomm, "ServerComm", "ensureTileFormat(...) " << ENSURE_TILE_FORMAT_OK)
+ return status;
+}