class Snapshot implements Watcher {

    public void run() throws IOException, KeeperException, InterruptedException {
        String timestamp = timestamp(TimestampFormat.snapshot);

        String connectString = admin.getConfiguration().get("hbase.zookeeper.quorum");
        ZooKeeper zooKeeper = null;
        try {
            Map<String, String> failedSnapshotMap = new TreeMap<>();

            zooKeeper = new ZooKeeper(connectString, SESSION_TIMEOUT, this);
            for (String tableName : args.tableSet(admin)) {
                if (args.isExcluded(tableName)) {
                    System.out.println(timestamp(TimestampFormat.log)
                            + " - Table \"" + tableName + "\" - EXCLUDED");
                    continue;
                }

                String snapshotName = getPrefix(tableName) + timestamp;
                try {
                    snapshot(zooKeeper, tableName, snapshotName);
                } catch (Throwable e) {
                    failedSnapshotMap.put(snapshotName, tableName);
                }

                // delete old snapshots after creating new one
                deleteOldSnapshots(admin, tableName);
            }
            deleteSnapshotsForNotExistingTables();
            deleteOldAbortZnodes(zooKeeper);

            retrySnapshot(zooKeeper, failedSnapshotMap);
            Util.sendAlertAfterSuccess(args, this.getClass());
        } catch (Throwable e) {
            String message = "ConnectionString= " + connectString + ", CurrentHost= "
                    + InetAddress.getLocalHost().getHostName() + ", Message= " + errorMessage(e);
            System.out.println("\n" + timestamp(TimestampFormat.log) + " - " + message);
            Util.sendAlertAfterFailed(args, this.getClass(), message);
            throw e;
        } finally {
            if (zooKeeper != null && zooKeeper.getState().isConnected()) {
                zooKeeper.close();
            }
        }
    }

      Snapshot(HBaseAdmin admin, SnapshotArgs args);

}