/** * Take a snapshot of the specified table and verify the given families. * Note that this will leave the table disabled in the case of an offline snapshot. */ public static void createSnapshotAndValidate(Admin admin, TableName tableName, List<byte[]> nonEmptyFamilyNames, List<byte[]> emptyFamilyNames, String snapshotNameString, Path rootDir, FileSystem fs, boolean onlineSnapshot) throws Exception { if (!onlineSnapshot) { try { admin.disableTable(tableName); } catch (TableNotEnabledException tne) { LOG.info("In attempting to disable " + tableName + " it turns out that the this table is " + "already disabled."); } } admin.snapshot(snapshotNameString, tableName); List<SnapshotDescription> snapshots = SnapshotTestingUtils.assertExistsMatchingSnapshot(admin, snapshotNameString, tableName); if (snapshots == null || snapshots.size() != 1) { Assert.fail("Incorrect number of snapshots for table " + tableName); } SnapshotTestingUtils.confirmSnapshotValid(snapshots.get(0), tableName, nonEmptyFamilyNames, emptyFamilyNames, rootDir, admin, fs); }
@Test(timeout = 300000) public void testAsyncFlushSnapshot() throws Exception { Admin admin = UTIL.getHBaseAdmin(); SnapshotDescription snapshot = SnapshotDescription.newBuilder().setName("asyncSnapshot") .setTable(TABLE_NAME.getNameAsString()) .setType(SnapshotDescription.Type.FLUSH) .build(); // take the snapshot async admin.takeSnapshotAsync(snapshot); // constantly loop, looking for the snapshot to complete HMaster master = UTIL.getMiniHBaseCluster().getMaster(); SnapshotTestingUtils.waitForSnapshotToComplete(master, snapshot, 200); LOG.info(" === Async Snapshot Completed ==="); UTIL.getHBaseCluster().getMaster().getMasterFileSystem().logFileSystemState(LOG); // make sure we get the snapshot SnapshotTestingUtils.assertOneSnapshotThatMatches(admin, snapshot); }
/** * Delete an existing snapshot. * @param snapshotName name of the snapshot * @throws IOException if a remote or network exception occurs */ @Override public void deleteSnapshot(final String snapshotName) throws IOException { // make sure the snapshot is possibly valid TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(snapshotName)); // do the delete executeCallable(new MasterCallable<Void>(getConnection()) { @Override public Void call(int callTimeout) throws ServiceException { PayloadCarryingRpcController controller = rpcControllerFactory.newController(); controller.setCallTimeout(callTimeout); master.deleteSnapshot(controller, DeleteSnapshotRequest.newBuilder(). setSnapshot(SnapshotDescription.newBuilder().setName(snapshotName).build()).build() ); return null; } }); }
/** * Check to see if there is a snapshot in progress with the same name or on the same table. * Currently we have a limitation only allowing a single snapshot per table at a time. Also we * don't allow snapshot with the same name. * @param snapshot description of the snapshot being checked. * @return <tt>true</tt> if there is a snapshot in progress with the same name or on the same * table. */ synchronized boolean isTakingSnapshot(final SnapshotDescription snapshot) { TableName snapshotTable = TableName.valueOf(snapshot.getTable()); if (isTakingSnapshot(snapshotTable)) { return true; } Iterator<Map.Entry<TableName, SnapshotSentinel>> it = this.snapshotHandlers.entrySet().iterator(); while (it.hasNext()) { Map.Entry<TableName, SnapshotSentinel> entry = it.next(); SnapshotSentinel sentinel = entry.getValue(); if (snapshot.getName().equals(sentinel.getSnapshot().getName()) && !sentinel.isFinished()) { return true; } } return false; }
/** * Take a snapshot using the specified handler. * On failure the snapshot temporary working directory is removed. * NOTE: prepareToTakeSnapshot() called before this one takes care of the rejecting the * snapshot request if the table is busy with another snapshot/restore operation. * @param snapshot the snapshot description * @param handler the snapshot handler */ private synchronized void snapshotTable(SnapshotDescription snapshot, final TakeSnapshotHandler handler) throws HBaseSnapshotException { try { handler.prepare(); this.executorService.submit(handler); this.snapshotHandlers.put(TableName.valueOf(snapshot.getTable()), handler); } catch (Exception e) { // cleanup the working directory by trying to delete it from the fs. Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(snapshot, rootDir); try { if (!this.master.getMasterFileSystem().getFileSystem().delete(workingDir, true)) { LOG.error("Couldn't delete working directory (" + workingDir + " for snapshot:" + ClientSnapshotDescriptionUtils.toString(snapshot)); } } catch (IOException e1) { LOG.error("Couldn't delete working directory (" + workingDir + " for snapshot:" + ClientSnapshotDescriptionUtils.toString(snapshot)); } // fail the snapshot throw new SnapshotCreationException("Could not build snapshot handler", e, snapshot); } }
/** * Return the handler if it is currently live and has the same snapshot target name. * The handler is removed from the sentinels map if completed. * @param sentinels live handlers * @param snapshot snapshot description * @return null if doesn't match, else a live handler. */ private synchronized SnapshotSentinel removeSentinelIfFinished( final Map<TableName, SnapshotSentinel> sentinels, final SnapshotDescription snapshot) { if (!snapshot.hasTable()) { return null; } TableName snapshotTable = TableName.valueOf(snapshot.getTable()); SnapshotSentinel h = sentinels.get(snapshotTable); if (h == null) { return null; } if (!h.getSnapshot().getName().equals(snapshot.getName())) { // specified snapshot is to the one currently running return null; } // Remove from the "in-progress" list once completed if (h.isFinished()) { sentinels.remove(snapshotTable); } return h; }
public RestoreSnapshotHandler(final MasterServices masterServices, final SnapshotDescription snapshot, final HTableDescriptor htd) throws IOException { super(EventType.C_M_RESTORE_SNAPSHOT, htd.getTableName(), masterServices, masterServices); // Snapshot information this.snapshot = snapshot; // Monitor this.monitor = new ForeignExceptionDispatcher(); // Check table exists. getTableDescriptor(); // This is the new schema we are going to write out as this modification. this.hTableDescriptor = htd; this.status = TaskMonitor.get().createStatus( "Restoring snapshot '" + snapshot.getName() + "' to table " + hTableDescriptor.getTableName()); }
/** * Take a snapshot without waiting for the server to complete that snapshot (asynchronous) * <p> * Only a single snapshot should be taken at a time, or results may be undefined. * @param snapshot snapshot to take * @return response from the server indicating the max time to wait for the snapshot * @throws IOException if the snapshot did not succeed or we lose contact with the master. * @throws SnapshotCreationException if snapshot creation failed * @throws IllegalArgumentException if the snapshot request is formatted incorrectly */ @Override public SnapshotResponse takeSnapshotAsync(SnapshotDescription snapshot) throws IOException, SnapshotCreationException { ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot); final SnapshotRequest request = SnapshotRequest.newBuilder().setSnapshot(snapshot) .build(); // run the snapshot on the master return executeCallable(new MasterCallable<SnapshotResponse>(getConnection()) { @Override public SnapshotResponse call(int callTimeout) throws ServiceException { PayloadCarryingRpcController controller = rpcControllerFactory.newController(); controller.setCallTimeout(callTimeout); return master.snapshot(controller, request); } }); }
public static void snapshot(Admin admin, final String snapshotName, final String tableName, SnapshotDescription.Type type, int numTries) throws IOException { int tries = 0; CorruptedSnapshotException lastEx = null; while (tries++ < numTries) { try { admin.snapshot(snapshotName, TableName.valueOf(tableName), type); return; } catch (CorruptedSnapshotException cse) { LOG.warn("Got CorruptedSnapshotException", cse); lastEx = cse; } } throw lastEx; }
/** * Test that we throw an exception if there is no working snapshot directory when we attempt to * 'complete' the snapshot * @throws Exception on failure */ @Test public void testCompleteSnapshotWithNoSnapshotDirectoryFailure() throws Exception { Path snapshotDir = new Path(root, HConstants.SNAPSHOT_DIR_NAME); Path tmpDir = new Path(snapshotDir, ".tmp"); Path workingDir = new Path(tmpDir, "not_a_snapshot"); assertFalse("Already have working snapshot dir: " + workingDir + " but shouldn't. Test file leak?", fs.exists(workingDir)); SnapshotDescription snapshot = SnapshotDescription.newBuilder().setName("snapshot").build(); try { SnapshotDescriptionUtils.completeSnapshot(snapshot, root, workingDir, fs); fail("Shouldn't successfully complete move of a non-existent directory."); } catch (IOException e) { LOG.info("Correctly failed to move non-existant directory: " + e.getMessage()); } }
/** * Make sure that there is only one snapshot returned from the master and its * name and table match the passed in parameters. */ public static List<SnapshotDescription> assertExistsMatchingSnapshot( Admin admin, String snapshotName, TableName tableName) throws IOException { // list the snapshot List<SnapshotDescription> snapshots = admin.listSnapshots(); List<SnapshotDescription> returnedSnapshots = new ArrayList<SnapshotDescription>(); for (SnapshotDescription sd : snapshots) { if (snapshotName.equals(sd.getName()) && tableName.equals(TableName.valueOf(sd.getTable()))) { returnedSnapshots.add(sd); } } Assert.assertTrue("No matching snapshots found.", returnedSnapshots.size()>0); return returnedSnapshots; }
/** * Helper method for testing async snapshot operations. Just waits for the * given snapshot to complete on the server by repeatedly checking the master. * * @param master: the master running the snapshot * @param snapshot: the snapshot to check * @param sleep: amount to sleep between checks to see if the snapshot is done * @throws ServiceException if the snapshot fails */ public static void waitForSnapshotToComplete(HMaster master, SnapshotDescription snapshot, long sleep) throws ServiceException { final IsSnapshotDoneRequest request = IsSnapshotDoneRequest.newBuilder() .setSnapshot(snapshot).build(); IsSnapshotDoneResponse done = IsSnapshotDoneResponse.newBuilder() .buildPartial(); while (!done.getDone()) { done = master.getMasterRpcServices().isSnapshotDone(null, request); try { Thread.sleep(sleep); } catch (InterruptedException e) { throw new ServiceException(e); } } }
/** * Convert the passed snapshot description into a 'full' snapshot description based on default * parameters, if none have been supplied. This resolves any 'optional' parameters that aren't * supplied to their default values. * @param snapshot general snapshot descriptor * @param conf Configuration to read configured snapshot defaults if snapshot is not complete * @return a valid snapshot description * @throws IllegalArgumentException if the {@link SnapshotDescription} is not a complete * {@link SnapshotDescription}. */ public static SnapshotDescription validate(SnapshotDescription snapshot, Configuration conf) throws IllegalArgumentException { if (!snapshot.hasTable()) { throw new IllegalArgumentException( "Descriptor doesn't apply to a table, so we can't build it."); } // set the creation time, if one hasn't been set long time = snapshot.getCreationTime(); if (time == SnapshotDescriptionUtils.NO_SNAPSHOT_START_TIME_SPECIFIED) { time = EnvironmentEdgeManager.currentTime(); LOG.debug("Creation time not specified, setting to:" + time + " (current time:" + EnvironmentEdgeManager.currentTime() + ")."); SnapshotDescription.Builder builder = snapshot.toBuilder(); builder.setCreationTime(time); snapshot = builder.build(); } return snapshot; }
/** * Write the snapshot description into the working directory of a snapshot * @param snapshot description of the snapshot being taken * @param workingDir working directory of the snapshot * @param fs {@link FileSystem} on which the snapshot should be taken * @throws IOException if we can't reach the filesystem and the file cannot be cleaned up on * failure */ public static void writeSnapshotInfo(SnapshotDescription snapshot, Path workingDir, FileSystem fs) throws IOException { FsPermission perms = FSUtils.getFilePermissions(fs, fs.getConf(), HConstants.DATA_FILE_UMASK_KEY); Path snapshotInfo = new Path(workingDir, SnapshotDescriptionUtils.SNAPSHOTINFO_FILE); try { FSDataOutputStream out = FSUtils.create(fs, snapshotInfo, perms, true); try { snapshot.writeTo(out); } finally { out.close(); } } catch (IOException e) { // if we get an exception, try to remove the snapshot info if (!fs.delete(snapshotInfo, false)) { String msg = "Couldn't delete snapshot info file: " + snapshotInfo; LOG.error(msg); throw new IOException(msg); } } }
/** * Read in the {@link org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription} stored for the snapshot in the passed directory * @param fs filesystem where the snapshot was taken * @param snapshotDir directory where the snapshot was stored * @return the stored snapshot description * @throws CorruptedSnapshotException if the * snapshot cannot be read */ public static SnapshotDescription readSnapshotInfo(FileSystem fs, Path snapshotDir) throws CorruptedSnapshotException { Path snapshotInfo = new Path(snapshotDir, SNAPSHOTINFO_FILE); try { FSDataInputStream in = null; try { in = fs.open(snapshotInfo); SnapshotDescription desc = SnapshotDescription.parseFrom(in); return desc; } finally { if (in != null) in.close(); } } catch (IOException e) { throw new CorruptedSnapshotException("Couldn't read snapshot info from:" + snapshotInfo, e); } }
@Override public void preSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx, final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) throws IOException { requirePermission("snapshot", hTableDescriptor.getTableName(), null, null, Permission.Action.ADMIN); }
@Override public void preListSnapshot(ObserverContext<MasterCoprocessorEnvironment> ctx, final SnapshotDescription snapshot) throws IOException { if (SnapshotDescriptionUtils.isSnapshotOwner(snapshot, getActiveUser())) { // list it, if user is the owner of snapshot } else { requirePermission("listSnapshot", Action.ADMIN); } }
@Override public void preDeleteSnapshot(final ObserverContext<MasterCoprocessorEnvironment> ctx, final SnapshotDescription snapshot) throws IOException { if (SnapshotDescriptionUtils.isSnapshotOwner(snapshot, getActiveUser())) { // Snapshot owner is allowed to delete the snapshot // TODO: We are not logging this for audit } else { requirePermission("deleteSnapshot", Action.ADMIN); } }
public void preSnapshot(final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) throws IOException { execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException { oserver.preSnapshot(ctx, snapshot, hTableDescriptor); } }); }
public void postSnapshot(final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) throws IOException { execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException { oserver.postSnapshot(ctx, snapshot, hTableDescriptor); } }); }
public void preListSnapshot(final SnapshotDescription snapshot) throws IOException { execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver observer, ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException { observer.preListSnapshot(ctx, snapshot); } }); }
public void preCloneSnapshot(final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) throws IOException { execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException { oserver.preCloneSnapshot(ctx, snapshot, hTableDescriptor); } }); }
public void postCloneSnapshot(final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) throws IOException { execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException { oserver.postCloneSnapshot(ctx, snapshot, hTableDescriptor); } }); }
public void postRestoreSnapshot(final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) throws IOException { execOperation(coprocessors.isEmpty() ? null : new CoprocessorOperation() { @Override public void call(MasterObserver oserver, ObserverContext<MasterCoprocessorEnvironment> ctx) throws IOException { oserver.postRestoreSnapshot(ctx, snapshot, hTableDescriptor); } }); }
/** * Check that the snapshot description written in the filesystem matches the current snapshot * @param snapshotDir snapshot directory to check */ private void verifySnapshotDescription(Path snapshotDir) throws CorruptedSnapshotException { SnapshotDescription found = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir); if (!this.snapshot.equals(found)) { throw new CorruptedSnapshotException("Snapshot read (" + found + ") doesn't equal snapshot we ran (" + snapshot + ").", snapshot); } }
/** * Delete the specified snapshot * @param snapshot * @throws SnapshotDoesNotExistException If the specified snapshot does not exist. * @throws IOException For filesystem IOExceptions */ public void deleteSnapshot(SnapshotDescription snapshot) throws SnapshotDoesNotExistException, IOException { // check to see if it is completed if (!isSnapshotCompleted(snapshot)) { throw new SnapshotDoesNotExistException(snapshot); } String snapshotName = snapshot.getName(); // first create the snapshot description and check to see if it exists FileSystem fs = master.getMasterFileSystem().getFileSystem(); Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir); // Get snapshot info from file system. The one passed as parameter is a "fake" snapshotInfo with // just the "name" and it does not contains the "real" snapshot information snapshot = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir); // call coproc pre hook MasterCoprocessorHost cpHost = master.getMasterCoprocessorHost(); if (cpHost != null) { cpHost.preDeleteSnapshot(snapshot); } LOG.debug("Deleting snapshot: " + snapshotName); // delete the existing snapshot if (!fs.delete(snapshotDir, true)) { throw new HBaseSnapshotException("Failed to delete snapshot directory: " + snapshotDir); } // call coproc post hook if (cpHost != null) { cpHost.postDeleteSnapshot(snapshot); } }
/** * Make sure that there is only one snapshot returned from the master and its * name and table match the passed in parameters. */ public static List<SnapshotDescription> assertOneSnapshotThatMatches( Admin admin, String snapshotName, TableName tableName) throws IOException { // list the snapshot List<SnapshotDescription> snapshots = admin.listSnapshots(); assertEquals("Should only have 1 snapshot", 1, snapshots.size()); assertEquals(snapshotName, snapshots.get(0).getName()); assertEquals(tableName, TableName.valueOf(snapshots.get(0).getTable())); return snapshots; }
/** * Take a snapshot of an enabled table. * @param snapshot description of the snapshot to take. * @throws HBaseSnapshotException if the snapshot could not be started */ private synchronized void snapshotEnabledTable(SnapshotDescription snapshot) throws HBaseSnapshotException { // setup the snapshot prepareToTakeSnapshot(snapshot); // Take the snapshot of the enabled table EnabledTableSnapshotHandler handler = new EnabledTableSnapshotHandler(snapshot, master, this); snapshotTable(snapshot, handler); }
/** * Check to see if the snapshot is one of the currently completed snapshots * Returns true if the snapshot exists in the "completed snapshots folder". * * @param snapshot expected snapshot to check * @return <tt>true</tt> if the snapshot is stored on the {@link FileSystem}, <tt>false</tt> if is * not stored * @throws IOException if the filesystem throws an unexpected exception, * @throws IllegalArgumentException if snapshot name is invalid. */ private boolean isSnapshotCompleted(SnapshotDescription snapshot) throws IOException { try { final Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshot, rootDir); FileSystem fs = master.getMasterFileSystem().getFileSystem(); // check to see if the snapshot already exists return fs.exists(snapshotDir); } catch (IllegalArgumentException iae) { throw new UnknownSnapshotException("Unexpected exception thrown", iae); } }
public SnapshotBuilder(final Configuration conf, final FileSystem fs, final Path rootDir, final HTableDescriptor htd, final SnapshotDescription desc, final RegionData[] tableRegions) throws IOException { this.fs = fs; this.conf = conf; this.rootDir = rootDir; this.htd = htd; this.desc = desc; this.tableRegions = tableRegions; this.snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir); new FSTableDescriptors(conf) .createTableDescriptorForTableDirectory(snapshotDir, htd, false); }
/** * Restore the specified snapshot. * The restore will fail if the destination table has a snapshot or restore in progress. * * @param snapshot Snapshot Descriptor * @param hTableDescriptor Table Descriptor */ private synchronized void restoreSnapshot(final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) throws HBaseSnapshotException { TableName tableName = hTableDescriptor.getTableName(); // make sure we aren't running a snapshot on the same table if (isTakingSnapshot(tableName)) { throw new RestoreSnapshotException("Snapshot in progress on the restore table=" + tableName); } // make sure we aren't running a restore on the same table if (isRestoringTable(tableName)) { throw new RestoreSnapshotException("Restore already in progress on the table=" + tableName); } try { RestoreSnapshotHandler handler = new RestoreSnapshotHandler(master, snapshot, hTableDescriptor).prepare(); this.executorService.submit(handler); restoreHandlers.put(tableName, handler); } catch (Exception e) { String msg = "Couldn't restore the snapshot=" + ClientSnapshotDescriptionUtils.toString( snapshot) + " on table=" + tableName; LOG.error(msg, e); throw new RestoreSnapshotException(msg, e); } }
/** * Returns the status of a restore operation. * If the in-progress restore is failed throws the exception that caused the failure. * * @param snapshot * @return false if in progress, true if restore is completed or not requested. * @throws IOException if there was a failure during the restore */ public boolean isRestoreDone(final SnapshotDescription snapshot) throws IOException { // check to see if the sentinel exists, // and if the task is complete removes it from the in-progress restore map. SnapshotSentinel sentinel = removeSentinelIfFinished(this.restoreHandlers, snapshot); // stop tracking "abandoned" handlers cleanupSentinels(); if (sentinel == null) { // there is no sentinel so restore is not in progress. return true; } LOG.debug("Verify snapshot=" + snapshot.getName() + " against=" + sentinel.getSnapshot().getName() + " table=" + TableName.valueOf(snapshot.getTable())); // If the restore is failed, rethrow the exception sentinel.rethrowExceptionIfFailed(); // check to see if we are done if (sentinel.isFinished()) { LOG.debug("Restore snapshot=" + ClientSnapshotDescriptionUtils.toString(snapshot) + " has completed. Notifying the client."); return true; } if (LOG.isDebugEnabled()) { LOG.debug("Sentinel is not yet finished with restoring snapshot=" + ClientSnapshotDescriptionUtils.toString(snapshot)); } return false; }
public CloneSnapshotHandler(final MasterServices masterServices, final SnapshotDescription snapshot, final HTableDescriptor hTableDescriptor) { super(masterServices, masterServices.getMasterFileSystem(), hTableDescriptor, masterServices.getConfiguration(), null, masterServices); // Snapshot information this.snapshot = snapshot; // Monitor this.monitor = new ForeignExceptionDispatcher(); this.status = TaskMonitor.get().createStatus("Cloning snapshot '" + snapshot.getName() + "' to table " + hTableDescriptor.getTableName()); }
/** * @param snapshot descriptor of the snapshot to take * @param masterServices master services provider */ public TakeSnapshotHandler(SnapshotDescription snapshot, final MasterServices masterServices) { super(masterServices, EventType.C_M_SNAPSHOT_TABLE); assert snapshot != null : "SnapshotDescription must not be nul1"; assert masterServices != null : "MasterServices must not be nul1"; this.master = masterServices; this.snapshot = snapshot; this.snapshotTable = TableName.valueOf(snapshot.getTable()); this.conf = this.master.getConfiguration(); this.fs = this.master.getMasterFileSystem().getFileSystem(); this.rootDir = this.master.getMasterFileSystem().getRootDir(); this.snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshot, rootDir); this.workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(snapshot, rootDir); this.monitor = new ForeignExceptionDispatcher(snapshot.getName()); this.snapshotManifest = SnapshotManifest.create(conf, fs, workingDir, snapshot, monitor); this.tableLockManager = master.getTableLockManager(); this.tableLock = this.tableLockManager.writeLock( snapshotTable, EventType.C_M_SNAPSHOT_TABLE.toString()); // prepare the verify this.verifier = new MasterSnapshotVerifier(masterServices, snapshot, rootDir); // update the running tasks this.status = TaskMonitor.get().createStatus( "Taking " + snapshot.getType() + " snapshot on table: " + snapshotTable); }
public static void confirmSnapshotValid(HBaseTestingUtility testUtil, SnapshotDescription snapshotDescriptor, TableName tableName, byte[] family) throws IOException { MasterFileSystem mfs = testUtil.getHBaseCluster().getMaster().getMasterFileSystem(); confirmSnapshotValid(snapshotDescriptor, tableName, family, mfs.getRootDir(), testUtil.getHBaseAdmin(), mfs.getFileSystem()); }
/** * Initialize the restore helper, based on the snapshot and table information provided. */ private RestoreSnapshotHelper getRestoreHelper(final Path rootDir, final Path snapshotDir, final SnapshotDescription sd, final HTableDescriptor htdClone) throws IOException { ForeignExceptionDispatcher monitor = Mockito.mock(ForeignExceptionDispatcher.class); MonitoredTask status = Mockito.mock(MonitoredTask.class); SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, sd); return new RestoreSnapshotHelper(conf, fs, manifest, htdClone, rootDir, monitor, status); }
/** * Test snapshotting a table that is online without flushing * @throws Exception */ @Test(timeout=30000) public void testSkipFlushTableSnapshot() throws Exception { Admin admin = UTIL.getHBaseAdmin(); // make sure we don't fail on listing snapshots SnapshotTestingUtils.assertNoSnapshots(admin); // put some stuff in the table try (Table table = UTIL.getConnection().getTable(TABLE_NAME)) { UTIL.loadTable(table, TEST_FAM); } LOG.debug("FS state before snapshot:"); UTIL.getHBaseCluster().getMaster().getMasterFileSystem().logFileSystemState(LOG); // take a snapshot of the enabled table String snapshotString = "skipFlushTableSnapshot"; byte[] snapshot = Bytes.toBytes(snapshotString); admin.snapshot(snapshotString, TABLE_NAME, SnapshotDescription.Type.SKIPFLUSH); LOG.debug("Snapshot completed."); // make sure we have the snapshot List<SnapshotDescription> snapshots = SnapshotTestingUtils.assertOneSnapshotThatMatches(admin, snapshot, TABLE_NAME); // make sure its a valid snapshot LOG.debug("FS state after snapshot:"); UTIL.getHBaseCluster().getMaster().getMasterFileSystem().logFileSystemState(LOG); SnapshotTestingUtils.confirmSnapshotValid(UTIL, snapshots.get(0), TABLE_NAME, TEST_FAM); admin.deleteSnapshot(snapshot); snapshots = admin.listSnapshots(); SnapshotTestingUtils.assertNoSnapshots(admin); }
public static void deleteAllSnapshots(final Admin admin) throws IOException { // Delete all the snapshots for (SnapshotDescription snapshot: admin.listSnapshots()) { admin.deleteSnapshot(snapshot.getName()); } SnapshotTestingUtils.assertNoSnapshots(admin); }
private SnapshotBuilder createSnapshot(final String snapshotName, final String tableName, final int numRegions, final int version) throws IOException { HTableDescriptor htd = createHtd(tableName); RegionData[] regions = createTable(htd, numRegions); SnapshotDescription desc = SnapshotDescription.newBuilder() .setTable(htd.getNameAsString()) .setName(snapshotName) .setVersion(version) .build(); Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir); SnapshotDescriptionUtils.writeSnapshotInfo(desc, workingDir, fs); return new SnapshotBuilder(conf, fs, rootDir, htd, desc, regions); }
private void failSnapshotStart(Admin admin, SnapshotDescription snapshot) throws IOException { try { admin.snapshot(snapshot); fail("Snapshot should not have succeed with name:" + snapshot.getName()); } catch (IllegalArgumentException e) { LOG.debug("Correctly failed to start snapshot:" + e.getMessage()); } }