|
@@ -0,0 +1,119 @@
|
|
|
+/**
|
|
|
+ * Licensed to the Apache Software Foundation (ASF) under one
|
|
|
+ * or more contributor license agreements. See the NOTICE file
|
|
|
+ * distributed with this work for additional information
|
|
|
+ * regarding copyright ownership. The ASF licenses this file
|
|
|
+ * to you under the Apache License, Version 2.0 (the
|
|
|
+ * "License"); you may not use this file except in compliance
|
|
|
+ * with the License. You may obtain a copy of the License at
|
|
|
+ *
|
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+ *
|
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+ * See the License for the specific language governing permissions and
|
|
|
+ * limitations under the License.
|
|
|
+ */
|
|
|
+package org.apache.hadoop.hdfs.server.namenode;
|
|
|
+
|
|
|
+import org.apache.hadoop.classification.InterfaceAudience;
|
|
|
+import org.apache.hadoop.classification.InterfaceStability;
|
|
|
+
|
|
|
+@InterfaceAudience.Private
|
|
|
+@InterfaceStability.Unstable
|
|
|
+public class ContentSummaryComputationContext {
|
|
|
+ private FSDirectory dir = null;
|
|
|
+ private FSNamesystem fsn = null;
|
|
|
+ private Content.Counts counts = null;
|
|
|
+ private long nextCountLimit = 0;
|
|
|
+ private long limitPerRun = 0;
|
|
|
+ private long yieldCount = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Constructor
|
|
|
+ *
|
|
|
+ * @param dir The FSDirectory instance
|
|
|
+ * @param fsn The FSNamesystem instance
|
|
|
+ * @param limitPerRun allowed number of operations in one
|
|
|
+ * locking period. 0 or a negative number means
|
|
|
+ * no limit (i.e. no yielding)
|
|
|
+ */
|
|
|
+ public ContentSummaryComputationContext(FSDirectory dir,
|
|
|
+ FSNamesystem fsn, long limitPerRun) {
|
|
|
+ this.dir = dir;
|
|
|
+ this.fsn = fsn;
|
|
|
+ this.limitPerRun = limitPerRun;
|
|
|
+ this.nextCountLimit = limitPerRun;
|
|
|
+ this.counts = Content.Counts.newInstance();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Constructor for blocking computation. */
|
|
|
+ public ContentSummaryComputationContext() {
|
|
|
+ this(null, null, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Return current yield count */
|
|
|
+ public long getYieldCount() {
|
|
|
+ return yieldCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Relinquish locks held during computation for a short while
|
|
|
+ * and reacquire them. This will give other threads a chance
|
|
|
+ * to acquire the contended locks and run.
|
|
|
+ *
|
|
|
+ * @return true if locks were released and reacquired.
|
|
|
+ */
|
|
|
+ public boolean yield() {
|
|
|
+ // Are we set up to do this?
|
|
|
+ if (limitPerRun <= 0 || dir == null || fsn == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Have we reached the limit?
|
|
|
+ long currentCount = counts.get(Content.FILE) +
|
|
|
+ counts.get(Content.SYMLINK) +
|
|
|
+ counts.get(Content.DIRECTORY) +
|
|
|
+ counts.get(Content.SNAPSHOTTABLE_DIRECTORY);
|
|
|
+ if (currentCount <= nextCountLimit) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update the next limit
|
|
|
+ nextCountLimit = currentCount + limitPerRun;
|
|
|
+
|
|
|
+ boolean hadDirReadLock = dir.hasReadLock();
|
|
|
+ boolean hadDirWriteLock = dir.hasWriteLock();
|
|
|
+ boolean hadFsnReadLock = fsn.hasReadLock();
|
|
|
+ boolean hadFsnWriteLock = fsn.hasWriteLock();
|
|
|
+
|
|
|
+ // sanity check.
|
|
|
+ if (!hadDirReadLock || !hadFsnReadLock || hadDirWriteLock ||
|
|
|
+ hadFsnWriteLock || dir.getReadHoldCount() != 1 ||
|
|
|
+ fsn.getReadHoldCount() != 1) {
|
|
|
+ // cannot relinquish
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // unlock
|
|
|
+ dir.readUnlock();
|
|
|
+ fsn.readUnlock();
|
|
|
+
|
|
|
+ try {
|
|
|
+ Thread.sleep(1);
|
|
|
+ } catch (InterruptedException ie) {
|
|
|
+ } finally {
|
|
|
+ // reacquire
|
|
|
+ fsn.readLock();
|
|
|
+ dir.readLock();
|
|
|
+ }
|
|
|
+ yieldCount++;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Get the content counts */
|
|
|
+ public Content.Counts getCounts() {
|
|
|
+ return counts;
|
|
|
+ }
|
|
|
+}
|