// // sqlsnap.h Define the interface to the nt/sql snapshot handler. // // The idea here is for a pure interface, making it easy to keep the // abstraction maximized (can move to COM later, if we like). // // No C++ exceptions will be thrown across the interfaces. // // To use this interface, the calling process must invoke: // InitSQLEnvironment - once to setup the environment, establishing // the error and trace loggers. // The trace logger is optional, but an error logger must be provided. // The loggers are created by deriving from CLogFacility and implementing // a "WriteImplementation" method. // // Thereafter, calls to "CreateSqlSnapshot" are used to create snapshot objects // which encapsulate the operations needed to support storage snapshots. // // ***************************************** // LIMITATIONS // // - only SIMPLE databases can be snapshot (trunc on checkpoint = 'true') // Exception: SQL2000 full recovery db's are allowed. But master can't be restored with them. // - there is no serialization of services starting or adding/changing file lists during the snapshot // - servers which are not started when the snapshot starts are skipped (non-torn databases will be // backed up fine, torn databases won't be detected). // - sql7.0 databases which are "un"-useable will prevent snapshots (the list of files can't be obtained). // #include #include #include //////////////////////////////////////////////////////////////////////// // 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 "INCSQLSH" // //////////////////////////////////////////////////////////////////////// HRESULT InitSQLEnvironment(); // Caller must provide a path checker interface. // Used to provide info about the snapshot class CCheckPath { public: // ComponentBased snapshots can deal with non-simple recovery. // The backup app must handle VDI metadata if rollforward will be supported. // virtual bool IsComponentBased () throw() = 0; // ComponentBased snapshots provide an explicit list of databases // virtual PCWSTR EnumerateSelectedDatabases (const WCHAR *instanceName, UINT* nextIndex) throw () = 0; // return true if Path is part of the snapshot // Only intended for non-component-based backups. // virtual bool IsPathInSnapshot (const WCHAR* path) throw () = 0; }; //------------------------------------------------------------------ // Provide information Post-Freeze (or Thaw) about the databases // which were frozen and which support VDI metadata. // struct FrozenDatabaseInfo { const WCHAR* serverName; const WCHAR* databaseName; // BOOL isSimpleRecovery; THIS ISN'T CONVENIENTLY AVAILABLE....DO WE NEED IT? UINT metaDataSize; const BYTE* pMetaData; }; //------------------------------------------------------------- // A handler for snapshots. // class CSqlSnapshot { public: virtual ~CSqlSnapshot () throw () {}; virtual HRESULT Prepare ( CCheckPath* checker) throw () = 0; virtual HRESULT Freeze () throw () = 0; virtual HRESULT Thaw () throw () = 0; // Call this at "Post-snapshot" time, after all databases are frozen and MD is complete. // // Iterate over the databases which were frozen. // Valid to call this after Freeze, Thaw until destruction or Prepare(). // virtual HRESULT GetFirstDatabase (FrozenDatabaseInfo* fInfo) throw () = 0; virtual HRESULT GetNextDatabase (FrozenDatabaseInfo* fInfo) throw () = 0; }; extern "C" CSqlSnapshot* CreateSqlSnapshot () throw (); //------------------------------------------------------------- // Handle the restore operations for "composite restore" situations. // // An object is used to cache the connection to a single instance. // Thus the caller should perform operations grouped by instance. // class CSqlRestore { public: // Inform SQLServer that data laydown is desired on the full database. // Performs a DETACH, freeing the files. // virtual HRESULT PrepareToRestore ( const WCHAR* pInstance, const WCHAR* pDatabase) throw () = 0; // After data is laid down, this performs RESTORE WITH SNAPSHOT[,NORECOVERY] // virtual HRESULT FinalizeRestore ( const WCHAR* pInstance, const WCHAR* pDatabase, bool compositeRestore, // true if WITH NORECOVERY desired const BYTE* pMetadata, // metadata obtained from BACKUP unsigned int dataLen) // size of metadata (in bytes) throw () = 0; }; extern "C" CSqlRestore* CreateSqlRestore () throw (); //------------------------------------------------------------- // An enumerator for SQL objects. // // An object of this class can have only one active query at // a time. Requesting a new enumeration will close any previous // partially fetched result. // #define MAX_SERVERNAME 128 #define MAX_DBNAME 128 struct ServerInfo { bool isOnline; // true if the server is ready for connections // bool supportsCompositeRestore; // true if >=SQL2000 (RESTORE WITH NORECOVERY,SNAPSHOT) // not readily available. Ask Brian if we really need it.... // this is easy to obtain when the databases are being enumerated. // WCHAR name [MAX_SERVERNAME]; // null terminated name of server }; struct DatabaseInfo { bool isSimpleRecovery; // true if the recovery model is "SIMPLE" bool supportsFreeze; // true if this database can freeze (via dbcc or backup) UINT32 status; // status bits WCHAR name [MAX_DBNAME]; // null terminated name of database }; struct DatabaseFileInfo { bool isLogFile; // true if this is a log file WCHAR name [MAX_PATH]; }; // A heirarchical enumerator // server(instance) (1:N) databases (1:N) files // ...add doc... // class CSqlEnumerator { public: virtual ~CSqlEnumerator () throw () {}; virtual HRESULT FirstServer ( ServerInfo* pServer) throw () = 0; virtual HRESULT NextServer ( ServerInfo* pServer) throw () = 0; virtual HRESULT FirstDatabase ( const WCHAR* pServerName, DatabaseInfo* pDbInfo) throw () = 0; virtual HRESULT NextDatabase ( DatabaseInfo* pDbInfo) throw () = 0; virtual HRESULT FirstFile ( const WCHAR* pServerName, const WCHAR* pDbName, DatabaseFileInfo* pFileInfo) throw () = 0; virtual HRESULT NextFile ( DatabaseFileInfo* pFileInfo) throw () = 0; }; extern "C" CSqlEnumerator* CreateSqlEnumerator () throw (); //------------------------------------------------------ // HRESULTS returned by the interface. // // WARNING: I used facility = x78 arbitrarily! // #define SQLLIB_ERROR(code) MAKE_HRESULT(SEVERITY_ERROR, 0x78, code) #define SQLLIB_STATUS(code) MAKE_HRESULT(SEVERITY_SUCCESS, 0x78, code) // Status codes // #define S_SQLLIB_NOSERVERS SQLLIB_STATUS(1) // no SQLServers of interest (from Prepare) // Error codes // #define E_SQLLIB_GENERIC SQLLIB_ERROR(1) // something bad, check the errorlog #define E_SQLLIB_TORN_DB SQLLIB_ERROR(2) // database would be torn by the snapshot #define E_SQLLIB_NO_SUPPORT SQLLIB_ERROR(3) // 6.5 doesn't support snapshots #define E_SQLLIB_PROTO SQLLIB_ERROR(4) // protocol error (ex: freeze before prepare) #define E_SQLLIB_NONSIMPLE SQLLIB_ERROR(5) // only simple databases are supported