Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

445 lines
8.7 KiB

// ***************************************************************************
// Copyright (C) 2000- Microsoft Corporation.
// @File: sqlsnapi.h
//
// PURPOSE:
//
// The internal include file for the sql snapshot module
//
// NOTES:
//
// HISTORY:
//
// @Version: Whistler/Shiloh
// 66601 srs 10/05/00 NTSNAP improvements
//
//
// @EndHeader@
// ***************************************************************************
#include <string>
#include <vector>
#include <list>
#include <oledb.h>
#include <oledberr.h>
#include <sqloledb.h>
#include "vdi.h" // interface declaration from SQLVDI kit
////////////////////////////////////////////////////////////////////////
// Standard foo for file name aliasing. This code block must be after
// all includes of VSS header files.
//
#ifdef VSS_FILE_ALIAS
#undef VSS_FILE_ALIAS
#endif
#define VSS_FILE_ALIAS "SQLSNPIH"
//
////////////////////////////////////////////////////////////////////////
typedef unsigned long ULONG;
typedef wchar_t WCHAR;
#define TRUE 1
#define FALSE 0
class CLogMsg;
// Unexpected, "internal" errors can be logged with some
// generic international text, like "Internal error: <English servicibility text>"
//
// Situations we expect, for which the user needs to know should
// occur with proper internationalization
//
// Process wide globals used by the sql modules
//
extern IMalloc * g_pIMalloc;
//-------------------------------------------------------------------------
//
typedef std::wstring WString;
typedef std::vector<WString> StringVector;
typedef StringVector::const_iterator StringVectorIter;
typedef std::list<WString> StringList;
typedef StringList::const_iterator StringListIter;
StringVector* EnumerateServers ();
//-------------------------------------------------------------------------
// Handle our simple needs for DB services.
//
// Useage:
// - Connect : establish a connection to a given server
// - SetCommand: setup the SQL text to send
// - ExecCommand: execute some SQL, returns TRUE if a result set
// is open and ready for retrieval
// - Get*: retrieve info from the result set
//
// The destructor will automatically disconnect from the server.
//
class SqlConnection
{
public:
SqlConnection () :
m_pCommandFactory (NULL),
m_pCommand (NULL),
m_pRowset (NULL),
m_pBuffer (NULL),
m_BufferSize (0),
m_hAcc (NULL),
m_pAccessor (NULL),
m_pBindings (NULL),
m_cBindings (0)
{}
~SqlConnection ();
void
Connect (const std::wstring& serverName);
void
Disconnect ();
void
ReleaseRowset ();
void
SetCommand (const std::wstring& command);
BOOL
ExecCommand ();
StringVector*
GetStringColumn ();
ULONG
GetServerVersion () {return m_ServerVersion;}
BOOL
FetchFirst ();
BOOL
FetchNext ();
void*
AccessColumn (int id);
private:
void LogOledbError
(
CVssFunctionTracer &ft,
CVssDebugInfo &dbgInfo,
LPCWSTR wszRoutine,
CLogMsg &msg
);
WString m_ServerName;
IDBCreateCommand* m_pCommandFactory;
ICommandText* m_pCommand;
IRowset* m_pRowset;
ULONG m_ServerVersion;
// used for the generic findfirst/findnext
DBBINDING* m_pBindings;
ULONG m_cBindings;
BYTE* m_pBuffer;
ULONG m_BufferSize;
HACCESSOR m_hAcc;
IAccessor* m_pAccessor;
};
BOOL
IsServerOnline (const WCHAR* serverName);
//-------------------------------------------------------------------------
// In SQL2000 we'll use VDI snapshots to avoid bug 58266: thaw fails.
//
// We'll prepare each database by starting a BACKUP WITH SNAPSHOT.
// This will require one thread per database.
// The backups will stall waiting for the VDI client to pull metadata.
// When the "freeze" message comes along, the controlling thread will
// pull all the BACKUPs to the frozen state.
// Later the "thaw" message results in gathering the "success" report
// from each thread.
//
//
class Freeze2000
{
public:
enum VDState
{
Unknown=0, Created, Open, SnapshotOpen
};
private:
class FrozenDatabase
{
friend Freeze2000;
FrozenDatabase () :
m_pContext (NULL),
m_hThread (NULL),
m_pIVDSet (NULL),
m_pIVD (NULL),
m_pSnapshotCmd (NULL),
m_VDState (Unknown),
m_SuccessDetected (FALSE)
{}
Freeze2000* m_pContext;
HANDLE m_hThread;
IClientVirtualDeviceSet2* m_pIVDSet;
IClientVirtualDevice* m_pIVD;
WString m_DbName;
VDC_Command* m_pSnapshotCmd;
VDState m_VDState;
WCHAR m_SetName [80];
bool m_SuccessDetected;
};
public:
Freeze2000 (
const WString& serverName,
ULONG maxDatabases);
~Freeze2000 ();
void
PrepareDatabase (
const WString& dbName);
void
WaitForPrepare ();
void
Freeze ();
BOOL
Thaw () throw ();
static DWORD
DatabaseThreadStart (LPVOID pContext);
private:
enum State {
Unprepared,
Preparing,
Prepared,
Frozen,
Complete,
Aborted
};
DWORD
DatabaseThread (
FrozenDatabase* pDbContext);
void
WaitForThreads ();
void
AdvanceVDState (bool toSnapshot);
void // race-free method to persist an abort condition
SetAbort ()
{
InterlockedIncrement (&m_AbortCount);
}
bool // return true if the freeze is aborting
CheckAbort ()
{
return 0 != InterlockedCompareExchange (&m_AbortCount, 0, 0);
}
void
Abort () throw ();
void
Lock ()
{
EnterCriticalSection (&m_Latch);
}
void
Unlock ()
{
LeaveCriticalSection (&m_Latch);
}
BOOL // return TRUE if we got the lock
TryLock ()
{
return TryEnterCriticalSection (&m_Latch);
}
LONG m_AbortCount;
CRITICAL_SECTION m_Latch;
State m_State;
WString m_ServerName;
GUID m_BackupId;
ULONG m_NumDatabases;
ULONG m_MaxDatabases;
FrozenDatabase* m_pDBContext;
};
//-------------------------------------------------------------------------
// Represent a server which can be frozen.
//
class FrozenServer
{
public:
FrozenServer (const std::wstring& serverName) :
m_Name (serverName),
m_pFreeze2000 (NULL)
{}
~FrozenServer ()
{
if (m_pFreeze2000)
{
delete m_pFreeze2000;
m_pFreeze2000 = NULL;
}
}
const std::wstring& GetName () const
{ return m_Name; }
BOOL
FindDatabasesToFreeze (
CCheckPath* checker);
BOOL
Prepare ();
BOOL
Freeze ();
BOOL
Thaw () throw ();
private:
BOOL
FindDatabases2000 (
CCheckPath* checker);
void
GetDatabaseProperties (const WString& dbName,
BOOL* pSimple,
BOOL* pOnline);
private:
std::wstring m_Name;
SqlConnection m_Connection;
StringList m_FrozenDatabases;
Freeze2000* m_pFreeze2000;
};
//-------------------------------------------------------------------------
//
class Snapshot : public CSqlSnapshot
{
enum Status {
NotInitialized,
Enumerated,
Prepared,
Frozen };
public:
HRESULT Prepare (
CCheckPath* checker) throw ();
HRESULT Freeze () throw ();
HRESULT Thaw () throw ();
Snapshot () {m_Status = NotInitialized;}
~Snapshot () throw ();
private:
void
Deinitialize ();
Status m_Status;
std::list<FrozenServer*> m_FrozenServers;
typedef std::list<FrozenServer*>::iterator ServerIter;
};
// We'll use very simple exception handling.
//
#define THROW_GENERIC throw exception ();
//----------------------------------------------------------
// Implement our simple enumeration service
//
class SqlEnumerator : public CSqlEnumerator
{
enum Status {
Unknown = 0,
DatabaseQueryActive,
FileQueryActive
};
public:
~SqlEnumerator () throw ();
SqlEnumerator () :
m_State (Unknown),
m_pServers (NULL)
{}
HRESULT FirstServer (
ServerInfo* pServer) throw ();
HRESULT NextServer (
ServerInfo* pServer) throw ();
HRESULT FirstDatabase (
const WCHAR* pServerName,
DatabaseInfo* pDbInfo) throw ();
HRESULT NextDatabase (
DatabaseInfo* pDbInfo) throw ();
HRESULT FirstFile (
const WCHAR* pServerName,
const WCHAR* pDbName,
DatabaseFileInfo* pDbInfo) throw ();
HRESULT NextFile (
DatabaseFileInfo* pDbInfo) throw ();
private:
Status m_State;
SqlConnection m_Connection;
StringVector* m_pServers;
int m_CurrServer;
};
#if defined (DEBUG)
// Type of assertion passed through to utassert_fail function.
//
#define DBG_ASSERT(exp) BS_ASSERT(exp)
// Allow for noop 64 bit asserts on win32 for things like
// overflowing 32 bit long, etc.
//
#ifdef _WIN64
#define DBG64_ASSERT(exp) BS_ASSERT(exp)
#else
#define DBG64_ASSERT(exp)
#endif
#else
#define DBG_ASSERT(exp)
#define DBG64_ASSERT(exp)
#define DBG_ASSERTSZ(exp, txt)
#endif