Writer Role in Backing Up Complex Stores

As with all important operations under VSS, incremental and differential backups require close cooperation between requesters and writers.

Backup Types

The infrastructure provides special support for five types of backup. They are described as follows:

  • Full (VSS_BT_FULL). Files will be backed up regardless of their last backup date. The backup history of each file will be updated, and this type of backup can be used as the basis of an incremental or differential backup. If there are log files, they may be truncated as a result of this backup.

    Restoring a full backup requires only a single backup image.

  • Differential (VSS_BT_DIFFERENTIAL). The VSS API is used to ensure that only files that have been changed or added since the last full backup are to be copied to a storage medium; all intermediate backup information is ignored. This may include entire files, or specific ranges within files. A differential backup is associated with a full backup, and generally cannot be restored until the full backup has been restored. If there are log files, they will usually not be truncated as a result of this backup.

    Restoring a differential backup requires the original backup image and the most recent differential backup image made since the last full backup.

  • Incremental (VSS_BT_INCREMENTAL). The VSS API is used to ensure that only files that have been changed or added since the last full or incremental backup are to be copied to a storage medium. This may include entire files, or specific ranges within files. Some writers do not allow incremental backups to be mixed with differential backups. If there are log files, they may be truncated as a result of this backup.

    Restoring an incremental backup requires the original backup image and all incremental backup images made since the initial backup.

  • Log Backup (VSS_BT_LOG). Only a writer's log files (files added to a component with the IVssCreateWriterMetadata::AddDataBaseLogFiles method, and retrieved by a call to IVssWMComponent::GetDatabaseLogFile) will be backed up. This backup type is specific to VSS. Log backups tend to be taken quite frequently. Typically, the log file will be truncated as a result of this backup.

  • Copy Backup (VSS_BT_COPY). Like the VSS_BT_FULL backup type, files will be backed up regardless of their last backup date. However, the backup history of each file will not be updated, and this type of backup cannot be used as the basis of an incremental or differential backup. Log files should never be truncated as a result of a copy backup.

Partial File Support

Some writers support file restoration through the overwriting of parts of the files they manage. A requester may be designed to take advantage of this, and if so it indicates this by setting the information in IVssBackupComponents::SetBackupState.

The writers indicate what type of backups are supported by calling IVssCreateWriterMetadata::SetBackupSchema while processing the Identify event. The dsSchemaMask parameter to the IVssCreateWriterMetadata::SetBackupSchema method is a bit mask indicating what types of backup are supported. All writers must support full backups.

VSS_BS_DIFFERENTIAL

Indicates support for differential backups.

VSS_BS_INCREMENTAL

Indicates support for incremental backups.

VSS_BS_LOG

Indicates support for log backups.

VSS_BS_COPY

Indicates support for copy backups.

VSS_BS_EXCLUSIVE_INCREMENTAL_DIFFERENTIAL

Indicates that a writer does not support mixing incremental backups with differential backups.

The writer can determine what type of backup is being performed by calling CVssWriter::GetBackupType. The earliest point when this can be performed is while processing the PrepareForBackup event. CVssWriter::GetBackupType will return a member of the VSS_BACKUP_TYPE enumeration. If the backup type is not supported by the writer, then the writer should treat the backup as a full backup.

Backup Stamps

Incremental and differential backups are always tied to a previous backup. There are two ways to tie backups. For simple data stores, the requester can keep track of the correlation between backups. However, for more complex data stores, the writer will need to maintain its own timestamp with the backup; this timestamp may keep track of log position, checkpoint information, and so on. A writer indicates that it needs its own timestamps by setting the VSS_BS_TIMESTAMPED bit when it calls IVssCreateWriterMetadata::SetBackupSchema.

A writer can store a timestamp with each component that is being backed up. The writer stores the timestamp by calling IVssComponent::SetBackupStamp, and passing in a string representation of the stamp for the wszBackupStamp parameter. Generally, a writer will call this method while processing the PostSnapshot event. However, for backups that do not involve a shadow copy, the PostSnapshot event will not be sent. In this case, IVssComponent::SetBackupStamp must be called while processing the PrepareForBackup event.

When an incremental or differential backup is being performed, the requester will indicate to the writer the backup stamp of the previous backup that is serving as a base for this backup. The writer can access this previous backup stamp while processing either the PrepareForBackup or PostSnapshot event, by calling IVssComponent::GetPreviousBackupStamp. The writer can use the returned stamp to determine what needs to be backed up.

Backup Strategies

File Backup Files Strategies

Often, certain files reported in the writer metadata need only be backed up when performing certain types of backup. Some files may only be required when performing a full backup. Other files may only be required when performing an incremental or differential backup. VSS provides a method for the writers to indicate this information to the requester. When adding files to components using IVssCreateWriterMetadata::AddDatabaseFiles, IVssCreateWriterMetadata::AddDatabaseLogFiles, or IVssCreateWriterMetadata::AddFilesToFileGroup, the dwBackupTypeMask parameter indicates for which backup types these files must be backed up. The mask can contain one or more of the following values:

VSS_FSBT_FULL_BACKUP_REQUIRED

Required for full backups.

VSS_FSBT_DIFFERENTIAL_BACKUP_REQUIRED

Required for differential backups.

VSS_FSBT_INCREMENTAL_BACKUP_REQUIRED

Required for incremental backups.

VSS_FSBT_LOG_BACKUP_REQUIRED

Required for log backups.

VSS_FSBT_ALL_BACKUP_REQUIRED

Required for all backup types; this is the default.

This specification overrides the component's selectivity specification. For example, consider a component whose files are all marked with VSS_FSBT_LOG_BACKUP_REQUIRED but not with VSS_FSBT_FULL_BACKUP_REQUIRED. Suppose this component is not selectable for backup (bSelectable was false when IVssCreateWriterMetadata::AddComponent was called). In the case of a log backup, this means that all the files in this component must always be backed up. However, in the case of a full backup, none of the files need to be backed up, despite the fact that the component's selectivity implies it should be backed up.

Backup By Last Modify Time

One way for a writer to indicate what files have changed is by using the differenced file mechanism. A writer can specify that certain files in a component should only be backed up if they have been modified since a certain time. The writer calls IVssComponent::AddDifferencedFilesByLastModifyTime with a file specification and a last modify time. IVssComponent::AddDifferencedFilesByLastModifyTime is typically called while processing the PostSnapshot event, although it can be called while processing the PrepareForBackup event. The requester must then back up all files matching the file specification that have changed since the specified time. If the writer is using the backup stamp mechanism, this last modify time will be determined based on the previous backup stamp in the backup document. The writer can also pass in zero for the last modify time, which indicates that the requester is responsible for determining the time of the last backup and the files changed since that time.

Partial File Backup

Another way for a writer to indicate changes to the requester is by using the partial-file mechanism. A writer can specify byte ranges within component files that need to be backed up; the writer may specify these file ranges while processing either the PostSnapshot or PrepareForBackup event. The writer calls IVssComponent::AddPartialFile to add partial file specifications to the backup. A partial file specification consists of a path and file name together with information about what ranges in the file need to be backed up.

File Specification Rules

IVssComponent::AddDifferencedFilesByLastModifyTime or IVssComponent::AddPartialFile can both be used to modify file specifications given during the Identify event, or to add completely new files to the specification. If the writer is modifying information set during the Identify event using IVssComponent::AddDifferencedFilesByLastModifyTime, then the file specification must exactly match one of the file specifications in the current component. The file specification must not partially overlap files in the current component, and it must not match files in any other components. Files specified using IVssComponent::AddPartialFile can, however, partially overlap another file specification. Information set by IVssComponent::AddDifferencedFilesByLastModifyTime or IVssComponent::AddPartialFile overrides the information set earlier using the IVssCreateWriterMetadata interface in response to the Identify event.

General file specifications can have an alternate-location value (set by the wszAlternateLocation parameter of IVssCreateWriterMetadata::AddFilesToFileGroup) that indicates an alternate location to obtain the file from at backup time. If the file specification set through the differenced-file or partial-file mechanisms matches an existing file specification that has an alternate location, the backup application will obtain the data from this alternate location.

If the file specification set in IVssComponent::AddDifferencedFilesByLastModifyTime or in IVssComponent::AddPartialFile does not match and files in the component that are being backed up, then all matching files are now added to the backup. Care must be taken that the writer only adds files that exist on a volume that is already being shadow copied while doing this; otherwise, the requester may fail to back up these files. If these functions are called while processing the PostSnapshot event, this can be determined by using the CVssWriter::IsPathAffected method. If called while handling the PrepareForBackup event, the writer must make this determination using another method.

Backup Without a Shadow Copy

Certain types of files may not need to be backed up off of a shadow copy volume. For example, this will often be true of database log files. Since log files grow monotonically, and a writer can specify exactly what portions of the file to back up using partial files, it will often be possible to back up the log off the original volume. As an optimization, a writer can mark which files require shadow copies for different backup types using the flags set in the dwBackupTypeMask parameter of IVssCreateWriterMetadata::AddDatabaseFiles, IVssCreateWriterMetadata::AddDatabaseLogFiles, or IVssCreateWriterMetadata::AddFilesToFileGroup. Supported flags include the following:

VSS_FSBT_FULL_SNAPSHOT_REQUIRED

Shadow copy required for full backups.

VSS_FSBT_DIFFERENTIAL_SNAPSHOT_REQUIRED

Shadow copy required for differential backups.

VSS_FSBT_INCREMENTAL_SNAPSHOT_REQUIRED

Shadow copy required for incremental backups.

VSS_FSBT_LOG_SNAPSHOT_REQUIRED

Shadow copy required for log backups.

VSS_FSBT_ALL_SNAPSHOT_REQUIRED

Shadow copy required for all backup types; this is the default.

If a specific volume contains only components that do not require a shadow copy for this backup, the requester can skip the step of creating a shadow copy for this volume. All the data on this volume can be copied to the backup media directly from the original volume.

Backup Cleanup

If the writer needs to perform log truncation or other post-backup cleanup, the proper place to do this is while processing the BackupComplete event. The BackupShutdown event will be sent some time after BackupComplete, so some cleanup may also be done in the BackupShutdown event handler.

The BackupShutdown event is always sent after termination of a backup. If the requester terminates abnormally while performing a backup, BackupShutdown will be sent immediately, without first sending BackupComplete. If the writer needs to clean up any state, that may be done here; however, log truncation should not happen in this event because the backup did not necessarily complete.

Restore Strategies

The basic tasks of writers at restore are to verify that the restore can happen in handling the PreRestore event, and that the restore has happened in handling the PostRestore event. More complex stores will also perform a recovery process in the PostRestore handler. If the restore is part of an incremental or differential restore, the writer will generally want to delay this recovery process until all incremental or differential restores have been completed. IVssComponent::GetAdditionalRestores will indicate whether this is the final restore of this component, or whether there are more restores to come. If IVssComponent::GetAdditionalRestores returns true, the writer should not perform its recovery procedure on that component.

New Targets

If supported by the writer, the requester can restore data files to a location other than the original backup-time location. A writer indicates support for this restore mode by setting the VSS_BS_WRITER_SUPPORTS_NEW_TARGET bit in the dsSchemaMask parameter when calling IVssCreateWriterMetadata::SetBackupSchema. A writer obtains the new locations for component files at restore time by calling IVssComponent::GetNewTargetCount and IVssComponent::GetNewTarget.

Directed Targets

For complicated restore scenarios, a writer may want to map ranges of a backed-up file onto different ranges of the same or a different file. This can be done by using the directed-target mechanism. To do this, a writer must first indicate this is happening by calling IVssComponent::SetRestoreTarget, passing in VSS_RT_DIRECTED for the target parameter. Then, for each mapping, the writer calls IVssComponent::AddDirectedTarget. This method takes a full path to a source file on the backup and a full path to a destination file that will be restored to. It also takes a ranges list for each of these files. The writer calls these functions while handling the PreRestore event, and the requester is then responsible for restoring the specified ranges in the source file to the mapped ranges in the destination file. The format of the ranges string is the same as in IVssComponent::AddPartialFile

Private Writer Metadata

It is often useful for a writer to maintain private metadata with a backup to properly perform an incremental or differential restore. A writer may call IVssComponent::SetBackupMetadata while handling either PrepareForBackup or PostSnapshot to store metadata. This metadata can be accessed by the writer during either PreRestore or PostRestore by calling IVssComponent::GetBackupMetadata. Metadata can also be stored with partial file specification by using the wszMetadata parameter of IVssComponent::AddPartialFile; this metadata is accessed through the pbstrMetadataparameter of IVssComponent::GetPartialFile. The writer can also pass metadata to itself between CVssWriter::OnPreRestore and CVssWriter::OnPostRestore. In CVssWriter::OnPreRestore, the metadata is set by calling IVssComponent::SetRestoreMetadata. In CVssWriter::OnPostRestore, the metadata is retrieved by calling IVssComponent::GetRestoreMetadata.