public Quota.Counts cleanFile(final INodeFile file, final int snapshotId, int priorSnapshotId, final BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { if (snapshotId == Snapshot.CURRENT_STATE_ID) { // delete the current file while the file has snapshot feature if (!isCurrentFileDeleted()) { file.recordModification(priorSnapshotId); deleteCurrentFile(); } collectBlocksAndClear(file, collectedBlocks, removedINodes); return Quota.Counts.newInstance(); } else { // delete the snapshot priorSnapshotId = getDiffs().updatePrior(snapshotId, priorSnapshotId); return diffs.deleteSnapshotDiff(snapshotId, priorSnapshotId, file, collectedBlocks, removedINodes); } }
public Quota.Counts updateQuotaAndCollectBlocks(INodeFile file, FileDiff removed, BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { long oldDiskspace = file.diskspaceConsumed(); if (removed.snapshotINode != null) { short replication = removed.snapshotINode.getFileReplication(); short currentRepl = file.getBlockReplication(); if (currentRepl == 0) { oldDiskspace = file.computeFileSize(true, true) * replication; } else if (replication > currentRepl) { oldDiskspace = oldDiskspace / file.getBlockReplication() * replication; } } collectBlocksAndClear(file, collectedBlocks, removedINodes); long dsDelta = oldDiskspace - file.diskspaceConsumed(); return Quota.Counts.newInstance(0, dsDelta); }
@Override Quota.Counts combinePosteriorAndCollectBlocks( final INodeDirectory currentDir, final DirectoryDiff posterior, final BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { final Quota.Counts counts = Quota.Counts.newInstance(); diff.combinePosterior(posterior.diff, new Diff.Processor<INode>() { /** Collect blocks for deleted files. */ @Override public void process(INode inode) { if (inode != null) { inode.computeQuotaUsage(counts, false); inode.destroyAndCollectBlocks(collectedBlocks, removedINodes); } } }); return counts; }
private void checkQuotaUsageComputation(final Path dirPath, final long expectedNs, final long expectedDs) throws IOException { INodeDirectory dirNode = getDir(fsdir, dirPath); assertTrue(dirNode.isQuotaSet()); Quota.Counts q = dirNode.getDirectoryWithQuotaFeature().getSpaceConsumed(); assertEquals(dirNode.dumpTreeRecursively().toString(), expectedNs, q.get(Quota.NAMESPACE)); assertEquals(dirNode.dumpTreeRecursively().toString(), expectedDs, q.get(Quota.DISKSPACE)); Quota.Counts counts = Quota.Counts.newInstance(); dirNode.computeQuotaUsage(counts, false); assertEquals(dirNode.dumpTreeRecursively().toString(), expectedNs, counts.get(Quota.NAMESPACE)); assertEquals(dirNode.dumpTreeRecursively().toString(), expectedDs, counts.get(Quota.DISKSPACE)); }
@Override public Quota.Counts cleanSubtree(final Snapshot snapshot, Snapshot prior, final BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes, final boolean countDiffChange) throws QuotaExceededException { if (snapshot == null) { // delete the current file recordModification(prior, null); isCurrentFileDeleted = true; Util.collectBlocksAndClear(this, collectedBlocks, removedINodes); return Quota.Counts.newInstance(); } else { // delete a snapshot prior = getDiffs().updatePrior(snapshot, prior); return diffs.deleteSnapshotDiff(snapshot, prior, this, collectedBlocks, removedINodes, countDiffChange); } }
/** clear the created list */ private Quota.Counts destroyCreatedList( final INodeDirectoryWithSnapshot currentINode, final BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { Quota.Counts counts = Quota.Counts.newInstance(); final List<INode> createdList = getList(ListType.CREATED); for (INode c : createdList) { c.computeQuotaUsage(counts, true); c.destroyAndCollectBlocks(collectedBlocks, removedINodes); // c should be contained in the children list, remove it currentINode.removeChild(c); } createdList.clear(); return counts; }
/** * Undo the rename operation for the dst tree, i.e., if the rename operation * (with OVERWRITE option) removes a file/dir from the dst tree, add it back * and delete possible record in the deleted list. */ public void undoRename4DstParent(final INode deletedChild, Snapshot latestSnapshot) throws QuotaExceededException { boolean removeDeletedChild = diffs.removeChild(ListType.DELETED, deletedChild); // pass null for inodeMap since the parent node will not get replaced when // undoing rename final boolean added = addChild(deletedChild, true, removeDeletedChild ? null : latestSnapshot, null); // update quota usage if adding is successfully and the old child has not // been stored in deleted list before if (added && !removeDeletedChild) { final Quota.Counts counts = deletedChild.computeQuotaUsage(); addSpaceConsumed(counts.get(Quota.NAMESPACE), counts.get(Quota.DISKSPACE), false); } }
@Override public final Quota.Counts computeQuotaUsage(Quota.Counts counts, boolean useCache, int lastSnapshotId) { if ((useCache && isQuotaSet()) || lastSnapshotId == Snapshot.INVALID_ID) { return super.computeQuotaUsage(counts, useCache, lastSnapshotId); } Snapshot lastSnapshot = diffs.getSnapshotById(lastSnapshotId); ReadOnlyList<INode> childrenList = getChildrenList(lastSnapshot); for (INode child : childrenList) { child.computeQuotaUsage(counts, useCache, lastSnapshotId); } counts.add(Quota.NAMESPACE, 1); return counts; }
private static Quota.Counts updateQuotaAndCollectBlocks( INodeFile currentINode, FileDiff removed, BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { FileWithSnapshot sFile = (FileWithSnapshot) currentINode; long oldDiskspace = currentINode.diskspaceConsumed(); if (removed.snapshotINode != null) { short replication = removed.snapshotINode.getFileReplication(); short currentRepl = currentINode.getBlockReplication(); if (currentRepl == 0) { oldDiskspace = currentINode.computeFileSize(true, true) * replication; } else if (replication > currentRepl) { oldDiskspace = oldDiskspace / currentINode.getBlockReplication() * replication; } } Util.collectBlocksAndClear(sFile, collectedBlocks, removedINodes); long dsDelta = oldDiskspace - currentINode.diskspaceConsumed(); return Quota.Counts.newInstance(0, dsDelta); }
private void checkQuotaUsageComputation(final Path dirPath, final long expectedNs, final long expectedDs) throws IOException { INode node = fsdir.getINode(dirPath.toString()); assertTrue(node.isDirectory() && node.isQuotaSet()); INodeDirectoryWithQuota dirNode = (INodeDirectoryWithQuota) node; assertEquals(dirNode.dumpTreeRecursively().toString(), expectedNs, dirNode.getNamespace()); assertEquals(dirNode.dumpTreeRecursively().toString(), expectedDs, dirNode.getDiskspace()); Quota.Counts counts = Quota.Counts.newInstance(); dirNode.computeQuotaUsage(counts, false); assertEquals(dirNode.dumpTreeRecursively().toString(), expectedNs, counts.get(Quota.NAMESPACE)); assertEquals(dirNode.dumpTreeRecursively().toString(), expectedDs, counts.get(Quota.DISKSPACE)); }
public Quota.Counts cleanFile(final INodeFile file, final int snapshotId, int priorSnapshotId, final BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes, final boolean countDiffChange) throws QuotaExceededException { if (snapshotId == Snapshot.CURRENT_STATE_ID) { // delete the current file while the file has snapshot feature if (!isCurrentFileDeleted()) { file.recordModification(priorSnapshotId); deleteCurrentFile(); } collectBlocksAndClear(file, collectedBlocks, removedINodes); return Quota.Counts.newInstance(); } else { // delete the snapshot priorSnapshotId = getDiffs().updatePrior(snapshotId, priorSnapshotId); return diffs.deleteSnapshotDiff(snapshotId, priorSnapshotId, file, collectedBlocks, removedINodes, countDiffChange); } }
@Override Quota.Counts combinePosteriorAndCollectBlocks(INodeFile currentINode, FileDiff posterior, BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { return currentINode.getFileWithSnapshotFeature() .updateQuotaAndCollectBlocks(currentINode, posterior, collectedBlocks, removedINodes); }
@Override Quota.Counts destroyDiffAndCollectBlocks(INodeFile currentINode, BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { return currentINode.getFileWithSnapshotFeature() .updateQuotaAndCollectBlocks(currentINode, this, collectedBlocks, removedINodes); }
/** * Delete a snapshot. The synchronization of the diff list will be done * outside. If the diff to remove is not the first one in the diff list, we * need to combine the diff with its previous one. * * @param snapshot The id of the snapshot to be deleted * @param prior The id of the snapshot taken before the to-be-deleted snapshot * @param collectedBlocks Used to collect information for blocksMap update * @return delta in namespace. */ public final Quota.Counts deleteSnapshotDiff(final int snapshot, final int prior, final N currentINode, final BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { int snapshotIndex = Collections.binarySearch(diffs, snapshot); Quota.Counts counts = Quota.Counts.newInstance(); D removed = null; if (snapshotIndex == 0) { if (prior != Snapshot.NO_SNAPSHOT_ID) { // there is still snapshot before // set the snapshot to latestBefore diffs.get(snapshotIndex).setSnapshotId(prior); } else { // there is no snapshot before removed = diffs.remove(0); counts.add(removed.destroyDiffAndCollectBlocks(currentINode, collectedBlocks, removedINodes)); } } else if (snapshotIndex > 0) { final AbstractINodeDiff<N, A, D> previous = diffs.get(snapshotIndex - 1); if (previous.getSnapshotId() != prior) { diffs.get(snapshotIndex).setSnapshotId(prior); } else { // combine the to-be-removed diff with its previous diff removed = diffs.remove(snapshotIndex); if (previous.snapshotINode == null) { previous.snapshotINode = removed.snapshotINode; } counts.add(previous.combinePosteriorAndCollectBlocks( currentINode, removed, collectedBlocks, removedINodes)); previous.setPosterior(removed.getPosterior()); removed.setPosterior(null); } } return counts; }
/** * Remove the snapshot with the given name from {@link #snapshotsByNames}, * and delete all the corresponding DirectoryDiff. * * @param snapshotRoot The directory where we take snapshots * @param snapshotName The name of the snapshot to be removed * @param collectedBlocks Used to collect information to update blocksMap * @return The removed snapshot. Null if no snapshot with the given name * exists. */ public Snapshot removeSnapshot(INodeDirectory snapshotRoot, String snapshotName, BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) throws SnapshotException { final int i = searchSnapshot(DFSUtil.string2Bytes(snapshotName)); if (i < 0) { throw new SnapshotException("Cannot delete snapshot " + snapshotName + " from path " + snapshotRoot.getFullPathName() + ": the snapshot does not exist."); } else { final Snapshot snapshot = snapshotsByNames.get(i); int prior = Snapshot.findLatestSnapshot(snapshotRoot, snapshot.getId()); try { Quota.Counts counts = snapshotRoot.cleanSubtree(snapshot.getId(), prior, collectedBlocks, removedINodes); INodeDirectory parent = snapshotRoot.getParent(); if (parent != null) { // there will not be any WithName node corresponding to the deleted // snapshot, thus only update the quota usage in the current tree parent.addSpaceConsumed(-counts.get(Quota.NAMESPACE), -counts.get(Quota.DISKSPACE), true); } } catch(QuotaExceededException e) { INode.LOG.error("BUG: removeSnapshot increases namespace usage.", e); } // remove from snapshotsByNames after successfully cleaning the subtree snapshotsByNames.remove(i); return snapshot; } }