/** * Wait for latch to count to zero, ignoring any spurious wake-ups, but waking periodically to * check for errors * @param latch latch to wait on * @param monitor monitor to check for errors while waiting * @param wakeFrequency frequency to wake up and check for errors (in * {@link TimeUnit#MILLISECONDS}) * @param latchDescription description of the latch, for logging * @throws ForeignException type of error the monitor can throw, if the task fails * @throws InterruptedException if we are interrupted while waiting on latch */ public static void waitForLatch(CountDownLatch latch, ForeignExceptionSnare monitor, long wakeFrequency, String latchDescription) throws ForeignException, InterruptedException { boolean released = false; while (!released) { if (monitor != null) { monitor.rethrowException(); } /* ForeignExceptionDispatcher.LOG.debug("Waiting for '" + latchDescription + "' latch. (sleep:" + wakeFrequency + " ms)"); */ released = latch.await(wakeFrequency, TimeUnit.MILLISECONDS); } // check error again in case an error raised during last wait if (monitor != null) { monitor.rethrowException(); } }
private SnapshotManifest(final Configuration conf, final FileSystem fs, final Path workingDir, final SnapshotDescription desc, final ForeignExceptionSnare monitor) { this.monitor = monitor; this.desc = desc; this.workingDir = workingDir; this.conf = conf; this.fs = fs; this.manifestSizeLimit = conf.getInt(SNAPSHOT_MANIFEST_SIZE_LIMIT_CONF_KEY, 64 * 1024 * 1024); }
/** * Wait for latch to count to zero, ignoring any spurious wake-ups, but waking periodically to * check for errors * @param latch latch to wait on * @param monitor monitor to check for errors while waiting * @param wakeFrequency frequency to wake up and check for errors (in * {@link TimeUnit#MILLISECONDS}) * @param latchDescription description of the latch, for logging * @throws ForeignException type of error the monitor can throw, if the task fails * @throws InterruptedException if we are interrupted while waiting on latch */ public static void waitForLatch(CountDownLatch latch, ForeignExceptionSnare monitor, long wakeFrequency, String latchDescription) throws ForeignException, InterruptedException { boolean released = false; while (!released) { if (monitor != null) { monitor.rethrowException(); } /* ForeignExceptionDispatcher.LOG.debug("Waiting for '" + latchDescription + "' latch. (sleep:" + wakeFrequency + " ms)"); */ released = latch.await(wakeFrequency, TimeUnit.MILLISECONDS); } }
private SnapshotManifest(final Configuration conf, final FileSystem fs, final Path workingDir, final SnapshotDescription desc, final ForeignExceptionSnare monitor) { this.monitor = monitor; this.desc = desc; this.workingDir = workingDir; this.conf = conf; this.fs = fs; }
/** * exposed for testing. */ ForeignExceptionSnare getErrorCheckable() { return this.monitor; }
/** * Complete taking the snapshot on the region. Writes the region info and adds references to the * working snapshot directory. TODO for api consistency, consider adding another version with no * {@link ForeignExceptionSnare} arg. (In the future other cancellable HRegion methods could * eventually add a {@link ForeignExceptionSnare}, or we could do something fancier). * @param desc snasphot description object * @param exnSnare ForeignExceptionSnare that captures external exeptions in case we need to bail * out. This is allowed to be null and will just be ignored in that case. * @throws IOException if there is an external or internal error causing the snapshot to fail */ public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare) throws IOException { // This should be "fast" since we don't rewrite store files but instead // back up the store files by creating a reference Path rootDir = FSUtils.getRootDir(this.rsServices.getConfiguration()); Path snapshotRegionDir = TakeSnapshotUtils.getRegionSnapshotDirectory(desc, rootDir, regionInfo.getEncodedName()); // 1. dump region meta info into the snapshot directory LOG.debug("Storing region-info for snapshot."); checkRegioninfoOnFilesystem(snapshotRegionDir); // 2. iterate through all the stores in the region LOG.debug("Creating references for hfiles"); // This ensures that we have an atomic view of the directory as long as we have < ls limit // (batch size of the files in a directory) on the namenode. Otherwise, we get back the files in // batches and may miss files being added/deleted. This could be more robust (iteratively // checking to see if we have all the files until we are sure), but the limit is currently 1000 // files/batch, far more than the number of store files under a single column family. for (Store store : stores.values()) { // 2.1. build the snapshot reference directory for the store Path dstStoreDir = TakeSnapshotUtils.getStoreSnapshotDirectory(snapshotRegionDir, Bytes.toString(store.getFamily().getName())); List<StoreFile> storeFiles = store.getStorefiles(); if (LOG.isDebugEnabled()) { LOG.debug("Adding snapshot references for " + storeFiles + " hfiles"); } // 2.2. iterate through all the store's files and create "references". int sz = storeFiles.size(); for (int i = 0; i < sz; i++) { if (exnSnare != null) { exnSnare.rethrowException(); } StoreFile storeFile = storeFiles.get(i); Path file = storeFile.getPath(); LOG.debug("Creating reference for file (" + (i + 1) + "/" + sz + ") : " + file); Path referenceFile = new Path(dstStoreDir, file.getName()); boolean success = true; if (storeFile.isReference()) { // write the Reference object to the snapshot storeFile.getReference().write(fs, referenceFile); } else { // create "reference" to this store file. It is intentionally an empty file -- all // necessary information is captured by its fs location and filename. This allows us to // only figure out what needs to be done via a single nn operation (instead of having to // open and read the files as well). success = HBaseFileSystem.createNewFileOnFileSystem(fs, referenceFile); } if (!success) { throw new IOException("Failed to create reference file:" + referenceFile); } } } }
/** * Complete taking the snapshot on the region. Writes the region info and adds references to the * working snapshot directory. * * TODO for api consistency, consider adding another version with no {@link ForeignExceptionSnare} * arg. (In the future other cancellable HRegion methods could eventually add a * {@link ForeignExceptionSnare}, or we could do something fancier). * * @param desc snasphot description object * @param exnSnare ForeignExceptionSnare that captures external exeptions in case we need to * bail out. This is allowed to be null and will just be ignored in that case. * @throws IOException if there is an external or internal error causing the snapshot to fail */ public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare) throws IOException { // This should be "fast" since we don't rewrite store files but instead // back up the store files by creating a reference Path rootDir = FSUtils.getRootDir(this.rsServices.getConfiguration()); Path snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir); // 1. dump region meta info into the snapshot directory LOG.debug("Storing region-info for snapshot."); HRegionFileSystem snapshotRegionFs = HRegionFileSystem.createRegionOnFileSystem(conf, this.fs.getFileSystem(), snapshotDir, getRegionInfo()); // 2. iterate through all the stores in the region LOG.debug("Creating references for hfiles"); // This ensures that we have an atomic view of the directory as long as we have < ls limit // (batch size of the files in a directory) on the namenode. Otherwise, we get back the files in // batches and may miss files being added/deleted. This could be more robust (iteratively // checking to see if we have all the files until we are sure), but the limit is currently 1000 // files/batch, far more than the number of store files under a single column family. for (Store store : stores.values()) { // 2.1. build the snapshot reference directory for the store Path dstStoreDir = snapshotRegionFs.getStoreDir(store.getFamily().getNameAsString()); List<StoreFile> storeFiles = new ArrayList<StoreFile>(store.getStorefiles()); if (LOG.isDebugEnabled()) { LOG.debug("Adding snapshot references for " + storeFiles + " hfiles"); } // 2.2. iterate through all the store's files and create "references". int sz = storeFiles.size(); for (int i = 0; i < sz; i++) { if (exnSnare != null) { exnSnare.rethrowException(); } StoreFile storeFile = storeFiles.get(i); Path file = storeFile.getPath(); LOG.debug("Creating reference for file (" + (i+1) + "/" + sz + ") : " + file); Path referenceFile = new Path(dstStoreDir, file.getName()); boolean success = true; if (storeFile.isReference()) { // write the Reference object to the snapshot storeFile.getFileInfo().getReference().write(fs.getFileSystem(), referenceFile); } else { // create "reference" to this store file. It is intentionally an empty file -- all // necessary information is captured by its fs location and filename. This allows us to // only figure out what needs to be done via a single nn operation (instead of having to // open and read the files as well). success = fs.getFileSystem().createNewFile(referenceFile); } if (!success) { throw new IOException("Failed to create reference file:" + referenceFile); } } } }
/** * Complete taking the snapshot on the region. Writes the region info and adds references to the * working snapshot directory. * * TODO for api consistency, consider adding another version with no {@link ForeignExceptionSnare} * arg. (In the future other cancellable HRegion methods could eventually add a * {@link ForeignExceptionSnare}, or we could do something fancier). * * @param desc snasphot description object * @param exnSnare ForeignExceptionSnare that captures external exeptions in case we need to * bail out. This is allowed to be null and will just be ignored in that case. * @throws IOException if there is an external or internal error causing the snapshot to fail */ public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare) throws IOException { // This should be "fast" since we don't rewrite store files but instead // back up the store files by creating a reference Path rootDir = FSUtils.getRootDir(this.rsServices.getConfiguration()); Path snapshotRegionDir = TakeSnapshotUtils.getRegionSnapshotDirectory(desc, rootDir, regionInfo.getEncodedName()); // 1. dump region meta info into the snapshot directory LOG.debug("Storing region-info for snapshot."); checkRegioninfoOnFilesystem(snapshotRegionDir); // 2. iterate through all the stores in the region LOG.debug("Creating references for hfiles"); // This ensures that we have an atomic view of the directory as long as we have < ls limit // (batch size of the files in a directory) on the namenode. Otherwise, we get back the files in // batches and may miss files being added/deleted. This could be more robust (iteratively // checking to see if we have all the files until we are sure), but the limit is currently 1000 // files/batch, far more than the number of store files under a single column family. for (Store store : stores.values()) { // 2.1. build the snapshot reference directory for the store Path dstStoreDir = TakeSnapshotUtils.getStoreSnapshotDirectory(snapshotRegionDir, Bytes.toString(store.getFamily().getName())); List<StoreFile> storeFiles = store.getStorefiles(); if (LOG.isDebugEnabled()) { LOG.debug("Adding snapshot references for " + storeFiles + " hfiles"); } // 2.2. iterate through all the store's files and create "references". int sz = storeFiles.size(); for (int i = 0; i < sz; i++) { if (exnSnare != null) { exnSnare.rethrowException(); } StoreFile storeFile = storeFiles.get(i); Path file = storeFile.getPath(); LOG.debug("Creating reference for file (" + (i+1) + "/" + sz + ") : " + file); Path referenceFile = new Path(dstStoreDir, file.getName()); boolean success = true; if (storeFile.isReference()) { // write the Reference object to the snapshot storeFile.getReference().write(fs, referenceFile); } else { // create "reference" to this store file. It is intentionally an empty file -- all // necessary information is captured by its fs location and filename. This allows us to // only figure out what needs to be done via a single nn operation (instead of having to // open and read the files as well). success = HBaseFileSystem.createNewFileOnFileSystem(fs, referenceFile); } if (!success) { throw new IOException("Failed to create reference file:" + referenceFile); } } } }
/** * Complete taking the snapshot on the region. Writes the region info and adds references to the * working snapshot directory. * * TODO for api consistency, consider adding another version with no {@link ForeignExceptionSnare} * arg. (In the future other cancellable HRegion methods could eventually add a * {@link ForeignExceptionSnare}, or we could do something fancier). * * @param desc snasphot description object * @param exnSnare ForeignExceptionSnare that captures external exeptions in case we need to * bail out. This is allowed to be null and will just be ignored in that case. * @throws IOException if there is an external or internal error causing the snapshot to fail */ public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare) throws IOException { // This should be "fast" since we don't rewrite store files but instead // back up the store files by creating a reference Path rootDir = FSUtils.getRootDir(this.rsServices.getConfiguration()); Path snapshotRegionDir = TakeSnapshotUtils.getRegionSnapshotDirectory(desc, rootDir, regionInfo.getEncodedName()); // 1. dump region meta info into the snapshot directory LOG.debug("Storing region-info for snapshot."); checkRegioninfoOnFilesystem(snapshotRegionDir); // 2. iterate through all the stores in the region LOG.debug("Creating references for hfiles"); // This ensures that we have an atomic view of the directory as long as we have < ls limit // (batch size of the files in a directory) on the namenode. Otherwise, we get back the files in // batches and may miss files being added/deleted. This could be more robust (iteratively // checking to see if we have all the files until we are sure), but the limit is currently 1000 // files/batch, far more than the number of store files under a single column family. for (Store store : stores.values()) { // 2.1. build the snapshot reference directory for the store Path dstStoreDir = TakeSnapshotUtils.getStoreSnapshotDirectory(snapshotRegionDir, Bytes.toString(store.getFamily().getName())); List<StoreFile> storeFiles = store.getStorefiles(); if (LOG.isDebugEnabled()) { LOG.debug("Adding snapshot references for " + storeFiles + " hfiles"); } // 2.2. iterate through all the store's files and create "references". int sz = storeFiles.size(); for (int i = 0; i < sz; i++) { if (exnSnare != null) { exnSnare.rethrowException(); } Path file = storeFiles.get(i).getPath(); // create "reference" to this store file. It is intentionally an empty file -- all // necessary infomration is captured by its fs location and filename. This allows us to // only figure out what needs to be done via a single nn operation (instead of having to // open and read the files as well). LOG.debug("Creating reference for file (" + (i+1) + "/" + sz + ") : " + file); Path referenceFile = new Path(dstStoreDir, file.getName()); boolean success = HBaseFileSystem.createNewFileOnFileSystem(fs, referenceFile); if (!success) { throw new IOException("Failed to create reference file:" + referenceFile); } } } }
/** * Complete taking the snapshot on the region. Writes the region info and adds references to the * working snapshot directory. TODO for api consistency, consider adding another version with no * {@link ForeignExceptionSnare} arg. (In the future other cancellable HRegion methods could * eventually add a {@link ForeignExceptionSnare}, or we could do something fancier). * * @param desc snapshot description object * @param exnSnare ForeignExceptionSnare that captures external exceptions in case we need to bail * out. This is allowed to be null and will just be ignored in that case. * @throws IOException if there is an external or internal error causing the snapshot to fail */ public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare) throws IOException { Path rootDir = FSUtils.getRootDir(conf); Path snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir); SnapshotManifest manifest = SnapshotManifest.create(conf, getFilesystem(), snapshotDir, desc, exnSnare); manifest.addRegion(this); }
/** * Complete taking the snapshot on the region. Writes the region info and adds references to the * working snapshot directory. * <p/> * TODO for api consistency, consider adding another version with no {@link ForeignExceptionSnare} * arg. (In the future other cancellable HRegion methods could eventually add a * {@link ForeignExceptionSnare}, or we could do something fancier). * * @param desc snapshot description object * @param exnSnare ForeignExceptionSnare that captures external exceptions in case we need to * bail out. This is allowed to be null and will just be ignored in that case. * @throws IOException if there is an external or internal error causing the snapshot to fail */ public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare) throws IOException { Path rootDir = FSUtils.getRootDir(conf); Path snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir); SnapshotManifest manifest = SnapshotManifest.create(conf, getFilesystem(), snapshotDir, desc, exnSnare); manifest.addRegion(this); }
/** * Return a SnapshotManifest instance, used for writing a snapshot. * * There are two usage pattern: * - The Master will create a manifest, add the descriptor, offline regions * and consolidate the snapshot by writing all the pending stuff on-disk. * manifest = SnapshotManifest.create(...) * manifest.addRegion(tableDir, hri) * manifest.consolidate() * - The RegionServer will create a single region manifest * manifest = SnapshotManifest.create(...) * manifest.addRegion(region) */ public static SnapshotManifest create(final Configuration conf, final FileSystem fs, final Path workingDir, final SnapshotDescription desc, final ForeignExceptionSnare monitor) { return new SnapshotManifest(conf, fs, workingDir, desc, monitor); }
/** * Complete taking the snapshot on the region. Writes the region info and adds references to the * working snapshot directory. * * TODO for api consistency, consider adding another version with no {@link ForeignExceptionSnare} * arg. (In the future other cancellable HRegion methods could eventually add a * {@link ForeignExceptionSnare}, or we could do something fancier). * * @param desc snapshot description object * @param exnSnare ForeignExceptionSnare that captures external exceptions in case we need to * bail out. This is allowed to be null and will just be ignored in that case. * @throws IOException if there is an external or internal error causing the snapshot to fail */ public void addRegionToSnapshot(SnapshotDescription desc, ForeignExceptionSnare exnSnare) throws IOException { Path rootDir = FSUtils.getRootDir(conf); Path snapshotDir = SnapshotDescriptionUtils.getWorkingSnapshotDir(desc, rootDir); SnapshotManifest manifest = SnapshotManifest.create(conf, getFilesystem(), snapshotDir, desc, exnSnare); manifest.addRegion(this); }