Added DbSystem.dbRebuild to C#. Also added a unit test for it.

git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@878 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
dsandersoremutah
2006-09-20 17:33:52 +00:00
parent deb8ddd1eb
commit cb890340dc
5 changed files with 500 additions and 31 deletions

View File

@@ -359,6 +359,46 @@ namespace cstest
return( true);
}
//--------------------------------------------------------------------------
// Rebuild database test.
//--------------------------------------------------------------------------
static bool rebuildDbTest(
string sSrcDbName,
string sDestDbName,
DbSystem dbSystem)
{
MyDbRebuildStatus dbRebuildStatus = null;
CREATE_OPTS createOpts = null;
// Try restoring the database
beginTest( "Rebuild Database Test (" + sSrcDbName + " to " + sDestDbName + ")");
dbRebuildStatus = new MyDbRebuildStatus();
createOpts = new CREATE_OPTS();
createOpts.uiBlockSize = 8192;
createOpts.uiVersionNum = (uint)DBVersions.XFLM_CURRENT_VERSION_NUM;
createOpts.uiMinRflFileSize = 2000000;
createOpts.uiMaxRflFileSize = 20000000;
createOpts.bKeepRflFiles = 1;
createOpts.bLogAbortedTransToRfl = 1;
createOpts.uiDefaultLanguage = (uint)Languages.FLM_DE_LANG;
try
{
dbSystem.dbRebuild( sSrcDbName, null, sDestDbName, null, null,
null, null, createOpts, dbRebuildStatus);
}
catch (XFlaimException ex)
{
endTest( dbRebuildStatus.outputLines(), ex, "rebuilding database");
return( false);
}
endTest( true, true);
return( true);
}
//--------------------------------------------------------------------------
// Remove database test.
//--------------------------------------------------------------------------
@@ -460,6 +500,13 @@ namespace cstest
return;
}
// Database rebuild test
if (!rebuildDbTest( RESTORE_DB_NAME, REBUILD_DB_NAME, dbSystem))
{
return;
}
// Database check test
if (!checkDbTest( CREATE_DB_NAME, dbSystem))
@@ -478,6 +525,10 @@ namespace cstest
{
return;
}
if (!checkDbTest( REBUILD_DB_NAME, dbSystem))
{
return;
}
// Database remove test
@@ -497,6 +548,10 @@ namespace cstest
{
return;
}
if (!removeDbTest( dbSystem, REBUILD_DB_NAME))
{
return;
}
}
}
@@ -859,6 +914,43 @@ namespace cstest
}
}
public class PrintCorruption
{
public static void printCorruption(
XFLM_CORRUPT_INFO corruptInfo)
{
System.Console.WriteLine( "\nCorruption Found: {0}, Locale: {1}",
corruptInfo.eErrCode, corruptInfo.eErrLocale);
if (corruptInfo.uiErrLfNumber != 0)
{
System.Console.WriteLine( " Logical File Number...... {0} ({1})",
corruptInfo.uiErrLfNumber, corruptInfo.eErrLfType);
System.Console.WriteLine( " B-Tree Level............. {0}",
corruptInfo.uiErrBTreeLevel);
}
if (corruptInfo.uiErrBlkAddress != 0)
{
System.Console.WriteLine( " Block Address............ {0:X})",
corruptInfo.uiErrBlkAddress);
}
if (corruptInfo.uiErrParentBlkAddress != 0)
{
System.Console.WriteLine( " Parent Block Address..... {0:X})",
corruptInfo.uiErrParentBlkAddress);
}
if (corruptInfo.uiErrElmOffset != 0)
{
System.Console.WriteLine( " Element Offset........... {0})",
corruptInfo.uiErrElmOffset);
}
if (corruptInfo.ulErrNodeId != 0)
{
System.Console.WriteLine( " Node ID.................. {0})",
corruptInfo.ulErrNodeId);
}
}
}
public class MyDbCheckStatus : DbCheckStatus
{
public MyDbCheckStatus()
@@ -891,35 +983,44 @@ namespace cstest
public RCODE reportCheckErr(
XFLM_CORRUPT_INFO corruptInfo)
{
System.Console.WriteLine( "\nCorruption Found: {0}, Locale: {1}",
corruptInfo.eErrCode, corruptInfo.eErrLocale);
if (corruptInfo.uiErrLfNumber != 0)
PrintCorruption.printCorruption( corruptInfo);
m_bOutputLines = true;
return( RCODE.NE_XFLM_OK);
}
public bool outputLines()
{
return( m_bOutputLines);
}
private bool m_bOutputLines;
}
public class MyDbRebuildStatus : DbRebuildStatus
{
public MyDbRebuildStatus()
{
m_bOutputLines = false;
System.Console.Write( "\n");
}
public RCODE reportRebuild(
XFLM_REBUILD_INFO rebuildInfo)
{
if (rebuildInfo.bStartFlag != 0)
{
System.Console.WriteLine( " Logical File Number...... {0} ({1})",
corruptInfo.uiErrLfNumber, corruptInfo.eErrLfType);
System.Console.WriteLine( " B-Tree Level............. {0}",
corruptInfo.uiErrBTreeLevel);
}
if (corruptInfo.uiErrBlkAddress != 0)
{
System.Console.WriteLine( " Block Address............ {0:X})",
corruptInfo.uiErrBlkAddress);
}
if (corruptInfo.uiErrParentBlkAddress != 0)
{
System.Console.WriteLine( " Parent Block Address..... {0:X})",
corruptInfo.uiErrParentBlkAddress);
}
if (corruptInfo.uiErrElmOffset != 0)
{
System.Console.WriteLine( " Element Offset........... {0})",
corruptInfo.uiErrElmOffset);
}
if (corruptInfo.ulErrNodeId != 0)
{
System.Console.WriteLine( " Node ID.................. {0})",
corruptInfo.ulErrNodeId);
System.Console.WriteLine( "\nRebuild Phase: {0}", rebuildInfo.eDoingFlag);
}
System.Console.Write( "Bytes To Do {0}, Bytes Done: {1}\r",
rebuildInfo.ulDatabaseSize, rebuildInfo.ulBytesExamined);
m_bOutputLines = true;
return( RCODE.NE_XFLM_OK);
}
public RCODE reportRebuildErr(
XFLM_CORRUPT_INFO corruptInfo)
{
PrintCorruption.printCorruption( corruptInfo);
m_bOutputLines = true;
return( RCODE.NE_XFLM_OK);
}

View File

@@ -881,3 +881,92 @@ Exit:
return( rc);
}
typedef RCODE (FLMAPI * DB_REBUILD_STATUS)(
FLMBOOL bHaveRebuildInfo,
XFLM_REBUILD_INFO * pRebuildInfo,
XFLM_CORRUPT_INFO * pCorruptInfo);
/****************************************************************************
Desc:
****************************************************************************/
class CS_DbRebuildStatus : public IF_DbRebuildStatus
{
public:
CS_DbRebuildStatus(
DB_REBUILD_STATUS fnDbRebuildStatus)
{
m_fnDbRebuildStatus = fnDbRebuildStatus;
}
virtual ~CS_DbRebuildStatus()
{
}
RCODE FLMAPI reportRebuild(
XFLM_REBUILD_INFO * pRebuildInfo)
{
return( m_fnDbRebuildStatus( TRUE, pRebuildInfo, NULL));
}
RCODE FLMAPI reportRebuildErr(
XFLM_CORRUPT_INFO * pCorruptInfo)
{
return( m_fnDbRebuildStatus( FALSE, NULL, pCorruptInfo));
}
private:
DB_REBUILD_STATUS m_fnDbRebuildStatus;
};
/****************************************************************************
Desc:
****************************************************************************/
FLMEXTC FLMEXP RCODE FLMAPI xflaim_DbSystem_dbRebuild(
FLMUINT64 ui64This,
const char * pszSourceDbPath,
const char * pszSourceDataDir,
const char * pszDestDbPath,
const char * pszDestDataDir,
const char * pszDestRflDir,
const char * pszDictPath,
const char * pszPassword,
XFLM_CREATE_OPTS * pCreateOpts,
DB_REBUILD_STATUS fnRebuildStatus)
{
RCODE rc = NE_XFLM_OK;
IF_DbSystem * pDbSystem = ((IF_DbSystem *)(FLMUINT)ui64This);
IF_DbRebuildStatus * pDbRebuildStatus = NULL;
FLMUINT64 ui64TotNodes;
FLMUINT64 ui64NodesRecov;
FLMUINT64 ui64DiscardedDocs;
if (fnRebuildStatus)
{
if ((pDbRebuildStatus = f_new CS_DbRebuildStatus( fnRebuildStatus)) == NULL)
{
rc = RC_SET( NE_XFLM_MEM);
goto Exit;
}
}
if (RC_BAD( rc = pDbSystem->dbRebuild( pszSourceDbPath, pszSourceDataDir,
pszDestDbPath, pszDestDataDir, pszDestRflDir,
pszDictPath, pszPassword, pCreateOpts,
&ui64TotNodes, &ui64NodesRecov, &ui64DiscardedDocs,
pDbRebuildStatus)))
{
goto Exit;
}
Exit:
if (pDbRebuildStatus)
{
pDbRebuildStatus->Release();
}
return( rc);
}

View File

@@ -282,6 +282,10 @@ namespace xflaim
return m_pDbSystem;
}
//-----------------------------------------------------------------------------
// dbCreate
//-----------------------------------------------------------------------------
/// <summary>
/// Creates a new XFlaim database.
/// </summary>
@@ -350,8 +354,12 @@ namespace xflaim
return( db);
}
//-----------------------------------------------------------------------------
// dbOpen
//-----------------------------------------------------------------------------
/// <summary>
/// Creates a new XFlaim database.
/// Opens an existing XFlaim database.
/// </summary>
/// <param name="sDbFileName">
/// See documentation on <see cref="dbCreate"/>.
@@ -396,6 +404,10 @@ namespace xflaim
return( db);
}
//-----------------------------------------------------------------------------
// dbRemove
//-----------------------------------------------------------------------------
/// <summary>
/// Removes (deletes) an XFlaim database.
/// </summary>
@@ -427,6 +439,10 @@ namespace xflaim
}
}
//-----------------------------------------------------------------------------
// dbRestore
//-----------------------------------------------------------------------------
/// <summary>
/// Restores a previously backed up database. The <paramref name="sBackupPath"/> parameter
/// and the <paramref name="restoreClient"/> parameter are mutually exclusive. If the
@@ -720,6 +736,10 @@ namespace xflaim
private RestoreStatus m_restoreStatus;
}
//-----------------------------------------------------------------------------
// dbCheck
//-----------------------------------------------------------------------------
/// <summary>
/// Check for physical and logical corruptions on the specified database.
/// </summary>
@@ -819,6 +839,10 @@ namespace xflaim
private DbCheckStatus m_dbCheckStatus;
}
//-----------------------------------------------------------------------------
// dbCopy
//-----------------------------------------------------------------------------
/// <summary>
/// Makes a copy of an existing database.
/// </summary>
@@ -916,6 +940,10 @@ namespace xflaim
private DbCopyStatus m_dbCopyStatus;
}
//-----------------------------------------------------------------------------
// dbRename
//-----------------------------------------------------------------------------
/// <summary>
/// Rename a database.
/// </summary>
@@ -991,7 +1019,124 @@ namespace xflaim
private DbRenameStatus m_dbRenameStatus;
}
// PRIVATE METHODS THAT ARE IMPLEMENTED IN C AND C++
//-----------------------------------------------------------------------------
// dbRebuild
//-----------------------------------------------------------------------------
/// <summary>
/// Rebuild a database.
/// </summary>
/// <param name="sSourceDbPath">
/// The name of the control file of the database that is to be rebuilt.
/// </param>
/// <param name="sSourceDataDir">
/// The data file directory. See <see cref="dbCreate"/> for more information.
/// </param>
/// <param name="sDestDbPath">
/// The name of the control file of the destination
/// database that is to be built from the source database.
/// </param>
/// <param name="sDestDataDir">
/// The destination database's data file directory. See <see cref="dbCreate"/> for
/// more information.
/// </param>
/// <param name="sDestRflDir">
/// The destination database's roll-forward log
/// directory. See <see cref="dbCreate"/> for more information.
/// </param>
/// <param name="sDictPath">
/// The name of a file containing dictionary definitions that
/// are to be put into the destination database when it is created.
/// May be null.
/// </param>
/// <param name="sPassword">
/// Password for opening the source database. This is only needed
/// if the database key is currently wrapped in a password instead of the
/// local NICI storage key. May be null.
/// </param>
/// <param name="createOpts">
/// A <see cref="CREATE_OPTS"/> object that contains several parameters that
/// are used in the creation of the destination database.
/// </param>
/// <param name="rebuildStatus">
/// If non-null this is an object that implements the <see cref="DbRebuildStatus"/>
/// interface. It is a callback object that is used to report rebuild progress.
/// </param>
public void dbRebuild(
string sSourceDbPath,
string sSourceDataDir,
string sDestDbPath,
string sDestDataDir,
string sDestRflDir,
string sDictPath,
string sPassword,
CREATE_OPTS createOpts,
DbRebuildStatus rebuildStatus)
{
int rc;
DbRebuildStatusDelegate dbRebuildStatus = null;
DbRebuildStatusCallback fnDbRebuildStatus = null;
if (rebuildStatus != null)
{
dbRebuildStatus = new DbRebuildStatusDelegate( rebuildStatus);
fnDbRebuildStatus = new DbRebuildStatusCallback( dbRebuildStatus.funcDbRebuildStatus);
}
if ((rc = xflaim_DbSystem_dbRebuild( m_pDbSystem, sSourceDbPath, sSourceDataDir, sDestDbPath,
sDestDataDir, sDestRflDir, sDictPath, sPassword,
createOpts, fnDbRebuildStatus)) != 0)
{
throw new XFlaimException( rc);
}
}
private delegate RCODE DbRebuildStatusCallback(
int bHaveRebuildInfo,
IntPtr pRebuildInfo,
IntPtr pCorruptInfo);
private class DbRebuildStatusDelegate
{
public DbRebuildStatusDelegate(
DbRebuildStatus dbRebuildStatus)
{
m_dbRebuildStatus = dbRebuildStatus;
}
~DbRebuildStatusDelegate()
{
}
public RCODE funcDbRebuildStatus(
int bHaveRebuildInfo,
IntPtr pRebuildInfo,
IntPtr pCorruptInfo)
{
RCODE rc = RCODE.NE_XFLM_OK;
if (bHaveRebuildInfo != 0)
{
rc = m_dbRebuildStatus.reportRebuild(
(XFLM_REBUILD_INFO)Marshal.PtrToStructure( pRebuildInfo,
typeof( XFLM_REBUILD_INFO)));
}
else
{
XFLM_CORRUPT_INFO corruptInfo = new XFLM_CORRUPT_INFO();
rc = m_dbRebuildStatus.reportRebuildErr(
(XFLM_CORRUPT_INFO)Marshal.PtrToStructure( pCorruptInfo,
typeof( XFLM_CORRUPT_INFO)));
}
return( rc);
}
private DbRebuildStatus m_dbRebuildStatus;
}
//-----------------------------------------------------------------------------
// PRIVATE METHODS THAT ARE IMPLEMENTED IN C AND C++
//-----------------------------------------------------------------------------
[DllImport("xflaim")]
private static extern int xflaim_DbSystem_createDbSystem(
@@ -1073,6 +1218,19 @@ namespace xflaim
int bOverwriteDestOk,
DbRenameStatusCallback fnDbRenameStatus);
[DllImport("xflaim",CharSet=CharSet.Ansi)]
private static extern int xflaim_DbSystem_dbRebuild(
ulong pDbSystem,
[MarshalAs(UnmanagedType.LPStr)] string pszSourceDbPath,
[MarshalAs(UnmanagedType.LPStr)] string pszSourceDataDir,
[MarshalAs(UnmanagedType.LPStr)] string pszDestDbPath,
[MarshalAs(UnmanagedType.LPStr)] string pszDestDataDir,
[MarshalAs(UnmanagedType.LPStr)] string pszDestRflDir,
[MarshalAs(UnmanagedType.LPStr)] string pszDictPath,
[MarshalAs(UnmanagedType.LPStr)] string pszPassword,
CREATE_OPTS pCreateOpts,
DbRebuildStatusCallback fnDbRebuildStatus);
private ulong m_pDbSystem;
}
}

View File

@@ -369,12 +369,10 @@ namespace xflaim
/// <summary>
/// Indicates whether we are just starting this phase of the operation. Value
/// will be non-zero if just starting, zero otherwise.
/// is currently in.
/// </summary>
public int bStartFlag;
/// <summary>
/// Total number of bytes in the database.
/// is currently in.
/// </summary>
public ulong ulDatabaseSize;
/// <summary>

View File

@@ -0,0 +1,123 @@
//------------------------------------------------------------------------------
// Desc: Db Rebuild Status
//
// Tabs: 3
//
// Copyright (c) 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$
//------------------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
namespace xflaim
{
/// <summary>
/// Phases of a rebuild operation.
/// </summary>
public enum RebuildPhase
{
/// <summary>Determining block size</summary>
REBUILD_GET_BLK_SIZ = 1,
/// <summary>Recovering the dictionary</summary>
REBUILD_RECOVER_DICT = 2,
/// <summary>Recovering non-dictionary data</summary>
REBUILD_RECOVER_DATA = 3
}
/// <summary>
/// Class that reports progress information for a <see cref="DbSystem.dbRebuild"/> operation.
/// It is returned in the <see cref="DbRebuildStatus.reportRebuild"/> method.
/// IMPORTANT NOTE: This structure needs to stay in sync with the XFLM_REBUILD_INFO
/// structure defined in xflaim.h
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class XFLM_REBUILD_INFO
{
/// <summary>Current phase of the rebuild operation</summary>
public RebuildPhase eDoingFlag;
/// <summary>
/// Indicates whether we are just starting this phase of the operation. Value
/// will be non-zero if just starting, zero otherwise.
/// </summary>
public int bStartFlag;
/// <summary>
/// Size of the database in bytes.
/// </summary>
public ulong ulDatabaseSize;
/// <summary>
/// Total bytes read so far.
/// </summary>
public ulong ulBytesExamined;
/// <summary>
/// Total DOM nodes found so far.
/// </summary>
public ulong ulTotNodes;
/// <summary>
/// Total DOM nodes recovered.
/// </summary>
public ulong ulNodesRecov;
/// <summary>
/// Total DOM nodes discarded.
/// </summary>
public ulong ulDiscardedDocs;
}
/// <summary>
/// This interface allows XFlaim to periodically pass information back to the
/// client about the status of an ongoing database rebuild operation. The
/// implementor may do anything it wants with the information, such as write
/// it to a log file or display it on the screen.
/// </summary>
public interface DbRebuildStatus
{
/// <summary>
/// Called by <see cref="DbSystem.dbRebuild"/> to report progress of the
/// rebuild operation.
/// </summary>
/// <param name="rebuildInfo">
/// This object contains information about the progress of the
/// rebuild operation.
/// </param>
/// <returns>
/// If the implementation object returns anything but RCODE.NE_XFLM_OK
/// the <see cref="DbSystem.dbRebuild"/> operation will abort and throw an
/// <see cref="XFlaimException"/>
/// </returns>
RCODE reportRebuild(
XFLM_REBUILD_INFO rebuildInfo);
/// <summary>
/// Called by <see cref="DbSystem.dbRebuild"/> to report corruptions found by the
/// rebuild operation.
/// </summary>
/// <param name="corruptInfo">
/// Information about the corruption is contained in this object.
/// </param>
/// <returns>
/// If the implementation object returns anything but RCODE.NE_XFLM_OK
/// the <see cref="DbSystem.dbRebuild"/> operation will abort and throw an
/// <see cref="XFlaimException"/>
/// </returns>
RCODE reportRebuildErr(
XFLM_CORRUPT_INFO corruptInfo);
}
}