3636
3737import org .apache .hadoop .thirdparty .com .google .common .collect .Iterators ;
3838import org .apache .hadoop .thirdparty .com .google .common .util .concurrent .ThreadFactoryBuilder ;
39+ import org .apache .hadoop .util .Timer ;
3940import org .slf4j .Logger ;
4041import org .slf4j .LoggerFactory ;
4142import org .apache .hadoop .classification .InterfaceAudience ;
5556import org .apache .hadoop .ipc .RPC ;
5657import org .apache .hadoop .security .SecurityUtil ;
5758
58- import static org .apache .hadoop .util .Time .monotonicNow ;
5959import static org .apache .hadoop .util .ExitUtil .terminate ;
6060
6161import org .apache .hadoop .thirdparty .com .google .common .annotations .VisibleForTesting ;
6262import org .apache .hadoop .thirdparty .com .google .common .base .Preconditions ;
63- import org .apache .hadoop .util .Time ;
6463
6564
6665/**
@@ -172,14 +171,21 @@ public class EditLogTailer {
172171 */
173172 private final long maxTxnsPerLock ;
174173
174+ /**
175+ * Timer instance to be set only using constructor.
176+ * Only tests can reassign this by using setTimerForTests().
177+ * For source code, this timer instance should be treated as final.
178+ */
179+ private Timer timer ;
180+
175181 public EditLogTailer (FSNamesystem namesystem , Configuration conf ) {
176182 this .tailerThread = new EditLogTailerThread ();
177183 this .conf = conf ;
178184 this .namesystem = namesystem ;
185+ this .timer = new Timer ();
179186 this .editLog = namesystem .getEditLog ();
180-
181- lastLoadTimeMs = monotonicNow ();
182- resetLastRollTimeMs ();
187+ this .lastLoadTimeMs = timer .monotonicNow ();
188+ this .lastRollTimeMs = timer .monotonicNow ();
183189
184190 logRollPeriodMs = conf .getTimeDuration (
185191 DFSConfigKeys .DFS_HA_LOGROLL_PERIOD_KEY ,
@@ -301,7 +307,7 @@ public Void run() throws Exception {
301307 long editsTailed = 0 ;
302308 // Fully tail the journal to the end
303309 do {
304- long startTime = Time .monotonicNow ();
310+ long startTime = timer .monotonicNow ();
305311 try {
306312 NameNode .getNameNodeMetrics ().addEditLogTailInterval (
307313 startTime - lastLoadTimeMs );
@@ -312,7 +318,7 @@ public Void run() throws Exception {
312318 throw new IOException (e );
313319 } finally {
314320 NameNode .getNameNodeMetrics ().addEditLogTailTime (
315- Time .monotonicNow () - startTime );
321+ timer .monotonicNow () - startTime );
316322 }
317323 } while (editsTailed > 0 );
318324 return null ;
@@ -336,7 +342,7 @@ public long doTailEdits() throws IOException, InterruptedException {
336342 LOG .debug ("lastTxnId: " + lastTxnId );
337343 }
338344 Collection <EditLogInputStream > streams ;
339- long startTime = Time .monotonicNow ();
345+ long startTime = timer .monotonicNow ();
340346 try {
341347 streams = editLog .selectInputStreams (lastTxnId + 1 , 0 ,
342348 null , inProgressOk , true );
@@ -349,7 +355,7 @@ public long doTailEdits() throws IOException, InterruptedException {
349355 return 0 ;
350356 } finally {
351357 NameNode .getNameNodeMetrics ().addEditLogFetchTime (
352- Time .monotonicNow () - startTime );
358+ timer .monotonicNow () - startTime );
353359 }
354360 if (LOG .isDebugEnabled ()) {
355361 LOG .debug ("edit streams to load from: " + streams .size ());
@@ -374,7 +380,7 @@ public long doTailEdits() throws IOException, InterruptedException {
374380 }
375381
376382 if (editsLoaded > 0 ) {
377- lastLoadTimeMs = monotonicNow ();
383+ lastLoadTimeMs = timer . monotonicNow ();
378384 }
379385 lastLoadedTxnId = image .getLastAppliedTxId ();
380386 return editsLoaded ;
@@ -395,7 +401,7 @@ public long getLastLoadTimeMs() {
395401 */
396402 private boolean tooLongSinceLastLoad () {
397403 return logRollPeriodMs >= 0 &&
398- (monotonicNow () - lastRollTimeMs ) > logRollPeriodMs ;
404+ (timer . monotonicNow () - lastRollTimeMs ) > logRollPeriodMs ;
399405 }
400406
401407 /**
@@ -423,20 +429,38 @@ void triggerActiveLogRoll() {
423429 try {
424430 future = rollEditsRpcExecutor .submit (getNameNodeProxy ());
425431 future .get (rollEditsTimeoutMs , TimeUnit .MILLISECONDS );
426- resetLastRollTimeMs ();
432+ this . lastRollTimeMs = timer . monotonicNow ();
427433 lastRollTriggerTxId = lastLoadedTxnId ;
428434 } catch (ExecutionException | InterruptedException e ) {
429435 LOG .warn ("Unable to trigger a roll of the active NN" , e );
430436 } catch (TimeoutException e ) {
431- future .cancel (true );
437+ if (future != null ) {
438+ future .cancel (true );
439+ }
432440 LOG .warn (String .format (
433441 "Unable to finish rolling edits in %d ms" , rollEditsTimeoutMs ));
434442 }
435443 }
436444
445+ /**
446+ * This is only to be used by tests. For source code, the only way to
447+ * set timer is by using EditLogTailer constructor.
448+ *
449+ * @param newTimer Timer instance provided by tests.
450+ */
451+ @ VisibleForTesting
452+ void setTimerForTest (final Timer newTimer ) {
453+ this .timer = newTimer ;
454+ }
455+
456+ /**
457+ * Used by tests. Return Timer instance used by EditLogTailer.
458+ *
459+ * @return Return Timer instance used by EditLogTailer.
460+ */
437461 @ VisibleForTesting
438- public void resetLastRollTimeMs () {
439- this . lastRollTimeMs = monotonicNow () ;
462+ Timer getTimer () {
463+ return timer ;
440464 }
441465
442466 @ VisibleForTesting
@@ -498,15 +522,15 @@ private void doWork() {
498522 // name system lock will be acquired to further block even the block
499523 // state updates.
500524 namesystem .cpLockInterruptibly ();
501- long startTime = Time .monotonicNow ();
525+ long startTime = timer .monotonicNow ();
502526 try {
503527 NameNode .getNameNodeMetrics ().addEditLogTailInterval (
504528 startTime - lastLoadTimeMs );
505529 editsTailed = doTailEdits ();
506530 } finally {
507531 namesystem .cpUnlock ();
508532 NameNode .getNameNodeMetrics ().addEditLogTailTime (
509- Time .monotonicNow () - startTime );
533+ timer .monotonicNow () - startTime );
510534 }
511535 //Update NameDirSize Metric
512536 if (triggeredLogRoll ) {
0 commit comments