/** * 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; }
@Override public void stop(String why) { // short circuit if (this.stopped) return; // make sure we get stop this.stopped = true; // pass the stop onto take snapshot handlers for (SnapshotSentinel snapshotHandler: this.snapshotHandlers.values()) { snapshotHandler.cancel(why); } // pass the stop onto all the restore handlers for (SnapshotSentinel restoreHandler: this.restoreHandlers.values()) { restoreHandler.cancel(why); } try { if (coordinator != null) { coordinator.close(); } } catch (IOException e) { LOG.error("stop ProcedureCoordinator error", e); } }
/** * 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<String, SnapshotSentinel> sentinels, final SnapshotDescription snapshot) { SnapshotSentinel h = sentinels.get(snapshot.getTable()); 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(snapshot.getTable()); } return h; }
@Override public void stop(String why) { // short circuit if (this.stopped) return; // make sure we get stop this.stopped = true; // pass the stop onto take snapshot handlers for (SnapshotSentinel snapshotHandler: this.snapshotHandlers.values()) { snapshotHandler.cancel(why); } // pass the stop onto all the restore handlers for (SnapshotSentinel restoreHandler: this.restoreHandlers.values()) { restoreHandler.cancel(why); } try { coordinator.close(); } catch (IOException e) { LOG.error("stop ProcedureCoordinator error", e); } }
@Override public void stop(String why) { // short circuit if (this.stopped) return; // make sure we get stop this.stopped = true; // pass the stop onto take snapshot handlers for (SnapshotSentinel snapshotHandler: this.snapshotHandlers.values()) { snapshotHandler.cancel(why); } try { if (coordinator != null) { coordinator.close(); } } catch (IOException e) { LOG.error("stop ProcedureCoordinator error", e); } }
@Override public void stop(String why) { // short circuit if (this.stopped) return; // make sure we get stop this.stopped = true; // pass the stop onto take snapshot handlers for (SnapshotSentinel snapshotHandler: this.snapshotHandlers.values()) { snapshotHandler.cancel(why); } // pass the stop onto all the restore handlers for (SnapshotSentinel restoreHandler: this.restoreHandlers.values()) { restoreHandler.cancel(why); } }
/** * Set the handler for the current snapshot * <p> * Exposed for TESTING * @param tableName * @param handler handler the master should use * * TODO get rid of this if possible, repackaging, modify tests. */ public synchronized void setSnapshotHandlerForTesting( final TableName tableName, final SnapshotSentinel handler) { if (handler != null) { this.snapshotHandlers.put(tableName, handler); } else { this.snapshotHandlers.remove(tableName); } }
/** * 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; }
/** * Remove the sentinels that are marked as finished and the completion time * has exceeded the removal timeout. * @param sentinels map of sentinels to clean */ private synchronized void cleanupSentinels(final Map<TableName, SnapshotSentinel> sentinels) { long currentTime = EnvironmentEdgeManager.currentTime(); Iterator<Map.Entry<TableName, SnapshotSentinel>> it = sentinels.entrySet().iterator(); while (it.hasNext()) { Map.Entry<TableName, SnapshotSentinel> entry = it.next(); SnapshotSentinel sentinel = entry.getValue(); if (sentinel.isFinished() && (currentTime - sentinel.getCompletionTimestamp()) > SNAPSHOT_SENTINELS_CLEANUP_TIMEOUT) { it.remove(); } } }
/** * 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) { if (isTakingSnapshot(snapshot.getTable())) { return true; } Iterator<Map.Entry<String, SnapshotSentinel>> it = this.snapshotHandlers.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, SnapshotSentinel> entry = it.next(); SnapshotSentinel sentinel = entry.getValue(); if (snapshot.getName().equals(sentinel.getSnapshot().getName()) && !sentinel.isFinished()) { return true; } } return false; }
/** * 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=" + 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=" + SnapshotDescriptionUtils.toString(snapshot) + " has completed. Notifying the client."); return true; } if (LOG.isDebugEnabled()) { LOG.debug("Sentinel is not yet finished with restoring snapshot=" + SnapshotDescriptionUtils.toString(snapshot)); } return false; }
/** * Remove the sentinels that are marked as finished and the completion time * has exceeded the removal timeout. * @param sentinels map of sentinels to clean */ private synchronized void cleanupSentinels(final Map<String, SnapshotSentinel> sentinels) { long currentTime = EnvironmentEdgeManager.currentTimeMillis(); Iterator<Map.Entry<String, SnapshotSentinel>> it = sentinels.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, SnapshotSentinel> entry = it.next(); SnapshotSentinel sentinel = entry.getValue(); if (sentinel.isFinished() && (currentTime - sentinel.getCompletionTimestamp()) > SNAPSHOT_SENTINELS_CLEANUP_TIMEOUT) { it.remove(); } } }