git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@509 0109f412-320b-0410-ab79-c3e0c5ffbbe6
5105 lines
91 KiB
C++
5105 lines
91 KiB
C++
//-------------------------------------------------------------------------
|
|
// Desc: FLAIM server functions
|
|
// Tabs: 3
|
|
//
|
|
// Copyright (c) 1998-2006 Novell, Inc. All Rights Reserved.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of version 2 of the GNU General Public
|
|
// License as published by the Free Software Foundation.
|
|
//
|
|
// This program 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 this program; if not, contact Novell, Inc.
|
|
//
|
|
// To contact Novell about this file by physical or electronic mail,
|
|
// you may find current contact information at www.novell.com
|
|
//
|
|
// $Id$
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "flaimsys.h"
|
|
|
|
FSTATIC RCODE fsvIteratorParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool);
|
|
|
|
FSTATIC RCODE fsvIteratorWhereParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool);
|
|
|
|
FSTATIC RCODE fsvIteratorFromParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool);
|
|
|
|
FSTATIC RCODE fsvIteratorSelectParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool);
|
|
|
|
FSTATIC RCODE fsvDbGetBlocks(
|
|
HFDB hDb,
|
|
FLMUINT uiAddress,
|
|
FLMUINT uiMinTransId,
|
|
FLMUINT * puiCount,
|
|
FLMUINT * puiBlocksExamined,
|
|
FLMUINT * puiNextBlkAddr,
|
|
FLMUINT uiFlags,
|
|
F_Pool * pPool,
|
|
FLMBYTE ** ppBlocks,
|
|
FLMUINT * puiBytes);
|
|
|
|
FSTATIC RCODE fsvGetHandles(
|
|
FSV_WIRE * pWire);
|
|
|
|
FSV_SCTX * gv_pGlobalContext = NULL;
|
|
|
|
/****************************************************************************
|
|
Desc: Initializes the server's global context.
|
|
****************************************************************************/
|
|
RCODE fsvInitGlobalContext(
|
|
FLMUINT uiMaxSessions,
|
|
const char * pszServerBasePath,
|
|
FSV_LOG_FUNC pLogFunc)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FSV_SCTX * pTmpContext = NULL;
|
|
|
|
if (gv_pGlobalContext)
|
|
{
|
|
|
|
// Context already initialized
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
if ((pTmpContext = f_new FSV_SCTX) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pTmpContext->Setup( uiMaxSessions, pszServerBasePath,
|
|
pLogFunc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (pTmpContext)
|
|
{
|
|
pTmpContext->Release();
|
|
}
|
|
}
|
|
else if (pTmpContext)
|
|
{
|
|
gv_pGlobalContext = pTmpContext;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Frees any resources allocated to the global context.
|
|
****************************************************************************/
|
|
void fsvFreeGlobalContext(void)
|
|
{
|
|
if (gv_pGlobalContext)
|
|
{
|
|
gv_pGlobalContext->Release();
|
|
gv_pGlobalContext = NULL;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Sets the server's base (relative) path
|
|
****************************************************************************/
|
|
RCODE fsvSetBasePath(
|
|
const char * pszServerBasePath)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
if (!gv_pGlobalContext)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = gv_pGlobalContext->SetBasePath( pszServerBasePath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Sets the server's temporary directory
|
|
****************************************************************************/
|
|
RCODE fsvSetTempDir(
|
|
const char * pszTempDir)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
if (!gv_pGlobalContext)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = gv_pGlobalContext->SetTempDir( pszTempDir)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Returns a pointer to the server's global context object.
|
|
****************************************************************************/
|
|
RCODE fsvGetGlobalContext(
|
|
FSV_SCTX ** ppGlobalContext)
|
|
{
|
|
*ppGlobalContext = gv_pGlobalContext;
|
|
return (FERR_OK);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: This is the function that processes FLAIM requests.
|
|
****************************************************************************/
|
|
RCODE fsvProcessRequest(
|
|
FCS_DIS * pDataIStream,
|
|
FCS_DOS * pDataOStream,
|
|
F_Pool * pScratchPool,
|
|
FLMUINT * puiSessionIdRV)
|
|
{
|
|
void * pvMark = NULL;
|
|
FSV_WIRE Wire(pDataIStream, pDataOStream);
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Set the temporary pool
|
|
|
|
if (pScratchPool)
|
|
{
|
|
pvMark = pScratchPool->poolMark();
|
|
Wire.setPool( pScratchPool);
|
|
}
|
|
|
|
// Read the request
|
|
|
|
if (RC_BAD( rc = Wire.read()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Close the input stream.
|
|
|
|
pDataIStream->close();
|
|
Wire.setDIStream( NULL);
|
|
|
|
// Get any required handles.
|
|
|
|
if (RC_BAD( rc = fsvGetHandles( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Call the appropriate handler function.
|
|
|
|
switch (Wire.getClass())
|
|
{
|
|
case FCS_OPCLASS_GLOBAL:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassGlobal( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_SESSION:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassSession( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_DATABASE:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassDatabase( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_TRANS:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassTransaction( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_RECORD:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassRecord( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_ITERATOR:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassIterator( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_BLOB:
|
|
{
|
|
rc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_DIAG:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassDiag( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_FILE:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassFile( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_ADMIN:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassAdmin( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_INDEX:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassIndex( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OPCLASS_MISC:
|
|
{
|
|
if (RC_BAD( rc = fsvOpClassMisc( &Wire)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (puiSessionIdRV)
|
|
{
|
|
|
|
// Set the session ID so that the calling routine has the option of
|
|
// performing cleanup on an error
|
|
|
|
*puiSessionIdRV = Wire.getSessionId();
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
|
|
// If the input stream is still open, the handler never send any
|
|
// data to the client. Close the input stream and try to send the
|
|
// error code to the client.
|
|
|
|
if (pDataIStream->isOpen())
|
|
{
|
|
(void) pDataIStream->close();
|
|
Wire.setDIStream( NULL);
|
|
}
|
|
|
|
if (RC_OK( Wire.sendOpcode( Wire.getClass(), Wire.getOp())))
|
|
{
|
|
if (RC_OK( Wire.sendRc( rc)))
|
|
{
|
|
if (RC_OK( Wire.sendTerminate()))
|
|
{
|
|
pDataOStream->close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDataOStream->close();
|
|
}
|
|
|
|
if (pScratchPool)
|
|
{
|
|
pScratchPool->poolReset( pvMark);
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a diagnostic operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassDiag(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Service the request.
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_DIAG_HTD_ECHO:
|
|
{
|
|
// Simply echo the record back to the client. This is done below
|
|
// when the response is sent to the client.
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_DIAG, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_DIAG_HTD_ECHO:
|
|
{
|
|
if (pWire->getRecord() != NULL)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendRecord( WIRE_VALUE_HTD,
|
|
pWire->getRecord())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a file system operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassFile(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
RCODE opRc = FERR_OK;
|
|
FSV_SCTX * pServerContext = NULL;
|
|
FLMUNICODE * puzSourcePath;
|
|
char szSourcePath[F_PATH_MAX_SIZE];
|
|
|
|
// Set up local variables.
|
|
|
|
if (RC_BAD( opRc = fsvGetGlobalContext( &pServerContext)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
puzSourcePath = pWire->getFilePath();
|
|
if (puzSourcePath)
|
|
{
|
|
|
|
// Convert the UNICODE URL to a server path.
|
|
|
|
if (RC_BAD( rc = pServerContext->BuildFilePath( puzSourcePath,
|
|
szSourcePath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Service the request.
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_FILE_EXISTS:
|
|
{
|
|
if (!puzSourcePath)
|
|
{
|
|
opRc = RC_SET( FERR_SYNTAX);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (RC_BAD( opRc = gv_FlmSysData.pFileSystem->doesFileExist(
|
|
szSourcePath)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_FILE_DELETE:
|
|
{
|
|
if (!puzSourcePath)
|
|
{
|
|
opRc = RC_SET( FERR_SYNTAX);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (RC_BAD( opRc = gv_FlmSysData.pFileSystem->deleteFile(
|
|
szSourcePath)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_FILE, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs an administrative operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassAdmin(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_ADMIN, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a global operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassGlobal(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
FSV_SCTX * pServerContext;
|
|
NODE * pTree = NULL;
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Service the request.
|
|
|
|
if (RC_BAD( rc = fsvGetGlobalContext( &pServerContext)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_GLOBAL_STATS_START:
|
|
{
|
|
if (RC_BAD( opRc = FlmConfig( FLM_START_STATS, 0, 0)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GLOBAL_STATS_STOP:
|
|
{
|
|
if (RC_BAD( opRc = FlmConfig( FLM_STOP_STATS, 0, 0)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GLOBAL_STATS_RESET:
|
|
{
|
|
if (RC_BAD( opRc = FlmConfig( FLM_RESET_STATS, 0, 0)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GLOBAL_MEM_INFO_GET:
|
|
{
|
|
FLM_MEM_INFO memInfo;
|
|
|
|
FlmGetMemoryInfo( &memInfo);
|
|
if (RC_BAD( opRc = fcsBuildMemInfo( &memInfo,
|
|
pWire->getPool(), &pTree)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GLOBAL_GET_THREAD_INFO:
|
|
{
|
|
if (RC_BAD( opRc = fcsBuildThreadInfo( pWire->getPool(), &pTree)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_GLOBAL, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
if (pTree)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendHTD( WIRE_VALUE_HTD, pTree)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a session operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassSession(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
FLMUINT uiSessionIdRV;
|
|
FSV_SCTX * pServerContext;
|
|
FSV_SESN * pSession = NULL;
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Service the request.
|
|
|
|
if (RC_BAD( opRc = fsvGetGlobalContext( &pServerContext)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_SESSION_OPEN:
|
|
{
|
|
// Create a new session.
|
|
|
|
if (RC_BAD( opRc = pServerContext->OpenSession(
|
|
pWire->getClientVersion(), pWire->getFlags(),
|
|
&uiSessionIdRV, &pSession)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_SESSION_CLOSE:
|
|
{
|
|
// Close the session.
|
|
|
|
if (RC_BAD( opRc = pServerContext->CloseSession( pWire->getSessionId())))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_SESSION, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
if (pWire->getOp() == FCS_OP_SESSION_OPEN)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_SESSION_ID,
|
|
uiSessionIdRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_SESSION_COOKIE,
|
|
pSession->getCookie())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_FLAGS,
|
|
FCS_SESSION_GEDCOM_SUPPORT)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_FLAIM_VERSION,
|
|
FLM_CUR_FILE_FORMAT_VER_NUM)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a record or DRN operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassRecord(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
FSV_SESN * pSession;
|
|
HFDB hDb;
|
|
FLMUINT uiContainer;
|
|
FLMUINT uiIndex;
|
|
FLMUINT uiAutoTrans;
|
|
FLMUINT uiDrn;
|
|
FLMUINT uiFlags;
|
|
FlmRecord * pRecord = NULL;
|
|
FlmRecord * pRecordRV = NULL;
|
|
FLMUINT uiDrnRV = 0;
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Get a pointer to the session object.
|
|
|
|
if ((pSession = pWire->getSession()) == NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
// Get the database handle. This is needed by all of the record
|
|
// operations.
|
|
|
|
if ((hDb = (HFDB) pWire->getFDB()) == HFDB_NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
// Initialize local variables.
|
|
|
|
uiContainer = pWire->getContainerId();
|
|
uiIndex = pWire->getIndexId();
|
|
uiDrn = pWire->getDrn();
|
|
uiAutoTrans = pWire->getAutoTrans();
|
|
uiFlags = pWire->getFlags();
|
|
pRecord = pWire->getRecord();
|
|
|
|
// Perform the operation.
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_RECORD_RETRIEVE:
|
|
{
|
|
if (!uiFlags)
|
|
{
|
|
uiFlags = FO_EXACT;
|
|
}
|
|
|
|
if (pWire->getBoolean())
|
|
{
|
|
|
|
// Fetch the record
|
|
|
|
if (RC_BAD( opRc = FlmRecordRetrieve( hDb, uiContainer, uiDrn,
|
|
uiFlags, &pRecordRV, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Just get the DRN
|
|
|
|
if (RC_BAD( opRc = FlmRecordRetrieve( hDb, uiContainer, uiDrn,
|
|
uiFlags, NULL, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_RECORD_ADD:
|
|
{
|
|
uiDrnRV = uiDrn;
|
|
if (RC_BAD( opRc = FlmRecordAdd( hDb, uiContainer, &uiDrnRV, pRecord,
|
|
uiAutoTrans)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_RECORD_MODIFY:
|
|
{
|
|
if (RC_BAD( opRc = FlmRecordModify( hDb, uiContainer, uiDrn, pRecord,
|
|
uiAutoTrans)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_RECORD_DELETE:
|
|
{
|
|
if (RC_BAD( opRc = FlmRecordDelete( hDb, uiContainer, uiDrn,
|
|
uiAutoTrans)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_RESERVE_NEXT_DRN:
|
|
{
|
|
uiDrnRV = uiDrn;
|
|
if (RC_BAD( opRc = FlmReserveNextDrn( hDb, uiContainer, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_KEY_RETRIEVE:
|
|
{
|
|
if (pSession->getClientVersion() >= FCS_VERSION_1_1_1)
|
|
{
|
|
if (RC_BAD( opRc = FlmKeyRetrieve( hDb, uiIndex, uiContainer,
|
|
pRecord, uiDrn, uiFlags, &pRecordRV, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FLMUINT uiKeyContainer = 0;
|
|
|
|
if (pRecord)
|
|
{
|
|
uiKeyContainer = pRecord->getContainerID();
|
|
}
|
|
|
|
// Older clients sent index # in the container tag.
|
|
|
|
if (RC_BAD( opRc = FlmKeyRetrieve( hDb, uiContainer, uiKeyContainer,
|
|
pRecord, uiDrn, uiFlags, &pRecordRV, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_RECORD, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
if (pRecordRV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendRecord( WIRE_VALUE_RECORD, pRecordRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (uiDrnRV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_DRN, uiDrnRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pRecordRV)
|
|
{
|
|
pRecordRV->Release();
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a database operation.
|
|
****************************************************************************/
|
|
RCODE fsvOpClassDatabase(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
RCODE opRc = FERR_OK;
|
|
FSV_SESN * pSession;
|
|
HFDB hDb = HFDB_NULL;
|
|
CREATE_OPTS CreateOptsRV;
|
|
FLMUINT uiBlockCountRV = 0;
|
|
FLMUINT uiBlocksExaminedRV = 0;
|
|
FLMUINT uiBlockAddrRV = 0;
|
|
FLMUINT uiTransIdRV;
|
|
FLMUINT64 ui64NumValue1RV = 0;
|
|
FLMUINT64 ui64NumValue2RV = 0;
|
|
FLMUINT64 ui64NumValue3RV = 0;
|
|
FLMBOOL bBoolValueRV = FALSE;
|
|
FLMUINT uiItemIdRV = 0;
|
|
char szItemName[64];
|
|
NODE * pHTDRV = NULL;
|
|
char szPathRV[F_PATH_MAX_SIZE];
|
|
F_NameTable nameTable;
|
|
FLMBOOL bHaveCreateOptsVal = FALSE;
|
|
FLMBOOL bHavePathValue = FALSE;
|
|
FLMBYTE * pBinary = NULL;
|
|
FLMUINT uiBinSize = 0;
|
|
|
|
szItemName[0] = 0;
|
|
|
|
if ((pSession = pWire->getSession()) == NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (pWire->getOp() != FCS_OP_DATABASE_OPEN &&
|
|
pWire->getOp() != FCS_OP_DATABASE_CREATE)
|
|
{
|
|
|
|
// Get the database handle for all database operations other than
|
|
// open and create.
|
|
|
|
if ((hDb = (HFDB) pWire->getFDB()) == HFDB_NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_DATABASE_OPEN:
|
|
{
|
|
if (RC_BAD( opRc = pSession->OpenDatabase( pWire->getFilePath(),
|
|
pWire->getFilePath3(), pWire->getFilePath2(),
|
|
pWire->getFlags())))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_CREATE:
|
|
{
|
|
CREATE_OPTS createOpts;
|
|
pWire->copyCreateOpts( &createOpts);
|
|
|
|
if (RC_BAD( opRc = pSession->CreateDatabase( pWire->getFilePath(),
|
|
pWire->getFilePath3(), pWire->getFilePath2(),
|
|
pWire->getDictPath(), pWire->getDictBuffer(), &createOpts)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_CLOSE:
|
|
{
|
|
if (RC_BAD( opRc = pSession->CloseDatabase()))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DB_REDUCE_SIZE:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbReduceSize( hDb, (FLMUINT) pWire->getCount(),
|
|
&uiBlockCountRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_ITEM_NAME:
|
|
{
|
|
if (RC_BAD( opRc = FlmGetItemName( hDb, pWire->getItemId(),
|
|
sizeof(szItemName), szItemName)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_NAME_TABLE:
|
|
{
|
|
if (RC_BAD( rc = nameTable.setupFromDb( hDb)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_COMMIT_CNT:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbGetCommitCnt( hDb, &uiBlockCountRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_TRANS_ID:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbGetTransId( hDb, &uiTransIdRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_GET_CONFIG:
|
|
{
|
|
switch ((eDbGetConfigType) pWire->getType())
|
|
{
|
|
case FDB_GET_VERSION:
|
|
{
|
|
// Doing via create opts to maintain backward compatibility.
|
|
|
|
f_memset( &CreateOptsRV, 0, sizeof(CreateOptsRV));
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_VERSION,
|
|
(void *) &CreateOptsRV.uiVersionNum)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
bHaveCreateOptsVal = TRUE;
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_BLKSIZ:
|
|
{
|
|
// Doing via create opts to maintain backward compatibility.
|
|
|
|
f_memset( &CreateOptsRV, 0, sizeof(CreateOptsRV));
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_BLKSIZ,
|
|
(void *) &CreateOptsRV.uiBlockSize)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
bHaveCreateOptsVal = TRUE;
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_DEFAULT_LANG:
|
|
{
|
|
// Doing via create opts to maintain backward compatibility.
|
|
|
|
f_memset( &CreateOptsRV, 0, sizeof(CreateOptsRV));
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_DEFAULT_LANG,
|
|
(void *) &CreateOptsRV.uiDefaultLanguage)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
bHaveCreateOptsVal = TRUE;
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_TRANS_ID:
|
|
case FDB_GET_RFL_FILE_NUM:
|
|
case FDB_GET_RFL_HIGHEST_NU:
|
|
case FDB_GET_LAST_BACKUP_TRANS_ID:
|
|
case FDB_GET_BLOCKS_CHANGED_SINCE_BACKUP:
|
|
case FDB_GET_FILE_EXTEND_SIZE:
|
|
case FDB_GET_APP_DATA:
|
|
{
|
|
FLMUINT uiTmpValue;
|
|
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb,
|
|
(eDbGetConfigType) pWire->getType(),
|
|
(void *) &uiTmpValue)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
ui64NumValue1RV = (FLMUINT64) uiTmpValue;
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_RFL_FILE_SIZE_LIMITS:
|
|
{
|
|
FLMUINT uiTmpValue1;
|
|
FLMUINT uiTmpValue2;
|
|
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb,
|
|
FDB_GET_RFL_FILE_SIZE_LIMITS,
|
|
(void *) &uiTmpValue1,
|
|
(void *) &uiTmpValue2)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
ui64NumValue1RV = (FLMUINT64) uiTmpValue1;
|
|
ui64NumValue2RV = (FLMUINT64) uiTmpValue2;
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_RFL_KEEP_FLAG:
|
|
case FDB_GET_AUTO_TURN_OFF_KEEP_RFL_FLAG:
|
|
case FDB_GET_KEEP_ABORTED_TRANS_IN_RFL_FLAG:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb,
|
|
(eDbGetConfigType) pWire->getType(),
|
|
(void *) &bBoolValueRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_PATH:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_PATH,
|
|
(void *) szPathRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
bHavePathValue = TRUE;
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_CHECKPOINT_INFO:
|
|
{
|
|
CHECKPOINT_INFO checkpointInfo;
|
|
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb,
|
|
FDB_GET_CHECKPOINT_INFO, (void *) &checkpointInfo)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (RC_BAD( opRc = fcsBuildCheckpointInfo( &checkpointInfo,
|
|
pWire->getPool(), &pHTDRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_LOCK_HOLDER:
|
|
{
|
|
F_LOCK_USER lockUser;
|
|
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_LOCK_HOLDER,
|
|
(void *) &lockUser)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (RC_BAD( opRc = fcsBuildLockUser( &lockUser, FALSE,
|
|
pWire->getPool(), &pHTDRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_LOCK_WAITERS:
|
|
{
|
|
F_LOCK_USER * pLockUser = NULL;
|
|
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_LOCK_WAITERS,
|
|
(void *) &pLockUser)))
|
|
{
|
|
if (pLockUser)
|
|
{
|
|
f_free( &pLockUser);
|
|
}
|
|
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (RC_BAD( opRc = fcsBuildLockUser( pLockUser, TRUE,
|
|
pWire->getPool(), &pHTDRV)))
|
|
{
|
|
if (pLockUser)
|
|
{
|
|
f_free( &pLockUser);
|
|
}
|
|
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (pLockUser)
|
|
{
|
|
f_free( &pLockUser);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_RFL_DIR:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_RFL_DIR,
|
|
(void *) szPathRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
bHavePathValue = TRUE;
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_SERIAL_NUMBER:
|
|
{
|
|
uiBinSize = F_SERIAL_NUM_SIZE;
|
|
|
|
if( RC_BAD( opRc = pWire->getPool()->poolAlloc(
|
|
uiBinSize, (void **)&pBinary)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb,
|
|
FDB_GET_SERIAL_NUMBER, (void *) pBinary)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FDB_GET_SIZES:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbGetConfig( hDb, FDB_GET_SIZES,
|
|
(void *) &ui64NumValue1RV,
|
|
(void *) &ui64NumValue2RV,
|
|
(void *) &ui64NumValue3RV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_CONFIG:
|
|
{
|
|
switch ((eDbConfigType) pWire->getType())
|
|
{
|
|
case FDB_SET_APP_VERSION:
|
|
case FDB_RFL_KEEP_FILES:
|
|
case FDB_RFL_ROLL_TO_NEXT_FILE:
|
|
case FDB_KEEP_ABORTED_TRANS_IN_RFL:
|
|
case FDB_AUTO_TURN_OFF_KEEP_RFL:
|
|
case FDB_SET_APP_DATA:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbConfig( hDb,
|
|
(eDbConfigType) pWire->getType(),
|
|
(void *) ((FLMUINT) pWire->getNumber2()),
|
|
(void *) ((FLMUINT) pWire->getNumber3()))))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FDB_RFL_FILE_LIMITS:
|
|
case FDB_FILE_EXTEND_SIZE:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbConfig( hDb,
|
|
(eDbConfigType) pWire->getType(),
|
|
(void *) ((FLMUINT) pWire->getNumber1()),
|
|
(void *) ((FLMUINT) pWire->getNumber2()))))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FDB_RFL_DIR:
|
|
{
|
|
char * pszPath;
|
|
F_Pool * pPool = pWire->getPool();
|
|
void * pvMark = pPool->poolMark();
|
|
|
|
if (RC_BAD( rc = fcsConvertUnicodeToNative( pPool,
|
|
pWire->getFilePath(), &pszPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( opRc = FlmDbConfig( hDb,
|
|
(eDbConfigType) pWire->getType(),
|
|
(void *) pszPath,
|
|
(void *) ((FLMUINT) pWire->getNumber3()))))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
pPool->poolReset( pvMark);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_LOCK:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbLock( hDb,
|
|
(eLockType) (FLMUINT) pWire->getNumber1(),
|
|
(FLMINT) pWire->getSignedValue(),
|
|
(FLMUINT) pWire->getFlags())))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_UNLOCK:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbUnlock( hDb)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_GET_BLOCK:
|
|
{
|
|
uiBlockCountRV = (FLMUINT) pWire->getCount();
|
|
if (RC_BAD( opRc = fsvDbGetBlocks( hDb, pWire->getAddress(),
|
|
pWire->getTransId(), &uiBlockCountRV, &uiBlocksExaminedRV,
|
|
&uiBlockAddrRV, pWire->getFlags(), pWire->getPool(),
|
|
&pBinary, &uiBinSize)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_CHECKPOINT:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbCheckpoint( hDb, pWire->getFlags())))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DB_SET_BACKUP_FLAG:
|
|
{
|
|
FLMBOOL bNewState = pWire->getBoolean();
|
|
|
|
if (!IsInCSMode( hDb))
|
|
{
|
|
FDB * pDb = (FDB *) hDb;
|
|
|
|
f_mutexLock( gv_FlmSysData.hShareMutex);
|
|
if (pDb->pFile->bBackupActive && bNewState)
|
|
{
|
|
f_mutexUnlock( gv_FlmSysData.hShareMutex);
|
|
opRc = RC_SET( FERR_BACKUP_ACTIVE);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
pDb->pFile->bBackupActive = bNewState;
|
|
f_mutexUnlock( gv_FlmSysData.hShareMutex);
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( opRc = fcsSetBackupActiveFlag( hDb, bNewState)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_DATABASE, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_DB_REDUCE_SIZE:
|
|
case FCS_OP_GET_COMMIT_CNT:
|
|
{
|
|
|
|
// Return a count
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_COUNT, uiBlockCountRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_NAME_TABLE:
|
|
{
|
|
|
|
// Return the name table.
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNameTable( WIRE_VALUE_NAME_TABLE,
|
|
&nameTable)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_ITEM_NAME:
|
|
{
|
|
FLMUNICODE * puzItemNameRV;
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
if (szItemName[0])
|
|
{
|
|
if (RC_BAD( rc = fcsConvertNativeToUnicode( pWire->getPool(),
|
|
szItemName, &puzItemNameRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendString( WIRE_VALUE_ITEM_NAME,
|
|
puzItemNameRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_ITEM_ID:
|
|
{
|
|
if (uiItemIdRV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_ITEM_ID, uiItemIdRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_GET_TRANS_ID:
|
|
{
|
|
|
|
// Return the transaction id for the database.
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_TRANSACTION_ID,
|
|
uiTransIdRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_GET_BLOCK:
|
|
{
|
|
|
|
// Return the requested block
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_COUNT, uiBlockCountRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_NUMBER2,
|
|
uiBlocksExaminedRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_ADDRESS, uiBlockAddrRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (uiBlockCountRV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendBinary( WIRE_VALUE_BLOCK, pBinary,
|
|
uiBinSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_DATABASE_GET_CONFIG:
|
|
{
|
|
switch (pWire->getType())
|
|
{
|
|
case FDB_GET_SERIAL_NUMBER:
|
|
if (RC_BAD( rc = pWire->sendBinary( WIRE_VALUE_SERIAL_NUM, pBinary,
|
|
uiBinSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bHaveCreateOptsVal)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendCreateOpts( WIRE_VALUE_CREATE_OPTS,
|
|
&CreateOptsRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (ui64NumValue1RV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_NUMBER1, ui64NumValue1RV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (ui64NumValue2RV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_NUMBER2, ui64NumValue2RV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (ui64NumValue3RV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_NUMBER3, ui64NumValue3RV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (bBoolValueRV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_BOOLEAN, bBoolValueRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (bHavePathValue)
|
|
{
|
|
FLMUNICODE * puzPath;
|
|
|
|
if (RC_BAD( rc = fcsConvertNativeToUnicode( pWire->getPool(), szPathRV,
|
|
&puzPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendString( WIRE_VALUE_FILE_PATH, puzPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (pHTDRV)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendHTD( WIRE_VALUE_HTD, pHTDRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs an iterator (cursor) operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassIterator(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
RCODE opRc = FERR_OK;
|
|
FSV_SESN * pSession = NULL;
|
|
HFCURSOR hIterator = HFCURSOR_NULL;
|
|
FLMBOOL bDoDrnOp = FALSE;
|
|
FlmRecord * pRecordRV = NULL;
|
|
FlmRecord * pTmpRecord = NULL;
|
|
FLMUINT uiIteratorIdRV = FCS_INVALID_ID;
|
|
FLMUINT uiCountRV = 0;
|
|
FLMUINT uiDrnRV = 0;
|
|
FLMBOOL bFlag = FALSE;
|
|
|
|
// Get a pointer to the session object.
|
|
|
|
if ((pSession = pWire->getSession()) == NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
// Get the iterator handle.
|
|
|
|
if ((hIterator = pWire->getIteratorHandle()) == HFDB_NULL)
|
|
{
|
|
if (pWire->getOp() != FCS_OP_ITERATOR_INIT)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
// Examine the wire flags for the operation.
|
|
|
|
bDoDrnOp = (FLMBOOL)
|
|
(
|
|
(pWire->getFlags() & FCS_ITERATOR_DRN_FLAG) ? (FLMBOOL) TRUE :
|
|
(FLMBOOL) FALSE
|
|
);
|
|
|
|
// Perform the requested operation.
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_ITERATOR_INIT:
|
|
{
|
|
// Build the query.
|
|
|
|
if (RC_BAD( opRc = fsvIteratorParse( pWire, pWire->getPool())))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
uiIteratorIdRV = pWire->getIteratorId();
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_ITERATOR_FREE:
|
|
{
|
|
// Free the iterator.
|
|
|
|
if (RC_BAD( opRc = pSession->FreeIterator( pWire->getIteratorId())))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_ITERATOR_FIRST:
|
|
{
|
|
// Retrieve the first record (or DRN) in the result set.
|
|
|
|
if (bDoDrnOp)
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorFirstDRN( hIterator, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorFirst( hIterator, &pRecordRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_ITERATOR_LAST:
|
|
{
|
|
// Retrieve the last record (or DRN) in the result set.
|
|
|
|
if (bDoDrnOp)
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorLastDRN( hIterator, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorLast( hIterator, &pRecordRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_ITERATOR_NEXT:
|
|
{
|
|
// Retrieve the next record (or DRN) in the result set.
|
|
|
|
if (bDoDrnOp)
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorNextDRN( hIterator, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorNext( hIterator, &pRecordRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_ITERATOR_PREV:
|
|
{
|
|
// Retrieve the previous record (or DRN) in the result set.
|
|
|
|
if (bDoDrnOp)
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorPrevDRN( hIterator, &uiDrnRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorPrev( hIterator, &pRecordRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_ITERATOR_COUNT:
|
|
{
|
|
// Count the number of records in the result set.
|
|
|
|
if (RC_BAD( opRc = FlmCursorRecCount( hIterator, &uiCountRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_ITERATOR_TEST_REC:
|
|
{
|
|
if ((pTmpRecord = pWire->getRecord()) != NULL)
|
|
{
|
|
pTmpRecord->AddRef();
|
|
|
|
if (RC_BAD( opRc = FlmCursorTestRec( hIterator, pTmpRecord, &bFlag)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
pTmpRecord->Release();
|
|
pTmpRecord = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (RC_BAD( opRc = FlmCursorTestDRN( hIterator, pWire->getDrn(),
|
|
&bFlag)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_ITERATOR, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
if (pRecordRV)
|
|
{
|
|
|
|
// Send the retrieved record.
|
|
|
|
if (RC_BAD( rc = pWire->sendRecord( WIRE_VALUE_RECORD, pRecordRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (uiDrnRV)
|
|
{
|
|
|
|
// Send the record's DRN.
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_DRN, uiDrnRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (uiCountRV)
|
|
{
|
|
|
|
// Send the record count.
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_RECORD_COUNT, uiCountRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (uiIteratorIdRV != FCS_INVALID_ID)
|
|
{
|
|
|
|
// Send the iterator's ID.
|
|
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_ITERATOR_ID,
|
|
uiIteratorIdRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (bFlag)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_BOOLEAN, bFlag)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pRecordRV)
|
|
{
|
|
pRecordRV->Release();
|
|
}
|
|
|
|
if (pTmpRecord)
|
|
{
|
|
pTmpRecord->Release();
|
|
pTmpRecord = NULL;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a transaction operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassTransaction(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
RCODE opRc = FERR_OK;
|
|
FSV_SESN * pSession;
|
|
HFDB hDb;
|
|
FLMUINT uiTransTypeRV;
|
|
FLMBYTE * pBlock = NULL;
|
|
FLMUINT uiBlockSize = 0;
|
|
FLMUINT uiFlmTransFlags = 0;
|
|
|
|
// Get a pointer to the session object.
|
|
|
|
if ((pSession = pWire->getSession()) == NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
// Get a handle to the database in case this is a database transaction
|
|
// operation
|
|
|
|
hDb = (HFDB) pWire->getFDB();
|
|
|
|
// Perform the requested operation.
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_TRANSACTION_BEGIN:
|
|
{
|
|
// Start a database transaction.
|
|
|
|
if (pWire->getFlags() & FCS_TRANS_FLAG_GET_HEADER)
|
|
{
|
|
uiBlockSize = 2048;
|
|
|
|
if( RC_BAD( rc = pWire->getPool()->poolAlloc( uiBlockSize,
|
|
(void **)&pBlock)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
if (pWire->getFlags() & FCS_TRANS_FLAG_DONT_KILL)
|
|
{
|
|
uiFlmTransFlags |= FLM_DONT_KILL_TRANS;
|
|
}
|
|
|
|
if (pWire->getFlags() & FCS_TRANS_FLAG_DONT_POISON)
|
|
{
|
|
uiFlmTransFlags |= FLM_DONT_POISON_CACHE;
|
|
}
|
|
|
|
if (RC_BAD( opRc = FlmDbTransBegin( hDb,
|
|
pWire->getTransType() | uiFlmTransFlags,
|
|
pWire->getMaxLockWait(), pBlock)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_TRANSACTION_COMMIT:
|
|
{
|
|
// Commit a database transaction.
|
|
|
|
if (RC_BAD( opRc = FlmDbTransCommit( hDb)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_TRANSACTION_COMMIT_EX:
|
|
{
|
|
// Commit a database transaction.
|
|
|
|
if (RC_BAD( opRc = fsvDbTransCommitEx( hDb, pWire)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_TRANSACTION_ABORT:
|
|
{
|
|
// Abort a database transaction.
|
|
|
|
if (RC_BAD( opRc = FlmDbTransAbort( hDb)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_TRANSACTION_GET_TYPE:
|
|
{
|
|
// Get the database transaction type.
|
|
|
|
if (RC_BAD( opRc = FlmDbGetTransType( hDb, &uiTransTypeRV)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_TRANS, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (pBlock)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendBinary( WIRE_VALUE_BLOCK,
|
|
pBlock, uiBlockSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_TRANSACTION_GET_TYPE:
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_TRANSACTION_TYPE,
|
|
uiTransTypeRV)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a maintenance operation.
|
|
****************************************************************************/
|
|
RCODE fsvOpClassMaintenance(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
FSV_SESN * pSession;
|
|
HFDB hDb;
|
|
F_Pool pool;
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Initialize a temporary pool.
|
|
|
|
pool.poolInit( 1024);
|
|
|
|
// Service the request.
|
|
|
|
if ((pSession = pWire->getSession()) == NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
if ((hDb = (HFDB) pWire->getFDB()) == HFDB_NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_CHECK:
|
|
{
|
|
if (RC_BAD( opRc = FlmDbCheck( hDb, NULL, NULL, NULL,
|
|
pWire->getFlags(), &pool, NULL, NULL, 0)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_MAINTENANCE, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_CHECK:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs an index operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassIndex(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
HFDB hDb = HFDB_NULL;
|
|
FLMUINT uiIndex;
|
|
FINDEX_STATUS indexStatus;
|
|
F_Pool * pTmpPool = pWire->getPool();
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Get the database handle. This is needed by all of the index
|
|
// operations.
|
|
|
|
if ((hDb = (HFDB) pWire->getFDB()) == HFDB_NULL)
|
|
{
|
|
opRc = RC_SET( FERR_BAD_HDL);
|
|
goto OP_EXIT;
|
|
}
|
|
|
|
// Initialize local variables.
|
|
|
|
uiIndex = pWire->getIndexId();
|
|
|
|
// Service the request.
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_INDEX_GET_STATUS:
|
|
{
|
|
if (RC_BAD( opRc = FlmIndexStatus( hDb, uiIndex, &indexStatus)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_INDEX_GET_NEXT:
|
|
{
|
|
if (RC_BAD( opRc = FlmIndexGetNext( hDb, &uiIndex)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_INDEX_SUSPEND:
|
|
{
|
|
if (RC_BAD( opRc = FlmIndexSuspend( hDb, uiIndex)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_INDEX_RESUME:
|
|
{
|
|
if (RC_BAD( opRc = FlmIndexResume( hDb, uiIndex)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_INDEX, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_INDEX_GET_STATUS:
|
|
{
|
|
NODE * pStatusTree;
|
|
|
|
if (RC_BAD( fcsBuildIndexStatus( &indexStatus, pTmpPool,
|
|
&pStatusTree)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendHTD( WIRE_VALUE_HTD, pStatusTree)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_OP_INDEX_GET_NEXT:
|
|
{
|
|
if (RC_BAD( rc = pWire->sendNumber( WIRE_VALUE_INDEX_ID, uiIndex)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Performs a misc. operation
|
|
****************************************************************************/
|
|
RCODE fsvOpClassMisc(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
FLMBYTE ucSerialNum[F_SERIAL_NUM_SIZE];
|
|
RCODE opRc = FERR_OK;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Service the request.
|
|
|
|
switch (pWire->getOp())
|
|
{
|
|
case FCS_OP_CREATE_SERIAL_NUM:
|
|
{
|
|
if (RC_BAD( opRc = f_createSerialNumber( ucSerialNum)))
|
|
{
|
|
goto OP_EXIT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
opRc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto OP_EXIT;
|
|
}
|
|
}
|
|
|
|
OP_EXIT:
|
|
|
|
// Send the server's response.
|
|
|
|
if (RC_BAD( rc = pWire->sendOpcode( FCS_OPCLASS_MISC, pWire->getOp())))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendRc( opRc)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_OK( opRc))
|
|
{
|
|
if (pWire->getOp() == FCS_OP_CREATE_SERIAL_NUM)
|
|
{
|
|
if (RC_BAD( rc = pWire->sendBinary( WIRE_VALUE_SERIAL_NUM, ucSerialNum,
|
|
F_SERIAL_NUM_SIZE)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
flmAssert( rc == FERR_NOT_IMPLEMENTED);
|
|
}
|
|
}
|
|
|
|
if (RC_BAD( rc = pWire->sendTerminate()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Configures an iterator based on from, where, select, and config
|
|
clauses provided by the client.
|
|
****************************************************************************/
|
|
FSTATIC RCODE fsvIteratorParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Parse the "from" clause. This contains record source information.
|
|
|
|
if (pWire->getIteratorFrom())
|
|
{
|
|
if (RC_BAD( rc = fsvIteratorFromParse( pWire, pPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (pWire->getIteratorHandle() == HFCURSOR_NULL)
|
|
{
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
// Parse the "where" clause. This contains the criteria.
|
|
|
|
if (pWire->getIteratorWhere())
|
|
{
|
|
if (RC_BAD( rc = fsvIteratorWhereParse( pWire, pPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Parse the "select" clause. This contains customized view
|
|
// information.
|
|
|
|
if (pWire->getIteratorSelect())
|
|
{
|
|
if (RC_BAD( rc = fsvIteratorSelectParse( pWire, pPool)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Adds selection criteria to an iterator.
|
|
****************************************************************************/
|
|
FSTATIC RCODE fsvIteratorWhereParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool)
|
|
{
|
|
HFCURSOR hIterator = pWire->getIteratorHandle();
|
|
NODE * pWhere = pWire->getIteratorWhere();
|
|
NODE * pCurNode;
|
|
NODE * pTmpNode;
|
|
void * pPoolMark;
|
|
FLMUINT uiTag;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// If no "where" clause, jump to exit.
|
|
|
|
if (!pWhere)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Process each component of the "where" clause.
|
|
|
|
pCurNode = GedChild( pWhere);
|
|
while (pCurNode)
|
|
{
|
|
uiTag = GedTagNum( pCurNode);
|
|
switch (uiTag)
|
|
{
|
|
case FCS_ITERATOR_MODE:
|
|
{
|
|
FLMUINT uiFlags = 0;
|
|
|
|
// Set the iterator's mode flags
|
|
|
|
if (RC_BAD( rc = GedGetUINT( pCurNode, &uiFlags)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = FlmCursorSetMode( hIterator, uiFlags)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Add an attribute to the criteria.
|
|
|
|
case FCS_ITERATOR_ATTRIBUTE:
|
|
{
|
|
FLMUINT uiAttrId;
|
|
|
|
// Get the attribute ID.
|
|
|
|
if (RC_BAD( rc = GedGetUINT( pCurNode, &uiAttrId)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the attribute.
|
|
|
|
if (uiTag == FCS_ITERATOR_ATTRIBUTE)
|
|
{
|
|
if (RC_BAD( rc = FlmCursorAddField( hIterator, uiAttrId, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Sanity check.
|
|
|
|
flmAssert( 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Add an attribute path to the criteria.
|
|
|
|
case FCS_ITERATOR_ATTRIBUTE_PATH:
|
|
{
|
|
FLMUINT puiPath[FCS_ITERATOR_MAX_PATH + 1];
|
|
FLMUINT uiAttrId;
|
|
FLMUINT uiPathPos = 0;
|
|
FLMUINT uiStartLevel;
|
|
|
|
if ((pTmpNode = GedFind( GED_TREE, pCurNode,
|
|
FCS_ITERATOR_ATTRIBUTE, 1)) != NULL)
|
|
{
|
|
|
|
// Build the attribute path.
|
|
|
|
uiStartLevel = GedNodeLevel( pTmpNode);
|
|
while (pTmpNode && GedNodeLevel( pTmpNode) >= uiStartLevel)
|
|
{
|
|
if (GedNodeLevel( pTmpNode) == uiStartLevel &&
|
|
GedTagNum( pTmpNode) == FCS_ITERATOR_ATTRIBUTE)
|
|
{
|
|
if (RC_BAD( rc = GedGetUINT( pTmpNode, &uiAttrId)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
puiPath[uiPathPos++] = uiAttrId;
|
|
if (uiPathPos > FCS_ITERATOR_MAX_PATH)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
pTmpNode = pTmpNode->next;
|
|
}
|
|
|
|
puiPath[uiPathPos] = 0;
|
|
}
|
|
|
|
// Add the attribute path.
|
|
|
|
if (RC_BAD( rc = FlmCursorAddFieldPath( hIterator, puiPath, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Add a numeric value to the criteria.
|
|
|
|
case FCS_ITERATOR_NUMBER_VALUE:
|
|
case FCS_ITERATOR_REC_PTR_VALUE:
|
|
{
|
|
|
|
// To save conversion time, cheat to determine if the number
|
|
// is negative.
|
|
|
|
FLMBYTE * pucValue = (FLMBYTE *) GedValPtr( pCurNode);
|
|
FLMBOOL bNegative = ((*pucValue & 0xF0) == 0xB0)
|
|
? TRUE
|
|
: FALSE;
|
|
|
|
if (bNegative)
|
|
{
|
|
FLMINT32 i32Value;
|
|
|
|
if (uiTag == FCS_ITERATOR_REC_PTR_VALUE)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = GedGetINT32( pCurNode, &i32Value)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_INT32_VAL,
|
|
&i32Value, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FLMUINT32 ui32Value;
|
|
FLMUINT uiValue;
|
|
|
|
if (RC_BAD( rc = GedGetUINT32( pCurNode, &ui32Value)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (uiTag == FCS_ITERATOR_NUMBER_VALUE)
|
|
{
|
|
if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_UINT32_VAL,
|
|
&ui32Value, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else if (uiTag == FCS_ITERATOR_REC_PTR_VALUE)
|
|
{
|
|
uiValue = ui32Value;
|
|
if (RC_BAD( rc = FlmCursorAddValue( hIterator,
|
|
FLM_REC_PTR_VAL, &uiValue, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Sanity check.
|
|
|
|
flmAssert( 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Add a binary value to the criteria.
|
|
|
|
case FCS_ITERATOR_BINARY_VALUE:
|
|
{
|
|
FLMBYTE * pucValue = (FLMBYTE *) GedValPtr( pCurNode);
|
|
FLMUINT uiValLen = GedValLen( pCurNode);
|
|
|
|
if (GedValType( pCurNode) != FLM_BINARY_TYPE)
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_BINARY_VAL,
|
|
pucValue, uiValLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Add a UNICODE string value to the criteria.
|
|
|
|
case FCS_ITERATOR_UNICODE_VALUE:
|
|
{
|
|
FLMUINT uiLen;
|
|
FLMUNICODE * puzBuf;
|
|
|
|
// Mark the pool.
|
|
|
|
pPoolMark = pPool->poolMark();
|
|
|
|
// Determine the length of the string.
|
|
|
|
if (RC_BAD( rc = GedGetUNICODE( pCurNode, NULL, &uiLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate a temporary buffer.
|
|
|
|
uiLen += 2;
|
|
if( RC_BAD( rc = pPool->poolAlloc( uiLen, (void **)&puzBuf)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Extract the string and add it to the criteria.
|
|
|
|
if (RC_BAD( rc = GedGetUNICODE( pCurNode, puzBuf, &uiLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_UNICODE_VAL,
|
|
puzBuf, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pPool->poolReset( pPoolMark);
|
|
break;
|
|
}
|
|
|
|
// Add a NATIVE, WP60, or Word String value to the criteria.
|
|
|
|
case FCS_ITERATOR_NATIVE_VALUE:
|
|
case FCS_ITERATOR_WP60_VALUE:
|
|
case FCS_ITERATOR_WDSTR_VALUE:
|
|
{
|
|
FLMUINT uiLen;
|
|
FLMBYTE * pucBuf;
|
|
|
|
// Mark the pool.
|
|
|
|
pPoolMark = pPool->poolMark();
|
|
|
|
// Determine the length of the string.
|
|
|
|
if (uiTag == FCS_ITERATOR_NATIVE_VALUE)
|
|
{
|
|
if (RC_BAD( rc = GedGetNATIVE( pCurNode, NULL, &uiLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate a temporary buffer.
|
|
|
|
uiLen += 2;
|
|
if( RC_BAD( rc = pPool->poolAlloc( uiLen, (void **)&pucBuf)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Extract the string and add it to the criteria.
|
|
|
|
if (uiTag == FCS_ITERATOR_NATIVE_VALUE)
|
|
{
|
|
if (RC_BAD( rc = GedGetNATIVE( pCurNode, (char *) pucBuf,
|
|
&uiLen)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_STRING_VAL,
|
|
pucBuf, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
pPool->poolReset( pPoolMark);
|
|
break;
|
|
}
|
|
|
|
// Add a native (internal) text value
|
|
|
|
case FCS_ITERATOR_FLM_TEXT_VALUE:
|
|
{
|
|
if (RC_BAD( rc = FlmCursorAddValue( hIterator, FLM_TEXT_VAL,
|
|
GedValPtr( pCurNode), GedValLen( pCurNode))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Add an operator to the criteria.
|
|
|
|
case FCS_ITERATOR_OPERATOR:
|
|
{
|
|
FLMUINT uiOp;
|
|
QTYPES eTranslatedOp;
|
|
|
|
// Get the C/S operator ID.
|
|
|
|
if (RC_BAD( rc = GedGetUINT( pCurNode, &uiOp)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (!uiOp ||
|
|
((uiOp - FCS_ITERATOR_OP_START) >= FCS_ITERATOR_OP_END))
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
|
|
// Translate the C/S ID to a FLAIM operator ID.
|
|
|
|
if (RC_BAD( rc = fcsTranslateQCSToQFlmOp( uiOp, &eTranslatedOp)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the operator to the criteria.
|
|
|
|
if (RC_BAD( rc = FlmCursorAddOp( hIterator, eTranslatedOp)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_SYNTAX);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
pCurNode = GedSibNext( pCurNode);
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Adds source information to an iterator.
|
|
****************************************************************************/
|
|
FSTATIC RCODE fsvIteratorFromParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool)
|
|
{
|
|
HFDB hDb = HFDB_NULL;
|
|
HFCURSOR hIterator = pWire->getIteratorHandle();
|
|
FLMUINT uiIteratorId = FCS_INVALID_ID;
|
|
NODE * pFrom = pWire->getIteratorFrom();
|
|
NODE * pCurNode;
|
|
NODE * pCSAttrNode;
|
|
NODE * pTmpNode;
|
|
RCODE rc = FERR_OK;
|
|
|
|
F_UNREFERENCED_PARM( pPool);
|
|
|
|
// If no "from" clause, jump to exit.
|
|
|
|
if (!pFrom)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Process each component of the "from" clause.
|
|
|
|
if (hIterator == HFCURSOR_NULL)
|
|
{
|
|
FSV_SESN * pSession;
|
|
FLMUINT uiContainerId = FLM_DATA_CONTAINER;
|
|
FLMUINT uiPath[4];
|
|
|
|
uiPath[0] = FCS_ITERATOR_FROM;
|
|
uiPath[1] = FCS_ITERATOR_CANDIDATE_SET;
|
|
uiPath[2] = FCS_ITERATOR_RECORD_SOURCE;
|
|
uiPath[3] = 0;
|
|
if ((pCSAttrNode = GedPathFind( GED_TREE, pFrom, uiPath, 1)) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the database handle.
|
|
|
|
if ((pSession = pWire->getSession()) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_BAD_HDL);
|
|
goto Exit;
|
|
}
|
|
|
|
hDb = pSession->GetDatabase();
|
|
|
|
// Get the container ID. A default value of FLM_DATA_CONTAINER will
|
|
// be used if a container ID is not found.
|
|
|
|
if ((pTmpNode = GedFind( GED_TREE, pCSAttrNode,
|
|
FCS_ITERATOR_CONTAINER_ID, 1)) != NULL)
|
|
{
|
|
if (RC_BAD( rc = GedGetUINT( pTmpNode, &uiContainerId)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Initialize the cursor when we get the source - only one source is
|
|
// allowed.
|
|
|
|
if (RC_BAD( rc = pSession->InitializeIterator( &uiIteratorId, hDb,
|
|
uiContainerId, &hIterator)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Set the iterator handle and ID so they will be available for the
|
|
// parser to use.
|
|
|
|
pWire->setIteratorId( uiIteratorId);
|
|
pWire->setIteratorHandle( hIterator);
|
|
}
|
|
|
|
pCurNode = GedChild( pFrom);
|
|
while (pCurNode)
|
|
{
|
|
switch (GedTagNum( pCurNode))
|
|
{
|
|
case FCS_ITERATOR_CANDIDATE_SET:
|
|
{
|
|
|
|
// Process record sources and indexes.
|
|
|
|
pCSAttrNode = GedChild( pCurNode);
|
|
while (pCSAttrNode)
|
|
{
|
|
switch (GedTagNum( pCSAttrNode))
|
|
{
|
|
|
|
// Define a record source.
|
|
|
|
case FCS_ITERATOR_RECORD_SOURCE:
|
|
{
|
|
|
|
// Handled above.
|
|
|
|
break;
|
|
}
|
|
|
|
// Specify a FLAIM index.
|
|
|
|
case FCS_ITERATOR_FLAIM_INDEX:
|
|
{
|
|
FLMUINT uiIndexId;
|
|
|
|
// Get the index ID.
|
|
|
|
if (RC_BAD( rc = GedGetUINT( pCSAttrNode, &uiIndexId)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the index.
|
|
|
|
if (RC_BAD( rc = FlmCursorConfig( hIterator,
|
|
FCURSOR_SET_FLM_IX, (void *) uiIndexId,
|
|
(void *) 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Set the record type.
|
|
|
|
case FCS_ITERATOR_RECORD_TYPE:
|
|
{
|
|
FLMUINT uiRecordType;
|
|
|
|
// Get the record type.
|
|
|
|
if (RC_BAD( rc = GedGetUINT( pCSAttrNode, &uiRecordType)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the record type.
|
|
|
|
if (RC_BAD( rc = FlmCursorConfig( hIterator,
|
|
FCURSOR_SET_REC_TYPE,
|
|
(void *) uiRecordType,
|
|
(void *) 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_ITERATOR_OK_TO_RETURN_KEYS:
|
|
{
|
|
FLMUINT uiOkToReturnKeys;
|
|
|
|
if (RC_BAD( rc = GedGetUINT(
|
|
pCSAttrNode, &uiOkToReturnKeys)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = FlmCursorConfig( hIterator,
|
|
FCURSOR_RETURN_KEYS_OK,
|
|
(void *) (FLMBOOL) (uiOkToReturnKeys
|
|
? TRUE
|
|
: FALSE),
|
|
(void *) NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
pCSAttrNode = GedSibNext( pCSAttrNode);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FCS_ITERATOR_MODE:
|
|
{
|
|
FLMUINT uiFlags;
|
|
|
|
// Get the mode flags.
|
|
|
|
if (RC_BAD( rc = GedGetUINT( pCurNode, &uiFlags)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = FlmCursorSetMode( hIterator, uiFlags)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
pCurNode = GedSibNext( pCurNode);
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Adds a view to an iterator
|
|
****************************************************************************/
|
|
FSTATIC RCODE fsvIteratorSelectParse(
|
|
FSV_WIRE * pWire,
|
|
F_Pool * pPool)
|
|
{
|
|
NODE * pSelect = pWire->getIteratorSelect();
|
|
NODE * pCurNode;
|
|
NODE * pView = NULL;
|
|
FLMBOOL bNullViewNotRec = FALSE;
|
|
RCODE rc = FERR_OK;
|
|
|
|
F_UNREFERENCED_PARM( pPool);
|
|
|
|
// If no "select" clause, jump to exit.
|
|
|
|
if (!pSelect)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pCurNode = GedChild( pSelect);
|
|
while (pCurNode)
|
|
{
|
|
switch (GedTagNum( pCurNode))
|
|
{
|
|
case FCS_ITERATOR_VIEW_TREE:
|
|
{
|
|
pView = GedChild( pCurNode);
|
|
break;
|
|
}
|
|
|
|
case FCS_ITERATOR_NULL_VIEW_NOT_REC:
|
|
{
|
|
bNullViewNotRec = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pCurNode = GedSibNext( pCurNode);
|
|
}
|
|
|
|
// Set the view record, if any (not supported).
|
|
|
|
if (GedChild( pCurNode))
|
|
{
|
|
rc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Reads blocks from the database
|
|
****************************************************************************/
|
|
FSTATIC RCODE fsvDbGetBlocks(
|
|
HFDB hDb,
|
|
FLMUINT uiAddress,
|
|
FLMUINT uiMinTransId,
|
|
FLMUINT * puiCount,
|
|
FLMUINT * puiBlocksExamined,
|
|
FLMUINT * puiNextBlkAddr,
|
|
FLMUINT uiFlags,
|
|
F_Pool * pPool,
|
|
FLMBYTE ** ppBlocks,
|
|
FLMUINT * puiBytes)
|
|
{
|
|
FDB * pDb = (FDB *) hDb;
|
|
FLMBOOL bDbInitialized = FALSE;
|
|
FLMBOOL bTransStarted = FALSE;
|
|
FLMUINT uiLoop;
|
|
FLMUINT uiCount = *puiCount;
|
|
SCACHE * pSCache = NULL;
|
|
FLMUINT uiBlockSize;
|
|
FLMUINT uiMaxFileSize;
|
|
RCODE rc = FERR_OK;
|
|
|
|
*ppBlocks = NULL;
|
|
*puiCount = 0;
|
|
*puiBlocksExamined = 0;
|
|
*puiBytes = 0;
|
|
|
|
if (IsInCSMode( hDb))
|
|
{
|
|
fdbInitCS( pDb);
|
|
bDbInitialized = TRUE;
|
|
|
|
CS_CONTEXT * pCSContext = pDb->pCSContext;
|
|
FCL_WIRE Wire(pCSContext, pDb);
|
|
|
|
if (!pCSContext->bConnectionGood)
|
|
{
|
|
rc = RC_SET( FERR_BAD_SERVER_CONNECTION);
|
|
goto Transmission_Error;
|
|
}
|
|
|
|
if (RC_BAD( rc = Wire.sendOp( FCS_OPCLASS_DATABASE,
|
|
FCS_OP_DATABASE_GET_BLOCK)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = Wire.sendNumber( WIRE_VALUE_ADDRESS, uiAddress)))
|
|
{
|
|
goto Transmission_Error;
|
|
}
|
|
|
|
if (RC_BAD( rc = Wire.sendNumber( WIRE_VALUE_TRANSACTION_ID, uiMinTransId)))
|
|
{
|
|
goto Transmission_Error;
|
|
}
|
|
|
|
if (RC_BAD( rc = Wire.sendNumber( WIRE_VALUE_COUNT, uiCount)))
|
|
{
|
|
goto Transmission_Error;
|
|
}
|
|
|
|
if (RC_BAD( rc = Wire.sendNumber( WIRE_VALUE_FLAGS, uiFlags)))
|
|
{
|
|
goto Transmission_Error;
|
|
}
|
|
|
|
if (RC_BAD( rc = Wire.sendTerminate()))
|
|
{
|
|
goto Transmission_Error;
|
|
}
|
|
|
|
// Read the response.
|
|
|
|
if (RC_BAD( rc = Wire.read()))
|
|
{
|
|
goto Transmission_Error;
|
|
}
|
|
|
|
if (RC_BAD( rc = Wire.getRCode()))
|
|
{
|
|
if (rc != FERR_IO_END_OF_FILE)
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
*puiBlocksExamined = (FLMUINT) Wire.getNumber2();
|
|
*puiCount = (FLMUINT) Wire.getCount();
|
|
*puiNextBlkAddr = Wire.getAddress();
|
|
|
|
if (*puiCount)
|
|
{
|
|
*puiBytes = Wire.getBlockSize();
|
|
if( RC_BAD( rc = pPool->poolAlloc( *puiBytes, (void **)ppBlocks)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
f_memcpy( *ppBlocks, Wire.getBlock(), *puiBytes);
|
|
}
|
|
|
|
goto Exit;
|
|
|
|
Transmission_Error:
|
|
|
|
pCSContext->bConnectionGood = FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!uiCount)
|
|
{
|
|
uiCount = 1;
|
|
}
|
|
|
|
uiBlockSize = pDb->pFile->FileHdr.uiBlockSize;
|
|
uiMaxFileSize = pDb->pFile->uiMaxFileSize;
|
|
bDbInitialized = TRUE;
|
|
if (RC_BAD( rc = fdbInit( pDb, FLM_READ_TRANS, FDB_TRANS_GOING_OK, 0,
|
|
&bTransStarted)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if( RC_BAD( rc = pPool->poolAlloc( uiBlockSize * uiCount,
|
|
(void **)ppBlocks)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read uiCount blocks from the database starting at uiAddress. If none
|
|
// of the blocks meet the min trans ID criteria, we will not return any
|
|
// blocks to the reader.
|
|
|
|
*puiNextBlkAddr = BT_END;
|
|
for (uiLoop = 0; uiLoop < uiCount; uiLoop++)
|
|
{
|
|
if (!FSAddrIsBelow( FSBlkAddress( FSGetFileNumber( uiAddress),
|
|
FSGetFileOffset( uiAddress)), pDb->LogHdr.uiLogicalEOF))
|
|
{
|
|
rc = RC_SET( FERR_IO_END_OF_FILE);
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, uiAddress, NULL,
|
|
&pSCache)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (FB2UD( &pSCache->pucBlk[BH_TRANS_ID]) >= uiMinTransId)
|
|
{
|
|
f_memcpy( (*ppBlocks + ((*puiCount) * uiBlockSize)), pSCache->pucBlk,
|
|
uiBlockSize);
|
|
(*puiCount)++;
|
|
(*puiBytes) += uiBlockSize;
|
|
}
|
|
(*puiBlocksExamined)++;
|
|
|
|
ScaReleaseCache( pSCache, FALSE);
|
|
pSCache = NULL;
|
|
|
|
uiAddress += uiBlockSize;
|
|
if (FSGetFileOffset( uiAddress) >= uiMaxFileSize)
|
|
{
|
|
uiAddress = FSBlkAddress( FSGetFileNumber( uiAddress) + 1, 0);
|
|
}
|
|
|
|
*puiNextBlkAddr = uiAddress;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pSCache)
|
|
{
|
|
ScaReleaseCache( pSCache, FALSE);
|
|
}
|
|
|
|
if (bTransStarted)
|
|
{
|
|
RCODE rc2 = flmAbortDbTrans( pDb);
|
|
if (RC_OK( rc))
|
|
{
|
|
rc = rc2;
|
|
}
|
|
}
|
|
|
|
if (bDbInitialized)
|
|
{
|
|
fdbExit( pDb);
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Commits a database transaction and updates the log header
|
|
****************************************************************************/
|
|
RCODE fsvDbTransCommitEx(
|
|
HFDB hDb,
|
|
FSV_WIRE * pWire)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FDB * pDb = (FDB *) hDb;
|
|
FLMBOOL bIgnore;
|
|
FLMBOOL bForceCheckpoint = FALSE;
|
|
FLMBYTE * pucHeader = NULL;
|
|
|
|
if (pWire->getFlags() & FCS_TRANS_FORCE_CHECKPOINT)
|
|
{
|
|
bForceCheckpoint = TRUE;
|
|
}
|
|
|
|
pucHeader = pWire->getBlock();
|
|
|
|
if (IsInCSMode( hDb))
|
|
{
|
|
fdbInitCS( pDb);
|
|
|
|
FCL_WIRE Wire(pDb->pCSContext, pDb);
|
|
|
|
if (!pDb->pCSContext->bConnectionGood)
|
|
{
|
|
rc = RC_SET( FERR_BAD_SERVER_CONNECTION);
|
|
}
|
|
else
|
|
{
|
|
rc = Wire.doTransOp( FCS_OP_TRANSACTION_COMMIT_EX, 0, 0, 0, pucHeader,
|
|
bForceCheckpoint);
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = fdbInit( pDb, FLM_NO_TRANS, FDB_TRANS_GOING_OK, 0, &bIgnore)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// If there is an invisible transaction going, it should not be
|
|
// commitable by an application.
|
|
|
|
if ((pDb->uiTransType == FLM_NO_TRANS) ||
|
|
(pDb->uiFlags & FDB_INVISIBLE_TRANS))
|
|
{
|
|
rc = RC_SET( FERR_NO_TRANS_ACTIVE);
|
|
goto Exit;
|
|
}
|
|
|
|
// See if we have a transaction going which should be aborted.
|
|
|
|
if (RC_BAD( pDb->AbortRc))
|
|
{
|
|
rc = RC_SET( FERR_ABORT_TRANS);
|
|
goto Exit;
|
|
}
|
|
|
|
// Fix up the log header. Currently, only fields directly related to a
|
|
// backup operation are updated.
|
|
|
|
if (pucHeader)
|
|
{
|
|
FLMBYTE * pLogHdr = &pucHeader[16];
|
|
FLMBYTE * pucUncommittedHdr = &pDb->pFile->ucUncommittedLogHdr[0];
|
|
|
|
f_memcpy( &pucUncommittedHdr[LOG_LAST_BACKUP_TRANS_ID],
|
|
&pLogHdr[LOG_LAST_BACKUP_TRANS_ID], 4);
|
|
|
|
f_memcpy( &pucUncommittedHdr[LOG_BLK_CHG_SINCE_BACKUP],
|
|
&pLogHdr[LOG_BLK_CHG_SINCE_BACKUP], 4);
|
|
|
|
f_memcpy( &pucUncommittedHdr[LOG_INC_BACKUP_SEQ_NUM],
|
|
&pLogHdr[LOG_INC_BACKUP_SEQ_NUM], 4);
|
|
|
|
f_memcpy( &pucUncommittedHdr[LOG_INC_BACKUP_SERIAL_NUM],
|
|
&pLogHdr[LOG_INC_BACKUP_SERIAL_NUM], F_SERIAL_NUM_SIZE);
|
|
}
|
|
|
|
// Commit the transaction
|
|
|
|
rc = flmCommitDbTrans( pDb, 0, bForceCheckpoint);
|
|
|
|
Exit:
|
|
|
|
flmExit( FLM_DB_TRANS_COMMIT, pDb, rc);
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc: Looks up session, database, and iterator handles.
|
|
****************************************************************************/
|
|
FSTATIC RCODE fsvGetHandles(
|
|
FSV_WIRE * pWire)
|
|
{
|
|
FSV_SCTX * pServerContext = NULL;
|
|
FSV_SESN * pSession = NULL;
|
|
HFCURSOR hIterator = HFCURSOR_NULL;
|
|
RCODE rc = FERR_OK;
|
|
|
|
if (RC_BAD( rc = fsvGetGlobalContext( &pServerContext)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (pWire->getSessionId() != FCS_INVALID_ID)
|
|
{
|
|
if (RC_BAD( pServerContext->GetSession( pWire->getSessionId(), &pSession)))
|
|
{
|
|
rc = RC_SET( FERR_BAD_HDL);
|
|
goto Exit;
|
|
}
|
|
|
|
if (pSession->getCookie() != pWire->getSessionCookie())
|
|
{
|
|
rc = RC_SET( FERR_BAD_HDL);
|
|
goto Exit;
|
|
}
|
|
|
|
pWire->setSession( pSession);
|
|
}
|
|
|
|
if (pSession)
|
|
{
|
|
pWire->setFDB( (FDB *) pSession->GetDatabase());
|
|
if (pWire->getIteratorId() != FCS_INVALID_ID)
|
|
{
|
|
if (RC_BAD( rc = pSession->GetIterator( pWire->getIteratorId(),
|
|
&hIterator)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pWire->setIteratorHandle( hIterator);
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE fsvPostStreamedRequest(
|
|
FSV_SESN * pSession,
|
|
FLMBYTE * pucPacket,
|
|
FLMUINT uiPacketSize,
|
|
FLMBOOL bLastPacket,
|
|
FCS_BIOS * pSessionResponse)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FLMBOOL bReleaseSession = FALSE;
|
|
F_Pool localPool;
|
|
|
|
localPool.poolInit( 1024);
|
|
|
|
if (!pSession && !bLastPacket)
|
|
{
|
|
|
|
// If this is a session open request, the request must be contained
|
|
// in a single packet.
|
|
|
|
rc = RC_SET( FERR_ILLEGAL_OP);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!pSession)
|
|
{
|
|
FCS_BIOS biosInput;
|
|
FCS_DIS dataIStream;
|
|
FCS_DOS dataOStream;
|
|
|
|
if (RC_BAD( rc = dataIStream.setup( &biosInput)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = dataOStream.setup( pSessionResponse)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = biosInput.write( pucPacket, uiPacketSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = fsvProcessRequest( &dataIStream, &dataOStream,
|
|
&localPool, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FCS_BIOS * pServerBIStream;
|
|
FCS_BIOS * pServerBOStream;
|
|
|
|
// Need to add a reference to the session object so that if the
|
|
// request closes the session, the response stream will not be
|
|
// destructed until the response has been returned to the client.
|
|
|
|
pSession->AddRef();
|
|
bReleaseSession = TRUE;
|
|
|
|
if (RC_BAD( rc = pSession->GetBIStream( &pServerBIStream)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pSession->GetBOStream( &pServerBOStream)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pServerBIStream->write( pucPacket, uiPacketSize)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (bLastPacket)
|
|
{
|
|
FCS_DIS dataIStream;
|
|
FCS_DOS dataOStream;
|
|
|
|
if (RC_BAD( rc = dataIStream.setup( pServerBIStream)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = dataOStream.setup( pServerBOStream)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pSession->getWireScratchPool()->poolReset();
|
|
if (RC_BAD( rc = fsvProcessRequest( &dataIStream, &dataOStream,
|
|
pSession->getWireScratchPool(), NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (bReleaseSession)
|
|
{
|
|
pSession->Release();
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE fsvGetStreamedResponse(
|
|
FSV_SESN * pSession,
|
|
FLMBYTE * pucPacketBuffer,
|
|
FLMUINT uiMaxPacketSize,
|
|
FLMUINT * puiPacketSize,
|
|
FLMBOOL * pbLastPacket)
|
|
{
|
|
FCS_BIOS * pServerBOStream = NULL;
|
|
RCODE rc = FERR_OK;
|
|
|
|
if (RC_BAD( rc = pSession->GetBOStream( &pServerBOStream)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = pServerBOStream->read( pucPacketBuffer, uiMaxPacketSize,
|
|
puiPacketSize)))
|
|
{
|
|
if (rc == FERR_EOF_HIT)
|
|
{
|
|
*pbLastPacket = TRUE;
|
|
rc = FERR_OK;
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
if (!pServerBOStream->isDataAvailable())
|
|
{
|
|
*pbLastPacket = TRUE;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FSV_SCTX::FSV_SCTX(void)
|
|
{
|
|
m_uiSessionToken = 0;
|
|
m_uiCacheSize = FSV_DEFAULT_CACHE_SIZE;
|
|
m_bSetupCalled = FALSE;
|
|
m_paSessions = NULL;
|
|
m_hMutex = F_MUTEX_NULL;
|
|
m_szServerBasePath[0] = '\0';
|
|
m_pLogFunc = NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FSV_SCTX::~FSV_SCTX(void)
|
|
{
|
|
FLMUINT uiSlot;
|
|
|
|
if (m_bSetupCalled)
|
|
{
|
|
|
|
// Clean up and free the session table.
|
|
|
|
for (uiSlot = 0; uiSlot < m_uiMaxSessions; uiSlot++)
|
|
{
|
|
if (m_paSessions[uiSlot] != NULL)
|
|
{
|
|
m_paSessions[uiSlot]->Release();
|
|
}
|
|
}
|
|
|
|
f_free( &m_paSessions);
|
|
|
|
// Free the session semaphore.
|
|
|
|
(void) f_mutexDestroy( &m_hMutex);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::Setup(
|
|
FLMUINT uiMaxSessions,
|
|
const char * pszServerBasePath,
|
|
FSV_LOG_FUNC pLogFunc)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
FLMUINT uiSlot;
|
|
|
|
// Make sure that setup has not been called.
|
|
|
|
flmAssert( m_bSetupCalled == FALSE);
|
|
|
|
// If zero was passed as the value of uiMaxSessions, use the default.
|
|
|
|
if (!uiMaxSessions)
|
|
{
|
|
m_uiMaxSessions = FSV_DEFAULT_MAX_CONNECTIONS;
|
|
}
|
|
else
|
|
{
|
|
m_uiMaxSessions = uiMaxSessions;
|
|
}
|
|
|
|
// Initialize the session table.
|
|
|
|
if (RC_BAD( rc = f_alloc( sizeof(FSV_SESN *) * m_uiMaxSessions, &m_paSessions
|
|
)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
for (uiSlot = 0; uiSlot < m_uiMaxSessions; uiSlot++)
|
|
{
|
|
m_paSessions[uiSlot] = NULL;
|
|
}
|
|
|
|
// Initialize the context mutex
|
|
|
|
if (RC_BAD( rc = f_mutexCreate( &m_hMutex)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Set the server's home path.
|
|
|
|
if (pszServerBasePath)
|
|
{
|
|
f_strcpy( m_szServerBasePath, pszServerBasePath);
|
|
}
|
|
else
|
|
{
|
|
m_szServerBasePath[0] = '\0';
|
|
}
|
|
|
|
// Set the logging function.
|
|
|
|
m_pLogFunc = pLogFunc;
|
|
|
|
// Set the setup flag.
|
|
|
|
m_bSetupCalled = TRUE;
|
|
|
|
Exit:
|
|
|
|
// Clean up any allocations if an error was encountered.
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (m_paSessions != NULL)
|
|
{
|
|
f_free( &m_paSessions);
|
|
}
|
|
|
|
if (m_hMutex != F_MUTEX_NULL)
|
|
{
|
|
f_mutexDestroy( &m_hMutex);
|
|
}
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::OpenSession(
|
|
FLMUINT uiVersion,
|
|
FLMUINT uiFlags,
|
|
FLMUINT * puiIdRV,
|
|
FSV_SESN ** ppSessionRV)
|
|
{
|
|
FLMUINT uiSlot;
|
|
FLMUINT uiCurrTime;
|
|
FLMBOOL bLocked = FALSE;
|
|
FSV_SESN * pSession = NULL;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Initialize the Id
|
|
|
|
*puiIdRV = 0;
|
|
|
|
// Create a new session object
|
|
|
|
if ((pSession = f_new FSV_SESN) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Allocate the session object
|
|
|
|
if (RC_BAD( rc = pSession->Setup( this, uiVersion, uiFlags)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Lock the context mutex
|
|
|
|
f_mutexLock( m_hMutex);
|
|
bLocked = TRUE;
|
|
|
|
// Find an empty slot in the table.
|
|
|
|
for (uiSlot = 0; uiSlot < m_uiMaxSessions; uiSlot++)
|
|
{
|
|
if (!m_paSessions[uiSlot])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (uiSlot >= m_uiMaxSessions)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Assign the session to the table slot.
|
|
|
|
m_paSessions[uiSlot] = pSession;
|
|
|
|
// Increment the session token.
|
|
|
|
m_uiSessionToken++;
|
|
|
|
// If the session token is 0xFFFF, reset it to 1. Because
|
|
// FSV_INVALID_ID is 0xFFFFFFFF, it is important to reset the session
|
|
// token so that a session will never be assigned an invalid ID.
|
|
|
|
if (m_uiSessionToken == 0xFFFF)
|
|
{
|
|
m_uiSessionToken = 1;
|
|
}
|
|
|
|
// Set the session's ID.
|
|
|
|
*puiIdRV = uiSlot | (m_uiSessionToken << 16);
|
|
pSession->setId( *puiIdRV);
|
|
|
|
// Set the session's cookie using the current time.
|
|
|
|
f_timeGetSeconds( &uiCurrTime);
|
|
pSession->setCookie( uiCurrTime);
|
|
|
|
// Unlock the context mutex
|
|
|
|
f_mutexUnlock( m_hMutex);
|
|
bLocked = FALSE;
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (pSession)
|
|
{
|
|
pSession->Release();
|
|
pSession = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ppSessionRV)
|
|
{
|
|
*ppSessionRV = pSession;
|
|
}
|
|
}
|
|
|
|
if (bLocked)
|
|
{
|
|
f_mutexUnlock( m_hMutex);
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::CloseSession(
|
|
FLMUINT uiId)
|
|
{
|
|
FLMUINT uiSlot = (0x0000FFFF & uiId);
|
|
FLMBOOL bLocked = FALSE;
|
|
FSV_SESN * pSession = NULL;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Lock the context mutex
|
|
|
|
f_mutexLock( m_hMutex);
|
|
bLocked = TRUE;
|
|
|
|
// Make sure that the slot is valid.
|
|
|
|
if (uiSlot >= m_uiMaxSessions)
|
|
{
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get a pointer to the table entry.
|
|
|
|
if ((pSession = m_paSessions[uiSlot]) == NULL)
|
|
{
|
|
|
|
// Session already closed
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
// Verify the session ID.
|
|
|
|
if (pSession->getId() != uiId)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Free the session.
|
|
|
|
pSession->Release();
|
|
|
|
// Reset the table entry.
|
|
|
|
m_paSessions[uiSlot] = NULL;
|
|
|
|
Exit:
|
|
|
|
if (bLocked)
|
|
{
|
|
f_mutexUnlock( m_hMutex);
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::GetSession(
|
|
FLMUINT uiId,
|
|
FSV_SESN ** ppSession)
|
|
{
|
|
FLMUINT uiSlot = (0x0000FFFF & uiId);
|
|
FLMBOOL bLocked = FALSE;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Lock the context mutex
|
|
|
|
f_mutexLock( m_hMutex);
|
|
bLocked = TRUE;
|
|
|
|
// Make sure that the slot is valid.
|
|
|
|
if (uiSlot >= m_uiMaxSessions)
|
|
{
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
// Get a pointer to the entry in the session table.
|
|
|
|
if ((*ppSession = m_paSessions[uiSlot]) == NULL)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Verify the session ID.
|
|
|
|
if ((*ppSession)->getId() != uiId)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (bLocked)
|
|
{
|
|
f_mutexUnlock( m_hMutex);
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::SetBasePath(
|
|
const char * pszServerBasePath)
|
|
{
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Lock the context mutex
|
|
|
|
f_mutexLock( m_hMutex);
|
|
|
|
// Set the server's base path.
|
|
|
|
if (pszServerBasePath)
|
|
{
|
|
f_strcpy( m_szServerBasePath, pszServerBasePath);
|
|
}
|
|
else
|
|
{
|
|
m_szServerBasePath[0] = '\0';
|
|
}
|
|
|
|
// Unlock the context mutex
|
|
|
|
f_mutexUnlock( m_hMutex);
|
|
return (FERR_OK);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::GetBasePath(
|
|
char * pszServerBasePath)
|
|
{
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Lock the context mutex
|
|
|
|
f_mutexLock( m_hMutex);
|
|
|
|
// Copy the base path.
|
|
|
|
f_strcpy( pszServerBasePath, m_szServerBasePath);
|
|
|
|
// Unlock the context mutex
|
|
|
|
f_mutexUnlock( m_hMutex);
|
|
return (FERR_OK);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::BuildFilePath(
|
|
const FLMUNICODE * puzUrlString,
|
|
char * pszFilePathRV)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
char szBasePath[F_PATH_MAX_SIZE];
|
|
FUrl Url;
|
|
char * pucAsciiUrl;
|
|
const char * pszFile;
|
|
F_Pool tmpPool;
|
|
|
|
// Initialize a temporary pool.
|
|
|
|
tmpPool.poolInit( 256);
|
|
|
|
// Attempt to convert the UNICODE URL to a native string
|
|
|
|
if (RC_BAD( rc = fcsConvertUnicodeToNative( &tmpPool, puzUrlString,
|
|
&pucAsciiUrl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Parse the URL.
|
|
|
|
if (RC_BAD( rc = Url.SetUrl( pucAsciiUrl)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pszFile = Url.GetFile();
|
|
|
|
if (Url.GetRelative())
|
|
{
|
|
|
|
// Get the server's base path.
|
|
|
|
GetBasePath( szBasePath);
|
|
|
|
// Build the database path.
|
|
|
|
f_strcpy( pszFilePathRV, szBasePath);
|
|
if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathAppend(
|
|
pszFilePathRV, pszFile)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// Absolute path. Use the path "as-is."
|
|
|
|
f_strcpy( pszFilePathRV, pszFile);
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SCTX::SetTempDir(
|
|
const char * pszTempDir)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Set the temporary directory. There is no need to lock the context
|
|
// semaphore because the state of the context is not being changed.
|
|
|
|
if (RC_BAD( rc = FlmConfig( FLM_TMPDIR, (void *) pszTempDir, 0)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
void FSV_SCTX::LogMessage(
|
|
FSV_SESN * pSession,
|
|
const char * pucMsg,
|
|
RCODE rc,
|
|
FLMUINT uiMsgSeverity)
|
|
{
|
|
if (m_pLogFunc)
|
|
{
|
|
f_mutexLock( m_hMutex);
|
|
m_pLogFunc( pucMsg, rc, uiMsgSeverity, (void *) pSession);
|
|
f_mutexUnlock( m_hMutex);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FSV_SESN::FSV_SESN(void)
|
|
{
|
|
m_pServerContext = NULL;
|
|
m_hDb = HFDB_NULL;
|
|
m_uiSessionId = FCS_INVALID_ID;
|
|
m_uiCookie = 0;
|
|
m_uiFlags = 0;
|
|
m_pBIStream = NULL;
|
|
m_pBOStream = NULL;
|
|
m_bSetupCalled = FALSE;
|
|
m_uiClientProtocolVersion = 0;
|
|
m_wireScratchPool.poolInit( 2048);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
FSV_SESN::~FSV_SESN(void)
|
|
{
|
|
FLMUINT uiLoop;
|
|
|
|
if (m_bSetupCalled)
|
|
{
|
|
|
|
// Free iterator resources.
|
|
|
|
for (uiLoop = 0; uiLoop < MAX_SESN_ITERATORS; uiLoop++)
|
|
{
|
|
if (m_IteratorList[uiLoop] != HFCURSOR_NULL)
|
|
{
|
|
(void) FlmCursorFree( &m_IteratorList[uiLoop]);
|
|
}
|
|
}
|
|
|
|
// Close the database
|
|
|
|
if (m_hDb != HFDB_NULL)
|
|
{
|
|
(void) FlmDbClose( &m_hDb);
|
|
}
|
|
|
|
// Free the buffer streams
|
|
|
|
if (m_pBIStream)
|
|
{
|
|
m_pBIStream->Release();
|
|
}
|
|
|
|
if (m_pBOStream)
|
|
{
|
|
m_pBOStream->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::Setup(
|
|
FSV_SCTX * pServerContext,
|
|
FLMUINT uiVersion,
|
|
FLMUINT uiFlags)
|
|
{
|
|
FLMUINT uiLoop;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has not been called.
|
|
|
|
flmAssert( m_bSetupCalled == FALSE);
|
|
|
|
// Verify that the requested version is supported.
|
|
|
|
if (uiVersion > FCS_VERSION_1_1_1)
|
|
{
|
|
rc = RC_SET( FERR_UNSUPPORTED_VERSION);
|
|
goto Exit;
|
|
}
|
|
|
|
m_uiClientProtocolVersion = uiVersion;
|
|
|
|
// Set the server context.
|
|
|
|
m_pServerContext = pServerContext;
|
|
|
|
// Initialize the iterator list
|
|
|
|
for (uiLoop = 0; uiLoop < MAX_SESN_ITERATORS; uiLoop++)
|
|
{
|
|
m_IteratorList[uiLoop] = HFCURSOR_NULL;
|
|
}
|
|
|
|
m_bSetupCalled = TRUE;
|
|
m_uiFlags = uiFlags;
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::OpenDatabase(
|
|
FLMUNICODE * puzDbPath,
|
|
FLMUNICODE * puzDataDir,
|
|
FLMUNICODE * puzRflDir,
|
|
FLMUINT uiOpenFlags)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
char * pszDbPath = NULL;
|
|
char * pszDataDir;
|
|
char * pszRflDir;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
flmAssert( m_hDb == HFDB_NULL);
|
|
|
|
if (RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE * 3, &pszDbPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pszDataDir = pszDbPath + F_PATH_MAX_SIZE;
|
|
pszRflDir = pszDataDir + F_PATH_MAX_SIZE;
|
|
|
|
// Perform some sanity checking.
|
|
|
|
if (!puzDbPath)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Convert the UNICODE URL to a server path.
|
|
|
|
if (RC_BAD( rc = m_pServerContext->BuildFilePath( puzDbPath, pszDbPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Convert the data directory
|
|
|
|
if (puzDataDir)
|
|
{
|
|
if (RC_BAD( rc = m_pServerContext->BuildFilePath( puzDataDir, pszDataDir)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDataDir = NULL;
|
|
}
|
|
|
|
// Convert the RFL path
|
|
|
|
if (puzRflDir)
|
|
{
|
|
if (RC_BAD( rc = m_pServerContext->BuildFilePath( puzRflDir, pszRflDir)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pszRflDir = 0;
|
|
}
|
|
|
|
// Open the database.
|
|
|
|
if (RC_BAD( rc = FlmDbOpen( pszDbPath, pszDataDir, pszRflDir, uiOpenFlags,
|
|
NULL, &m_hDb)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pszDbPath)
|
|
{
|
|
f_free( &pszDbPath);
|
|
}
|
|
|
|
// Free resources
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (m_hDb != HFDB_NULL)
|
|
{
|
|
(void) FlmDbClose( &m_hDb);
|
|
}
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::CreateDatabase(
|
|
FLMUNICODE * puzDbPath,
|
|
FLMUNICODE * puzDataDir,
|
|
FLMUNICODE * puzRflDir,
|
|
FLMUNICODE * puzDictPath,
|
|
FLMUNICODE * puzDictBuf,
|
|
CREATE_OPTS * pCreateOpts)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
F_Pool tmpPool;
|
|
char * pucDictBuf = NULL;
|
|
char * pszDbPath = NULL;
|
|
char * pszDataDir;
|
|
char * pszRflDir;
|
|
char * pszDictPath;
|
|
|
|
// Initialize a temporary pool.
|
|
|
|
tmpPool.poolInit( 1024);
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
flmAssert( m_hDb == HFDB_NULL);
|
|
|
|
if (RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE * 4, &pszDbPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pszDataDir = pszDbPath + F_PATH_MAX_SIZE;
|
|
pszRflDir = pszDataDir + F_PATH_MAX_SIZE;
|
|
pszDictPath = pszRflDir + F_PATH_MAX_SIZE;
|
|
|
|
// Perform some sanity checking.
|
|
|
|
if (!puzDbPath)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
|
|
// Convert the DB URL to a server path.
|
|
|
|
if (RC_BAD( rc = m_pServerContext->BuildFilePath( puzDbPath, pszDbPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Convert the dictionary URL to a server path.
|
|
|
|
if (puzDictPath)
|
|
{
|
|
if (RC_BAD( rc = m_pServerContext->BuildFilePath( puzDictPath, pszDictPath
|
|
)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDictPath = NULL;
|
|
}
|
|
|
|
// Convert the data directory
|
|
|
|
if (puzDataDir)
|
|
{
|
|
if (RC_BAD( rc = m_pServerContext->BuildFilePath( puzDataDir, pszDataDir)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszDataDir = NULL;
|
|
}
|
|
|
|
// Convert the RFL path
|
|
|
|
if (puzRflDir)
|
|
{
|
|
if (RC_BAD( rc = m_pServerContext->BuildFilePath( puzRflDir, pszRflDir)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pszRflDir = 0;
|
|
}
|
|
|
|
// Attempt to convert the UNICODE dictionary buffer to a native string
|
|
|
|
if (puzDictBuf)
|
|
{
|
|
if (RC_BAD( rc = fcsConvertUnicodeToNative( &tmpPool, puzDictBuf,
|
|
&pucDictBuf)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Create the database.
|
|
|
|
if (RC_BAD( rc = FlmDbCreate( pszDbPath, pszDataDir, pszRflDir, pszDictPath,
|
|
pucDictBuf, pCreateOpts, &m_hDb)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pszDbPath)
|
|
{
|
|
f_free( &pszDbPath);
|
|
}
|
|
|
|
// Free resources
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (m_hDb != HFDB_NULL)
|
|
{
|
|
(void) FlmDbClose( &m_hDb);
|
|
}
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::CloseDatabase(void)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Close the database.
|
|
|
|
if (m_hDb != HFDB_NULL)
|
|
{
|
|
if (RC_BAD( rc = FlmDbClose( &m_hDb)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::InitializeIterator(
|
|
FLMUINT * puiIteratorIdRV,
|
|
HFDB hDb,
|
|
FLMUINT uiContainer,
|
|
HFCURSOR * phIteratorRV)
|
|
{
|
|
HFCURSOR hIterator = HFCURSOR_NULL;
|
|
FLMUINT uiSlot;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Set the iterator id.
|
|
|
|
*puiIteratorIdRV = FCS_INVALID_ID;
|
|
|
|
// Find a slot in the session's iterator table
|
|
|
|
for (uiSlot = 0; uiSlot < MAX_SESN_ITERATORS; uiSlot++)
|
|
{
|
|
if (m_IteratorList[uiSlot] == HFCURSOR_NULL)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Too many open iterators
|
|
|
|
if (uiSlot == MAX_SESN_ITERATORS)
|
|
{
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
// Initialize a new iterator (cursor).
|
|
|
|
if (RC_BAD( rc = FlmCursorInit( hDb, uiContainer, &hIterator)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Add the iterator to the iterator list.
|
|
|
|
m_IteratorList[uiSlot] = hIterator;
|
|
*puiIteratorIdRV = uiSlot;
|
|
|
|
Exit:
|
|
|
|
// Free resources
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
if (hIterator != HFCURSOR_NULL)
|
|
{
|
|
(void) FlmCursorFree( &hIterator);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (phIteratorRV)
|
|
{
|
|
*phIteratorRV = hIterator;
|
|
}
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::FreeIterator(
|
|
FLMUINT uiIteratorId)
|
|
{
|
|
HFCURSOR hIterator = HFCURSOR_NULL;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
// Find the iterator in the resource bag and remove it.
|
|
|
|
if (uiIteratorId >= MAX_SESN_ITERATORS ||
|
|
m_IteratorList[uiIteratorId] == HFCURSOR_NULL)
|
|
{
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
hIterator = m_IteratorList[uiIteratorId];
|
|
m_IteratorList[uiIteratorId] = HFCURSOR_NULL;
|
|
|
|
// Free the iterator.
|
|
|
|
if (RC_BAD( rc = FlmCursorFree( &hIterator)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::GetIterator(
|
|
FLMUINT uiIteratorId,
|
|
HFCURSOR * phIteratorRV)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Make sure that setup has been called.
|
|
|
|
flmAssert( m_bSetupCalled == TRUE);
|
|
|
|
if (uiIteratorId >= MAX_SESN_ITERATORS ||
|
|
m_IteratorList[uiIteratorId] == HFCURSOR_NULL)
|
|
{
|
|
rc = RC_SET( FERR_FAILURE);
|
|
goto Exit;
|
|
}
|
|
|
|
*phIteratorRV = m_IteratorList[uiIteratorId];
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::GetBIStream(
|
|
FCS_BIOS ** ppBIStream)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
*ppBIStream = NULL;
|
|
|
|
if (!m_pBIStream)
|
|
{
|
|
m_pBIStream = f_new FCS_BIOS;
|
|
if (!m_pBIStream)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
*ppBIStream = m_pBIStream;
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_SESN::GetBOStream(
|
|
FCS_BIOS ** ppBOStream)
|
|
{
|
|
RCODE rc = FERR_OK;
|
|
|
|
*ppBOStream = NULL;
|
|
|
|
if (!m_pBOStream)
|
|
{
|
|
m_pBOStream = f_new FCS_BIOS;
|
|
if (!m_pBOStream)
|
|
{
|
|
rc = RC_SET( FERR_MEM);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
*ppBOStream = m_pBOStream;
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE flmStreamEventDispatcher(
|
|
FCS_BIOS * pStream,
|
|
FLMUINT uiEvent,
|
|
void * UserData)
|
|
{
|
|
CS_CONTEXT * pCSContext = (CS_CONTEXT *) UserData;
|
|
FLMUINT uiStreamHandlerId = FSEV_HANDLER_UNKNOWN;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Determine the handler
|
|
|
|
if (pCSContext->uiStreamHandlerId == FSEV_HANDLER_UNKNOWN)
|
|
{
|
|
if (f_stricmp( pCSContext->pucAddr, "DS") == 0)
|
|
{
|
|
uiStreamHandlerId = FSEV_HANDLER_DS;
|
|
}
|
|
else if (f_stricmp( pCSContext->pucAddr, "LOOPBACK") == 0)
|
|
{
|
|
uiStreamHandlerId = FSEV_HANDLER_LOOPBACK;
|
|
}
|
|
|
|
pCSContext->uiStreamHandlerId = uiStreamHandlerId;
|
|
}
|
|
else
|
|
{
|
|
uiStreamHandlerId = pCSContext->uiStreamHandlerId;
|
|
}
|
|
|
|
// Invoke the handler
|
|
|
|
switch (uiStreamHandlerId)
|
|
{
|
|
case FSEV_HANDLER_LOOPBACK:
|
|
{
|
|
if (RC_BAD( rc = fsvStreamLoopback( pStream, uiEvent, UserData)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
rc = RC_SET( FERR_NOT_IMPLEMENTED);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// Release CPU to prevent CPU hog
|
|
|
|
f_yieldCPU();
|
|
|
|
Exit:
|
|
|
|
if (RC_BAD( rc))
|
|
{
|
|
|
|
// Clear the saved handler ID in case a new handler is tried
|
|
|
|
pCSContext->uiStreamHandlerId = FSEV_HANDLER_UNKNOWN;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE fsvStreamLoopback(
|
|
FCS_BIOS * pStream,
|
|
FLMUINT uiEvent,
|
|
void * UserData)
|
|
{
|
|
CS_CONTEXT * pCSContext = (CS_CONTEXT *) UserData;
|
|
FCS_DIS dataIStream;
|
|
FCS_DOS dataOStream;
|
|
RCODE rc = FERR_OK;
|
|
|
|
F_UNREFERENCED_PARM( pStream);
|
|
|
|
if (uiEvent == FCS_BIOS_EOM_EVENT)
|
|
{
|
|
if (RC_BAD( rc = dataIStream.setup( (FCS_BIOS *) (pCSContext->pOStream))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = dataOStream.setup( (FCS_BIOS *) (pCSContext->pIStream))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RC_BAD( rc = fsvProcessRequest( &dataIStream, &dataOStream,
|
|
&(pCSContext->pool), NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
void FSV_WIRE::reset(void)
|
|
{
|
|
resetCommon();
|
|
m_uiOpSeqNum = 0;
|
|
m_uiClientVersion = 0;
|
|
m_uiAutoTrans = 0;
|
|
m_uiMaxLockWait = 0;
|
|
m_puzDictPath = NULL;
|
|
m_puzDictBuf = NULL;
|
|
m_puzFileName = NULL;
|
|
m_pucPassword = NULL;
|
|
m_pDrnList = NULL;
|
|
m_uiAreaId = 0;
|
|
m_pIteratorSelect = NULL;
|
|
m_pIteratorFrom = NULL;
|
|
m_pIteratorWhere = NULL;
|
|
m_pIteratorConfig = NULL;
|
|
m_pSession = NULL;
|
|
m_hIterator = HFCURSOR_NULL;
|
|
m_uiType = 0;
|
|
m_bSendGedcom = FALSE;
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
void FSV_WIRE::setSession(
|
|
FSV_SESN * pSession)
|
|
{
|
|
m_pSession = pSession;
|
|
|
|
// See if GEDCOM is supported by the client
|
|
|
|
if (m_pSession && (m_pSession->getFlags() & FCS_SESSION_GEDCOM_SUPPORT))
|
|
{
|
|
m_bSendGedcom = TRUE;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
Desc:
|
|
****************************************************************************/
|
|
RCODE FSV_WIRE::read(void)
|
|
{
|
|
FLMUINT uiTag;
|
|
FLMUINT uiCount = 0;
|
|
FLMBOOL bDone = FALSE;
|
|
RCODE rc = FERR_OK;
|
|
|
|
// Read the opcode.
|
|
|
|
if (RC_BAD( rc = readOpcode()))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Read the request / response values.
|
|
|
|
for (;;)
|
|
{
|
|
if (RC_BAD( rc = readCommon( &uiTag, &bDone)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (bDone)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// uiTag will be non-zero if readCommon did not understand it.
|
|
|
|
uiCount++;
|
|
if (uiTag)
|
|
{
|
|
switch ((uiTag & WIRE_VALUE_TAG_MASK))
|
|
{
|
|
case WIRE_VALUE_OP_SEQ_NUM:
|
|
{
|
|
if (RC_BAD( rc = readNumber( uiTag, &m_uiOpSeqNum, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_CLIENT_VERSION:
|
|
{
|
|
if (RC_BAD( rc = readNumber( uiTag, &m_uiClientVersion, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_DICT_FILE_PATH:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readUTF( m_pPool,
|
|
&m_puzDictPath)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_DICT_BUFFER:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readUTF( m_pPool, &m_puzDictBuf)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_PASSWORD:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readBinary( m_pPool,
|
|
&m_pucPassword, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_TYPE:
|
|
{
|
|
if (RC_BAD( rc = readNumber( uiTag, &m_uiType, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_AREA_ID:
|
|
{
|
|
if (RC_BAD( rc = readNumber( uiTag, &m_uiAreaId, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_FILE_NAME:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readUTF( m_pPool, &m_puzFileName)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_AUTOTRANS:
|
|
{
|
|
if (RC_BAD( rc = readNumber( uiTag, &m_uiAutoTrans, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_ITERATOR_SELECT:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readHTD( m_pPool, 0, 0,
|
|
&m_pIteratorSelect, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_ITERATOR_FROM:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readHTD( m_pPool, 0, 0,
|
|
&m_pIteratorFrom, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_ITERATOR_WHERE:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readHTD( m_pPool, 0, 0,
|
|
&m_pIteratorWhere, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_ITERATOR_CONFIG:
|
|
{
|
|
if (RC_BAD( rc = m_pDIStream->readHTD( m_pPool, 0, 0,
|
|
&m_pIteratorConfig, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WIRE_VALUE_MAX_LOCK_WAIT:
|
|
{
|
|
if (RC_BAD( rc = readNumber( uiTag, &m_uiMaxLockWait, NULL)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
if (RC_BAD( rc = skipValue( uiTag)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
return (rc);
|
|
}
|