Skip to content

Commit

Permalink
#672 Add support for nbackup GUID backup and in-place restore
Browse files Browse the repository at this point in the history
  • Loading branch information
mrotteveel committed Jul 3, 2021
1 parent af26685 commit 2a03497
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 16 deletions.
7 changes: 7 additions & 0 deletions src/documentation/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ The following has been changed or fixed since Jaybird 4.0.3
set. As a result, calling `getXXX` for that row after the update would
return `null` for the updated rows. The update was correctly persisted to
the database.
- New feature: Support for NBackup GUID-based backup and in-place restore ([jaybird#672](https://github.com/FirebirdSQL/jaybird/issues/672)) \
The `org.firebirdsql.management.NBackupManager` interface has two new
methods: `setBackupGuid(String)` expecting the brace-enclosed GUID of a
previous backup to use as the starting point for this backup, and
`setInPlaceRestore(boolean)` to enable (or disable) in-place restore. These
options require Firebird 4.0 or higher. \
This feature was backported from Jaybird 5.

Jaybird 4.0.3
-------------
Expand Down
1 change: 1 addition & 0 deletions src/main/org/firebirdsql/gds/ClumpletReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ public ClumpletType getClumpletType(byte tag) throws SQLException {
case isc_spb_nbk_file:
case isc_spb_nbk_direct:
case isc_spb_dbname:
case isc_spb_nbk_guid:
return ClumpletType.StringSpb;
case isc_spb_nbk_level:
case isc_spb_options:
Expand Down
3 changes: 3 additions & 0 deletions src/main/org/firebirdsql/gds/ISCConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,10 @@ public interface ISCConstants {
int isc_spb_nbk_level = 5;
int isc_spb_nbk_file = 6;
int isc_spb_nbk_direct = 7;
int isc_spb_nbk_guid = 8;
int isc_spb_nbk_no_triggers = 0x01;
int isc_spb_nbk_inplace = 0x02;
int isc_spb_nbk_sequence = 0x04;

/*****************************
* Service action items *
Expand Down
56 changes: 46 additions & 10 deletions src/main/org/firebirdsql/management/FBNBackupManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ public class FBNBackupManager extends FBServiceManager implements NBackupManager

private final List<String> backupFiles = new ArrayList<>();

private int backupLevel;
private int backupLevel = -1;
private String backupGuid;
private boolean noDBTriggers;
private boolean inPlaceRestore;

/**
* Create a new instance of <code>FBNBackupManager</code> based on the default GDSType.
Expand Down Expand Up @@ -67,22 +69,22 @@ public FBNBackupManager(GDSType gdsType) {
super(gdsType);
}

@Override
public void setBackupFile(String backupFile) {
addBackupFile(backupFile);
}

@Override
public void addBackupFile(String backupFile) {
backupFiles.add(backupFile);
}

@Override
public void clearBackupFiles() {
backupFiles.clear();
}

public void setDatabase(String database) {
super.setDatabase(database);
}

@Override
public void backupDatabase() throws SQLException {
try (FbService service = attachServiceManager()) {
executeServicesOperation(service, getBackupSRB(service));
Expand All @@ -100,15 +102,21 @@ private ServiceRequestBuffer getBackupSRB(FbService service) throws SQLException
ServiceRequestBuffer backupSPB = service.createServiceRequestBuffer();
backupSPB.addArgument(isc_action_svc_nbak);
backupSPB.addArgument(isc_spb_dbname, getDatabase());
if (backupFiles.size() == 0) {
if (backupFiles.isEmpty()) {
throw new SQLException("No backup file specified");
}
String backupFile = backupFiles.get(0);

backupSPB.addArgument(isc_spb_nbk_file, backupFile);
backupSPB.addArgument(isc_spb_nbk_level, backupLevel);
if (noDBTriggers) {
backupSPB.addArgument(isc_spb_options, isc_spb_nbk_no_triggers);
// Previously, the default level was 0, retain that default if no backup GUID has been set
int resolvedBackupLevel = backupLevel == -1 && backupGuid == null ? 0 : backupLevel;
backupSPB.addArgument(isc_spb_nbk_level, resolvedBackupLevel);
if (backupGuid != null) {
backupSPB.addArgument(isc_spb_nbk_guid, backupGuid);
}
int options = getOptions();
if (options != 0) {
backupSPB.addArgument(isc_spb_options, options);
}

return backupSPB;
Expand All @@ -117,6 +125,7 @@ private ServiceRequestBuffer getBackupSRB(FbService service) throws SQLException
/**
* @see org.firebirdsql.management.NBackupManager#restoreDatabase()
*/
@Override
public void restoreDatabase() throws SQLException {
try (FbService service = attachServiceManager()) {
executeServicesOperation(service, getRestoreSRB(service));
Expand All @@ -133,22 +142,49 @@ private ServiceRequestBuffer getRestoreSRB(FbService service) throws SQLExceptio
restoreSPB.addArgument(isc_action_svc_nrest);
restoreSPB.addArgument(isc_spb_dbname, getDatabase());

if (backupFiles.size() == 0) {
if (backupFiles.isEmpty()) {
throw new SQLException("No backup file specified");
}
for (String backupFile : backupFiles) {
restoreSPB.addArgument(isc_spb_nbk_file, backupFile);
}
int options = getOptions();
if (options != 0) {
restoreSPB.addArgument(isc_spb_options, options);
}

return restoreSPB;
}

private int getOptions() {
int options = 0;
if (noDBTriggers) {
options |= isc_spb_nbk_no_triggers;
}
if (inPlaceRestore) {
options |= isc_spb_nbk_inplace;
}
return options;
}

@Override
public void setBackupLevel(int backupLevel) {
this.backupLevel = backupLevel;
}

@Override
public void setBackupGuid(String guid) {
backupGuid = guid;
}

@Override
public void setNoDBTriggers(boolean noDBTriggers) {
this.noDBTriggers = noDBTriggers;
}

@Override
public void setInPlaceRestore(boolean inPlaceRestore) {
this.inPlaceRestore = inPlaceRestore;
}

}
42 changes: 36 additions & 6 deletions src/main/org/firebirdsql/management/NBackupManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,29 @@
* via the Firebird Services API.
*
* @author <a href="mailto:tsteinmaurer@users.sourceforge.net">Thomas Steinmaurer</a>
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
*/
public interface NBackupManager extends ServiceManager {

/**
* Sets the location of the backup file.
* <p>
* Warning: this method behaves identical to {@link #addBackupFile(String)}.
* </p>
*
* @param backupFile
* the location of the backup file.
*/
void setBackupFile(String backupFile);

/**
* Add the file to the backup of the specified size. Firebird allows
* splitting the backup into multiple files, limiting the size of the backup
* file. This can be useful for example for creating a backup on CD or DVD.
* Add additional backup files.
* <p>
* Specifying multiple backup files is only valid for restore, for backup only the first file is used.
* </p>
* <p>
* Use {@link #clearBackupFiles()} to clear earlier backup files.
* </p>
*
* @param backupFile
* the location of the backup file.
Expand Down Expand Up @@ -99,10 +107,32 @@ public interface NBackupManager extends ServiceManager {
void setBackupLevel(int level);

/**
* Sets the backup option no database triggers when connecting
* at backup.
* Sets the backup GUID (Firebird 4 and higher only).
* <p>
* The backup GUID is the GUID of a previous backup of the (source) database. This is used by Firebird to backup
* the pages modified since that backup.
* </p>
* <p>
* This setting is mutually exclusive with {@link #setBackupLevel(int)}, but this is only checked server-side.
* </p>
*
* @param noDBTriggers
* @param guid A GUID string of a previous backup, enclosed in braces.
* @since 4.0.4
*/
void setBackupGuid(String guid);

/**
* Sets the option no database triggers when connecting at backup or in-place restore.
*
* @param noDBTriggers {@code true} disable db triggers during backup or in-place restore.
*/
void setNoDBTriggers(boolean noDBTriggers);

/**
* Enables in-place restore.
*
* @param inPlaceRestore {@code true} to enable in-place restore
* @since 4.0.4
*/
void setInPlaceRestore(boolean inPlaceRestore);
}
14 changes: 14 additions & 0 deletions src/main/org/firebirdsql/util/FirebirdSupportInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,20 @@ public boolean supportsStatementTimeouts() {
return isVersionEqualOrAbove(4, 0);
}

/**
* @return {@code true} when this Firebird version supports NBackup backup with GUID
*/
public boolean supportsNBackupWithGuid() {
return isVersionEqualOrAbove(4, 0);
}

/**
* @return {@code true} when this Firebird version supports NBackup in-place restore
*/
public boolean supportsNBackupInPlaceRestore() {
return isVersionEqualOrAbove(4, 0);
}

/**
* @param serverVersion
* Server version
Expand Down
Loading

0 comments on commit 2a03497

Please sign in to comment.