/* * 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 . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . */ /************************************************************* * * * PURPOSE: * * * COMMENTS: * ************************************************************/ using namespace std; #include "mymalloc/mymalloc.h" #include "rasserver_entry.hh" #include "debug-srv.hh" // console output describing successful/unsuccessful actions (cf. servercomm/servercomm.cc) #define MSG_OK "ok" #define MSG_FAILED "failed" struct HTTPRequest { char *Database; int Command; char *QueryString; int ClientType; char *ClientID; int Endianess; int NumberOfQueryParams; char *BinData; int BinDataSize; char *Capability; }; RasServerEntry* RasServerEntry::myself = 0; RasServerEntry& RasServerEntry::getInstance() { if(myself == 0) myself = new RasServerEntry; return *myself; } RasServerEntry::RasServerEntry() { } RasServerEntry::~RasServerEntry() { } void RasServerEntry::compat_connectToDBMS() throw( r_Error ) { // here no log output, this is a server startup function! admin = AdminIf::instance(); if( !admin ) throw r_Error( r_Error::r_Error_BaseDBMSFailed ); } void RasServerEntry::compat_connectNewClient(const char *capability) { // we need to add the log information which otherwise is provided in ServerComm (servercomm/servercomm2.cc) RMInit::logOut << "Request: connectNewClient..." << flush; char client[256]; strcpy( client, "unknown" ); #if 0 // client table is a relict from 1-process, multi-user rasdaman; // now it conflicts with rasmgr dispatcher mimics, so we disable -- PB 2005-sep-01 currentClientContext = new ClientTblElt( client, ++(clientCount) ); currentClientIdx = clientCount; #else // this id must be !=0 because otherwise in ServerComm::getClientContext() it will not be recognized as valid id, and then the "last action" time will not be updated (timeout!) #define SINGLETON_CLIENTID 42 // disable client list by using only 1 element (fixed id), initialize only once currentClientIdx = SINGLETON_CLIENTID; // if (currentClientContext==NULL) currentClientContext = new ClientTblElt( client, currentClientIdx ); TALK( "using constant Client id " << currentClientIdx ); // make sure any old element is deleted; currently inhibited, crashes :( -- PB 2005-sep-02 // RMInit::logOut << "client table has " << clientTbl.size() << " elements before cleanup, "; // ServerComm::deleteClientTblEntry( currentClientIdx ); // RMInit::logOut << " and " << clientTbl.size() << " after."; #endif // 0 // Put the context information in the static control list ServerComm::addClientTblEntry( currentClientContext ); TALK( "assigned Client id " << currentClientIdx ); if(accessControl.crunchCapability(capability) == CAPABILITY_REFUSED) throw r_Ecapability_refused(); RMInit::logOut << MSG_OK << endl; } void RasServerEntry::compat_disconnectClient() { // we need to add the log information which otherwise is provided in ServerComm (servercomm/servercomm2.cc) RMInit::logOut << "Request: disconnect..." << flush; #if 0 // deleteClientTblEntry( currentClientIdx ); currentClientIdx = -1; #else // disable client list, use 1 constant element (see above) -- PB 2005-sep-01 currentClientIdx = SINGLETON_CLIENTID; ServerComm::deleteClientTblEntry( currentClientIdx ); // delete currentClientContext; // currentClientContext = NULL; // clientTbl.resize( 0 ); RMInit::logOut << MSG_OK << endl; #endif // 0 // in a disconnect following an abortta, the client can't be found any more in the table. // the delete op below then doesn't decrease table size -> endless loop. // Therefore let us take the original approach: delete only the requested client. -- PB 2003-nov-24 #if 0 // THIS IS PARANOIA, ONCE WE HAD SOME PROBLEMS, SO WE KILL ALL while(!clientTbl.empty()) { ClientTblElt *temp = clientTbl.front(); temp->currentUsers = 0; // forced! deleteClientTblEntry(temp->clientId); } #endif // 0 } // we want the ServerComm version, we'll drop this client management anyway ServerComm::ClientTblElt* RasServerEntry::getClientContext( unsigned long ClientId ) { #if 0 // see above -- we just have 1 single context -- PB 2005-sep-01 ClientId = SINGLETON_CLIENTID; #endif // 0 return ServerComm::getClientContext( ClientId ); } void RasServerEntry::compat_openDB(const char* databaseName) { // we use "ServercComm::" just to show that it's that function ServerComm::openDB( currentClientIdx, databaseName, "" ); } void RasServerEntry::compat_closeDB() { ServerComm::closeDB( currentClientIdx); } void RasServerEntry::compat_beginTA(bool rw) { ServerComm::beginTA( currentClientIdx, rw ? 0 : 1); } void RasServerEntry::compat_commitTA() { ServerComm::commitTA( currentClientIdx); } void RasServerEntry::compat_abortTA() { ServerComm::abortTA( currentClientIdx); } bool RasServerEntry::compat_isOpenTA() { return ServerComm::isTAOpen( currentClientIdx ); } int GetHTTPRequestTemp( char *Source, int SourceLen, struct HTTPRequest *RequestInfo); int RasServerEntry::compat_executeQueryHttp(const char* httpParams, int httpParamsLen, char*& resultBuffer) { strcpy(currentClientContext->clientIdText, ServerComm::HTTPCLIENT); HTTPRequest RequestInfo; /* Initialize RequestInfo */ RequestInfo.Database = NULL; RequestInfo.QueryString = NULL; RequestInfo.ClientType = 0; RequestInfo.ClientID = NULL; RequestInfo.Command = 0; RequestInfo.Endianess = 0; RequestInfo.NumberOfQueryParams = 0; RequestInfo.BinDataSize = 0; RequestInfo.BinData = NULL; RequestInfo.Capability = NULL; int resultLen = 0; if(GetHTTPRequestTemp( (char*)httpParams, httpParamsLen, &RequestInfo) == 0) { // we need to add the log information which otherwise is provided in ServerComm (servercomm/servercomm2.cc) // logged now in rnprotocol modules -- PB 2005-sep-05 // RMInit::logOut << "Request: http query '" << RequestInfo.QueryString << "'..." << flush; char* queryResult; resultLen = HttpServer::processRequest(currentClientIdx, RequestInfo.Database, RequestInfo.Command, RequestInfo.QueryString, RequestInfo.BinDataSize, RequestInfo.BinData, RequestInfo.Endianess, queryResult,RequestInfo.Capability); resultBuffer = queryResult; RMInit::logOut << MSG_OK << endl; } else RMInit::logOut << "Error: Internal HTTP protocol mismatch." << endl; // free RequestInfo free(RequestInfo.Database); free(RequestInfo.QueryString); free(RequestInfo.Capability); free(RequestInfo.BinData); free(RequestInfo.ClientID); return resultLen; } r_OId RasServerEntry::compat_getNewOId(unsigned short objType) { r_OId result; ServerComm::getNewOId(currentClientIdx, objType, result); return result; } int RasServerEntry::compat_executeQueryRpc(const char* query, ExecuteQueryRes &queryResult) { queryResult.token=NULL; queryResult.typeName=NULL; queryResult.typeStructure=NULL; return ServerComm::executeQuery(currentClientIdx, query, queryResult); } int RasServerEntry::compat_getNextElement(char* &buffer, unsigned int &bufferSize ) { return ServerComm::getNextElement(currentClientIdx, buffer, bufferSize); } int RasServerEntry::compat_endTransfer() { return ServerComm::endTransfer(currentClientIdx); } int RasServerEntry::compat_getNextMDD(r_Minterval &mddDomain, char* &typeName, char* &typeStructure, r_OId &oid,unsigned short ¤tFormat) { return ServerComm::getNextMDD( currentClientIdx, mddDomain, typeName, typeStructure, oid, currentFormat); } int RasServerEntry::compat_getNextTile(RPCMarray** rpcMarray) { return ServerComm::getNextTile( currentClientIdx, rpcMarray); } int RasServerEntry::compat_ExecuteUpdateQuery(const char *query, ExecuteUpdateRes& returnStructure) { return ServerComm::executeUpdate(currentClientIdx, query, returnStructure); } int RasServerEntry::compat_InitUpdate() { return ServerComm::initExecuteUpdate(currentClientIdx); } int RasServerEntry::compat_StartInsertTransMDD(const char *domain, int typeLength, const char *typeName) { r_Minterval mddDomain(domain); return ServerComm::startInsertTransMDD(currentClientIdx, mddDomain, typeLength, typeName); } int RasServerEntry::compat_InsertTile(int persistent, RPCMarray *rpcMarray) { return ServerComm::insertTile( currentClientIdx, persistent, rpcMarray ); } int RasServerEntry::compat_EndInsertMDD(int persistent) { return ServerComm::endInsertMDD( currentClientIdx, persistent ); } int RasServerEntry::compat_GetTypeStructure(const char *typeName, int typeType, char* &typeStructure) { return ServerComm::getTypeStructure( currentClientIdx, typeName, typeType, typeStructure ); } int RasServerEntry::compat_StartInsertPersMDD(const char *collName, r_Minterval &mddDomain, int typeLength, const char *typeName, r_OId &oid) { return ServerComm::startInsertPersMDD( currentClientIdx, collName, mddDomain, typeLength, typeName, oid ); } int RasServerEntry::compat_InsertMDD(const char *collName, RPCMarray *rpcMarray, const char *typeName, r_OId &oid) { return ServerComm::insertMDD( currentClientIdx, collName, rpcMarray, typeName, oid ); } int RasServerEntry::compat_InsertCollection(const char *collName, const char *typeName, r_OId &oid) { return ServerComm::insertColl( currentClientIdx, collName, typeName, oid ); } int RasServerEntry::compat_DeleteCollByName(const char *collName) { return ServerComm::deleteCollByName( currentClientIdx, collName ); } int RasServerEntry::compat_DeleteObjByOId(r_OId &oid) { return ServerComm::deleteObjByOId( currentClientIdx, oid ); } int RasServerEntry::compat_RemoveObjFromColl(const char *collName, r_OId &oid) { return ServerComm::removeObjFromColl( currentClientIdx, collName, oid ); } int RasServerEntry::compat_GetCollectionByName(const char* collName, char* &typeName, char* &typeStructure, r_OId &oid) { return ServerComm::getCollByName( currentClientIdx, collName, typeName, typeStructure, oid ); } int RasServerEntry::compat_GetCollectionByName(r_OId oid, char* &typeName, char* &typeStructure, char* &collName) { return ServerComm::getCollByOId( currentClientIdx, oid, typeName,typeStructure, collName ); } int RasServerEntry::compat_GetCollectionOidsByName(const char* collName, char* &typeName, char* &typeStructure, r_OId &oid, RPCOIdEntry* &oidTable, unsigned int &oidTableSize) { return ServerComm::getCollOIdsByName( currentClientIdx, collName, typeName, typeStructure, oid, oidTable, oidTableSize); } int RasServerEntry::compat_GetCollectionOidsByOId(r_OId oid, char* &typeName, char* &typeStructure, RPCOIdEntry* &oidTable, unsigned int &oidTableSize, char* &collName) { return ServerComm::getCollOIdsByOId( currentClientIdx, oid, typeName, typeStructure, oidTable, oidTableSize, collName); } int RasServerEntry::compat_GetObjectType(r_OId &oid, unsigned short &objType) { return ServerComm::getObjectType( currentClientIdx, oid, objType ); } int RasServerEntry::compat_SetTransferFormat(int format, const char* params) { return ServerComm::setTransferMode( currentClientIdx, format, params ); } int RasServerEntry::compat_SetStorageFormat(int format, const char* params) { return ServerComm::setStorageMode( currentClientIdx, format, params ); } //### stupid inherited stuff, we'll lose them later ##### void RasServerEntry::startRpcServer() throw( r_Error ){} void RasServerEntry::stopRpcServer(){} //####################################################### // local version of this function, with small adaptations to compile here. int GetHTTPRequestTemp( char *Source, int SourceLen, struct HTTPRequest *RequestInfo) { ENTER( "GetHTTPRequestTemp, source=" << Source << ", SourceLen=" << SourceLen ); int result = 0; // function return value char *Buffer = NULL; // ptr to current analysis point in Input char *Input = NULL; // local copy of Source Input = new char[ SourceLen + 1 ]; memcpy( Input, Source, SourceLen ); Input[SourceLen] = '\0'; // Read the message body and check for the post parameters Buffer = strtok( Input, "=" ); while( Buffer != NULL ) { if( strcmp(Buffer,"Database") == 0 ) { RequestInfo->Database = strdup(strtok( NULL, "&" )); TALK( "Parameter Database is " << RequestInfo->Database ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"QueryString") == 0 ) { RequestInfo->QueryString = strdup(strtok( NULL, "&" )); TALK( "Parameter QueryString is " << RequestInfo->QueryString ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"Capability") == 0 ) { RequestInfo->Capability = strdup(strtok( NULL, "&\0" )); TALK( "Parameter Capability is " << RequestInfo->Capability ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"ClientID") == 0 ) { RequestInfo->ClientID = strdup(strtok( NULL, "&" )); TALK( "Parameter ClientID is " << RequestInfo->ClientID ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"Command") == 0 ) { RequestInfo->Command = atoi( strtok( NULL, "&" ) ); TALK( "Parameter Command is " << RequestInfo->Command ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"Endianess") == 0 ) { RequestInfo->Endianess = atoi( strtok( NULL, "&" ) ); TALK( "Parameter Endianess is " << RequestInfo->Endianess ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"NumberOfQueryParameters") == 0 ) { RequestInfo->NumberOfQueryParams = atoi( strtok( NULL, "&" ) ); TALK( "Parameter NumberOfQueryParams is " << RequestInfo->NumberOfQueryParams ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"BinDataSize") == 0 ) { RequestInfo->BinDataSize = atoi( strtok( NULL, "&" ) ); TALK( "Parameter BinDataSize is " << RequestInfo->BinDataSize ); Buffer = strtok( NULL, "=" ); } else if( strcmp(Buffer,"BinData") == 0 ) { // This parameter has to be the last one! RequestInfo->BinData = new char[RequestInfo->BinDataSize ]; memcpy(RequestInfo->BinData, Source + (SourceLen-RequestInfo->BinDataSize), RequestInfo->BinDataSize ); //set Buffer to NULL => exit this while block Buffer = NULL; } else if( strcmp(Buffer,"ClientType") == 0 ) { Buffer = strtok( NULL, "&" ); TALK( "Parameter Type is " << Buffer ); /* BROWSER? */ if( strcmp(Buffer,"BROWSER") == 0 ) RequestInfo->ClientType = 1; /* Rasclient? */ else if( strcmp(Buffer,"RASCLIENT") == 0 ) RequestInfo->ClientType = 2; /* Sonstiges */ else { TALK( "Error: Unknown Parameter: " << Buffer ); result = 2; } Buffer = strtok( NULL, "=" ); } else result = 1; } if (result == 0) delete[] Input; LEAVE( "GetHTTPRequestTemp, result=" << result ); return result; } //##################################################################################################### #include "server/createinitmdd.hh" r_OId RasServerEntry::createCollection(const char* collName, const char* collTypeName) { FastCollectionCreator fcc(collName, collTypeName); return fcc.createCollection(); } r_OId RasServerEntry::createMDD(const char* collName, const char* mddTypeName, const char* definitionDomain, const char* tileDomain, bool rcindex) { FastMDDCreator fc; fc.setCollectionName(collName); fc.setMDDTypeName(mddTypeName); if(rcindex) return fc.createRCxMDD(definitionDomain, tileDomain); return fc.createMDD(definitionDomain); } void RasServerEntry::extendMDD(r_OId mddOId, const char *stripeDomain, const char* tileDomain) { FastMDDCreator fc; fc.addStripe(mddOId, stripeDomain, tileDomain); } vector RasServerEntry::getTileDomains(r_OId mddOId, const char *stripeDomain) { FastMDDCreator fc; return fc.getTileDomains(mddOId, stripeDomain); }