/** Is this file has the snapshot feature? */ public final boolean isWithSnapshot() { return getDirectoryWithSnapshotFeature() != null; }
public DirectoryDiffList getDiffs() { DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); return sf != null ? sf.getDiffs() : null; }
@Override public String toDetailString() { DirectoryWithSnapshotFeature sf = this.getDirectoryWithSnapshotFeature(); return super.toDetailString() + (sf == null ? "" : ", " + sf.getDiffs()); }
@Override public INodeDirectoryAttributes getSnapshotINode(int snapshotId) { DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); return sf == null ? this : sf.getDiffs().getSnapshotINode(snapshotId, this); }
/** * Save the child to the latest snapshot. * * @return the child inode, which may be replaced. */ public INode saveChild2Snapshot(final INode child, final int latestSnapshotId, final INode snapshotCopy) { if (latestSnapshotId == Snapshot.CURRENT_STATE_ID) { return child; } // add snapshot feature if necessary DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); if (sf == null) { sf = this.addSnapshotFeature(null); } return sf.saveChild2Snapshot(this, child, latestSnapshotId, snapshotCopy); }
/** * @param snapshotId * if it is not {@link Snapshot#CURRENT_STATE_ID}, get the result * from the corresponding snapshot; otherwise, get the result from * the current directory. * @return the current children list if the specified snapshot is null; * otherwise, return the children list corresponding to the snapshot. * Note that the returned list is never null. */ public ReadOnlyList<INode> getChildrenList(final int snapshotId) { DirectoryWithSnapshotFeature sf; if (snapshotId == Snapshot.CURRENT_STATE_ID || (sf = this.getDirectoryWithSnapshotFeature()) == null) { return getCurrentChildrenList(); } return sf.getChildrenList(this, snapshotId); }
/** Add quota usage for this inode excluding children. */ public QuotaCounts computeQuotaUsage4CurrentDirectory( BlockStoragePolicySuite bsps, byte storagePolicyId, QuotaCounts counts) { counts.addNameSpace(1); // include the diff list DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); if (sf != null) { counts.add(sf.computeQuotaUsage4CurrentDirectory(bsps, storagePolicyId)); } return counts; }
/** add DirectorySnapshottableFeature */ public void addSnapshottableFeature() { Preconditions.checkState(!isSnapshottable(), "this is already snapshottable, this=%s", this); DirectoryWithSnapshotFeature s = this.getDirectoryWithSnapshotFeature(); final DirectorySnapshottableFeature snapshottable = new DirectorySnapshottableFeature(s); if (s != null) { this.removeFeature(s); } this.addFeature(snapshottable); }
/** * Remove the specified child from this directory. */ public boolean removeChild(INode child, int latestSnapshotId) { if (isInLatestSnapshot(latestSnapshotId)) { // create snapshot feature if necessary DirectoryWithSnapshotFeature sf = this.getDirectoryWithSnapshotFeature(); if (sf == null) { sf = this.addSnapshotFeature(null); } return sf.removeChild(this, child, latestSnapshotId); } return removeChild(child); }
/** * @param name the name of the child * @param snapshotId * if it is not {@link Snapshot#CURRENT_STATE_ID}, get the result * from the corresponding snapshot; otherwise, get the result from * the current directory. * @return the child inode. */ public INode getChild(byte[] name, int snapshotId) { DirectoryWithSnapshotFeature sf; if (snapshotId == Snapshot.CURRENT_STATE_ID || (sf = getDirectoryWithSnapshotFeature()) == null) { ReadOnlyList<INode> c = getCurrentChildrenList(); final int i = ReadOnlyList.Util.binarySearch(c, name); return i < 0 ? null : c.get(i); } return sf.getChild(this, name, snapshotId); }
@Override public void recordModification(int latestSnapshotId) { if (isInLatestSnapshot(latestSnapshotId) && !shouldRecordInSrcSnapshot(latestSnapshotId)) { // add snapshot feature if necessary DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); if (sf == null) { sf = addSnapshotFeature(null); } // record self in the diff list if necessary sf.getDiffs().saveSelf2Snapshot(latestSnapshotId, this, null); } }
/** * 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 BlockStoragePolicySuite bsps, final INode deletedChild, int latestSnapshotId) { DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); assert sf != null : "Directory does not have snapshot feature"; boolean removeDeletedChild = sf.getDiffs().removeDeletedChild(deletedChild); int sid = removeDeletedChild ? Snapshot.CURRENT_STATE_ID : latestSnapshotId; final boolean added = addChild(deletedChild, true, sid); // update quota usage if adding is successfully and the old child has not // been stored in deleted list before if (added && !removeDeletedChild) { final QuotaCounts counts = deletedChild.computeQuotaUsage(bsps); addSpaceConsumed(counts); } }
DirectoryWithSnapshotFeature sf = this.getDirectoryWithSnapshotFeature(); if (sf != null) { sf.getDiffs().replaceCreatedChild(oldChild, newChild);
@Override public void destroyAndCollectBlocks(ReclaimContext reclaimContext) { reclaimContext.quotaDelta().add( new QuotaCounts.Builder().nameSpace(1).build()); final DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); if (sf != null) { sf.clear(reclaimContext, this); } for (INode child : getChildrenList(Snapshot.CURRENT_STATE_ID)) { child.destroyAndCollectBlocks(reclaimContext); } if (getAclFeature() != null) { AclStorage.removeAclFeature(getAclFeature()); } clear(); reclaimContext.removedINodes.add(this); }
private int getSelfSnapshot() { INode referred = getReferredINode().asReference().getReferredINode(); int snapshot = Snapshot.NO_SNAPSHOT_ID; if (referred.isFile() && referred.asFile().isWithSnapshot()) { snapshot = referred.asFile().getDiffs().getPrior(lastSnapshotId); } else if (referred.isDirectory()) { DirectoryWithSnapshotFeature sf = referred.asDirectory() .getDirectoryWithSnapshotFeature(); if (sf != null) { snapshot = sf.getDiffs().getPrior(lastSnapshotId); } } return snapshot; } }
@Override public ContentSummaryComputationContext computeContentSummary(int snapshotId, ContentSummaryComputationContext summary) throws AccessControlException { final DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); if (sf != null && snapshotId == Snapshot.CURRENT_STATE_ID) { final ContentCounts counts = new ContentCounts.Builder().build(); // if the getContentSummary call is against a non-snapshot path, the // computation should include all the deleted files/directories sf.computeContentSummary4Snapshot(summary.getBlockStoragePolicySuite(), counts); summary.getCounts().addContents(counts); // Also add ContentSummary to snapshotCounts (So we can extract it // later from the ContentSummary of all). summary.getSnapshotCounts().addContents(counts); } final DirectoryWithQuotaFeature q = getDirectoryWithQuotaFeature(); if (q != null && snapshotId == Snapshot.CURRENT_STATE_ID) { return q.computeContentSummary(this, summary); } else { return computeDirectoryContentSummary(summary, snapshotId); } }
private int getSelfSnapshot(final int prior) { WithCount wc = (WithCount) getReferredINode().asReference(); INode referred = wc.getReferredINode(); int lastSnapshot = Snapshot.CURRENT_STATE_ID; if (referred.isFile() && referred.asFile().isWithSnapshot()) { lastSnapshot = referred.asFile().getDiffs().getLastSnapshotId(); } else if (referred.isDirectory()) { DirectoryWithSnapshotFeature sf = referred.asDirectory() .getDirectoryWithSnapshotFeature(); if (sf != null) { lastSnapshot = sf.getLastSnapshotId(); } } if (lastSnapshot != Snapshot.CURRENT_STATE_ID && lastSnapshot != prior) { return lastSnapshot; } else { return Snapshot.CURRENT_STATE_ID; } } }
@Override public void cleanSubtree(ReclaimContext reclaimContext, final int snapshotId, int priorSnapshotId) { DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature(); // there is snapshot data if (sf != null) { sf.cleanDirectory(reclaimContext, this, snapshotId, priorSnapshotId); } else { // there is no snapshot data if (priorSnapshotId == Snapshot.NO_SNAPSHOT_ID && snapshotId == Snapshot.CURRENT_STATE_ID) { // destroy the whole subtree and collect blocks that should be deleted destroyAndCollectBlocks(reclaimContext); } else { // make a copy the quota delta QuotaCounts old = reclaimContext.quotaDelta().getCountsCopy(); // process recursively down the subtree cleanSubtreeRecursively(reclaimContext, snapshotId, priorSnapshotId, null); QuotaCounts current = reclaimContext.quotaDelta().getCountsCopy(); current.subtract(old); if (isQuotaSet()) { reclaimContext.quotaDelta().addQuotaDirUpdate(this, current); } } } }
@Override public QuotaCounts computeQuotaUsage(BlockStoragePolicySuite bsps, byte blockStoragePolicyId, boolean useCache, int lastSnapshotId) { final DirectoryWithSnapshotFeature sf = getDirectoryWithSnapshotFeature();
/** * When destroying a reference node (WithName or DstReference), we call this * method to identify the snapshot which is the latest snapshot before the * reference node's creation. */ static int getPriorSnapshot(INodeReference ref) { WithCount wc = (WithCount) ref.getReferredINode(); WithName wn = null; if (ref instanceof DstReference) { wn = wc.getLastWithName(); } else if (ref instanceof WithName) { wn = wc.getPriorWithName((WithName) ref); } if (wn != null) { INode referred = wc.getReferredINode(); if (referred.isFile() && referred.asFile().isWithSnapshot()) { return referred.asFile().getDiffs().getPrior(wn.lastSnapshotId); } else if (referred.isDirectory()) { DirectoryWithSnapshotFeature sf = referred.asDirectory() .getDirectoryWithSnapshotFeature(); if (sf != null) { return sf.getDiffs().getPrior(wn.lastSnapshotId); } } } return Snapshot.NO_SNAPSHOT_ID; }