/** * Check to make sure that we are OK to run the passed snapshot. Checks to make sure that we * aren't already running a snapshot or restore on the requested table. * * @param snapshot description of the snapshot we want to start * @throws HBaseSnapshotException if the filesystem could not be prepared to start the snapshot */ private synchronized void prepareToTakeSnapshot(SnapshotDescription snapshot) throws HBaseSnapshotException { FileSystem fs = master.getMasterFileSystem().getFileSystem(); Path workingDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(snapshot, rootDir); TableName snapshotTable = TableName.valueOf(snapshot.getTable()); // make sure we aren't already running a snapshot if (isTakingSnapshot(snapshot)) { SnapshotSentinel handler = this.snapshotHandlers.get(snapshotTable); throw new SnapshotCreationException( "Rejected taking " + ClientSnapshotDescriptionUtils.toString(snapshot) + " because we are already running another snapshot " + (handler != null ? ("on the same table " + ClientSnapshotDescriptionUtils.toString(handler.getSnapshot())) : "with the same name"), ProtobufUtil.createSnapshotDesc(snapshot)); } // make sure we aren't running a restore on the same table if (isRestoringTable(snapshotTable)) { throw new SnapshotCreationException( "Rejected taking " + ClientSnapshotDescriptionUtils.toString(snapshot) + " because we are already have a restore in progress on the same snapshot."); } try { // delete the working directory, since we aren't running the snapshot. Likely leftovers // from a failed attempt. fs.delete(workingDir, true); // recreate the working directory for the snapshot if (!fs.mkdirs(workingDir)) { throw new SnapshotCreationException( "Couldn't create working directory (" + workingDir + ") for snapshot", ProtobufUtil.createSnapshotDesc(snapshot)); } } catch (HBaseSnapshotException e) { throw e; } catch (IOException e) { throw new SnapshotCreationException( "Exception while checking to see if snapshot could be started.", e, ProtobufUtil.createSnapshotDesc(snapshot)); } }
/** * 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; }
/** * 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; }