001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.master;
019
020import static org.apache.hadoop.hbase.SplitLogCounters.resetCounters;
021import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_heartbeat;
022import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_node_create_queued;
023import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_orphan_task_acquired;
024import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_rescan;
025import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_rescan_deleted;
026import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_resubmit;
027import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_resubmit_dead_server_task;
028import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_resubmit_failed;
029import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_resubmit_force;
030import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_resubmit_threshold_reached;
031import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_resubmit_unassigned;
032import static org.apache.hadoop.hbase.SplitLogCounters.tot_mgr_task_deleted;
033import static org.junit.Assert.assertEquals;
034import static org.junit.Assert.assertFalse;
035import static org.junit.Assert.assertTrue;
036
037import java.io.IOException;
038import java.util.Map;
039import java.util.concurrent.atomic.LongAdder;
040import org.apache.hadoop.conf.Configuration;
041import org.apache.hadoop.fs.FileSystem;
042import org.apache.hadoop.fs.Path;
043import org.apache.hadoop.hbase.CoordinatedStateManager;
044import org.apache.hadoop.hbase.HBaseClassTestRule;
045import org.apache.hadoop.hbase.HBaseTestingUtil;
046import org.apache.hadoop.hbase.HConstants;
047import org.apache.hadoop.hbase.ServerName;
048import org.apache.hadoop.hbase.SplitLogCounters;
049import org.apache.hadoop.hbase.SplitLogTask;
050import org.apache.hadoop.hbase.Waiter;
051import org.apache.hadoop.hbase.coordination.ZKSplitLogManagerCoordination;
052import org.apache.hadoop.hbase.coordination.ZkCoordinatedStateManager;
053import org.apache.hadoop.hbase.master.SplitLogManager.Task;
054import org.apache.hadoop.hbase.master.SplitLogManager.TaskBatch;
055import org.apache.hadoop.hbase.testclassification.LargeTests;
056import org.apache.hadoop.hbase.testclassification.MasterTests;
057import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
058import org.apache.hadoop.hbase.zookeeper.TestMasterAddressTracker.NodeCreationListener;
059import org.apache.hadoop.hbase.zookeeper.ZKSplitLog;
060import org.apache.hadoop.hbase.zookeeper.ZKUtil;
061import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
062import org.apache.zookeeper.CreateMode;
063import org.apache.zookeeper.KeeperException;
064import org.apache.zookeeper.ZooDefs.Ids;
065import org.junit.After;
066import org.junit.Assert;
067import org.junit.Before;
068import org.junit.ClassRule;
069import org.junit.Test;
070import org.junit.experimental.categories.Category;
071import org.mockito.Mockito;
072import org.slf4j.Logger;
073import org.slf4j.LoggerFactory;
074
075@Category({ MasterTests.class, LargeTests.class })
076public class TestSplitLogManager {
077
078  @ClassRule
079  public static final HBaseClassTestRule CLASS_RULE =
080    HBaseClassTestRule.forClass(TestSplitLogManager.class);
081
082  private static final Logger LOG = LoggerFactory.getLogger(TestSplitLogManager.class);
083
084  private final ServerManager sm = Mockito.mock(ServerManager.class);
085
086  private ZKWatcher zkw;
087  private DummyMasterServices master;
088  private SplitLogManager slm;
089  private Configuration conf;
090  private int to;
091
092  private static HBaseTestingUtil TEST_UTIL;
093
094  class DummyMasterServices extends MockNoopMasterServices {
095    private ZKWatcher zkw;
096    private CoordinatedStateManager cm;
097
098    public DummyMasterServices(ZKWatcher zkw, Configuration conf) {
099      super(conf);
100      this.zkw = zkw;
101      cm = new ZkCoordinatedStateManager(this);
102    }
103
104    @Override
105    public ZKWatcher getZooKeeper() {
106      return zkw;
107    }
108
109    @Override
110    public CoordinatedStateManager getCoordinatedStateManager() {
111      return cm;
112    }
113
114    @Override
115    public ServerManager getServerManager() {
116      return sm;
117    }
118  }
119
120  @Before
121  public void setup() throws Exception {
122    TEST_UTIL = new HBaseTestingUtil();
123    TEST_UTIL.startMiniZKCluster();
124    conf = TEST_UTIL.getConfiguration();
125    // Use a different ZK wrapper instance for each tests.
126    zkw =
127      new ZKWatcher(conf, "split-log-manager-tests" + TEST_UTIL.getRandomUUID().toString(), null);
128    master = new DummyMasterServices(zkw, conf);
129
130    ZKUtil.deleteChildrenRecursively(zkw, zkw.getZNodePaths().baseZNode);
131    ZKUtil.createAndFailSilent(zkw, zkw.getZNodePaths().baseZNode);
132    assertTrue(ZKUtil.checkExists(zkw, zkw.getZNodePaths().baseZNode) != -1);
133    LOG.debug(zkw.getZNodePaths().baseZNode + " created");
134    ZKUtil.createAndFailSilent(zkw, zkw.getZNodePaths().splitLogZNode);
135    assertTrue(ZKUtil.checkExists(zkw, zkw.getZNodePaths().splitLogZNode) != -1);
136    LOG.debug(zkw.getZNodePaths().splitLogZNode + " created");
137
138    resetCounters();
139
140    // By default, we let the test manage the error as before, so the server
141    // does not appear as dead from the master point of view, only from the split log pov.
142    Mockito.when(sm.isServerOnline(Mockito.any())).thenReturn(true);
143
144    to = 12000;
145    conf.setInt(HConstants.HBASE_SPLITLOG_MANAGER_TIMEOUT, to);
146    conf.setInt("hbase.splitlog.manager.unassigned.timeout", 2 * to);
147
148    conf.setInt("hbase.splitlog.manager.timeoutmonitor.period", 100);
149    to = to + 16 * 100;
150  }
151
152  @After
153  public void teardown() throws IOException, KeeperException {
154    master.stop("");
155    if (slm != null) {
156      slm.stop();
157    }
158    TEST_UTIL.shutdownMiniZKCluster();
159  }
160
161  @Test
162  public void testBatchWaitMillis() {
163    assertEquals(100, SplitLogManager.getBatchWaitTimeMillis(0));
164    assertEquals(100, SplitLogManager.getBatchWaitTimeMillis(1));
165    assertEquals(1000, SplitLogManager.getBatchWaitTimeMillis(10));
166    assertEquals(60_000, SplitLogManager.getBatchWaitTimeMillis(101));
167    assertEquals(60_000, SplitLogManager.getBatchWaitTimeMillis(1011));
168  }
169
170  private interface Expr {
171    long eval();
172  }
173
174  private void waitForCounter(final LongAdder ctr, long oldval, long newval, long timems)
175    throws Exception {
176    Expr e = new Expr() {
177      @Override
178      public long eval() {
179        return ctr.sum();
180      }
181    };
182    waitForCounter(e, oldval, newval, timems);
183    return;
184  }
185
186  private void waitForCounter(final Expr e, final long oldval, long newval, long timems)
187    throws Exception {
188
189    TEST_UTIL.waitFor(timems, 10, new Waiter.Predicate<Exception>() {
190      @Override
191      public boolean evaluate() throws Exception {
192        return (e.eval() != oldval);
193      }
194    });
195
196    assertEquals(newval, e.eval());
197  }
198
199  private Task findOrCreateOrphanTask(String path) {
200    return slm.tasks.computeIfAbsent(path, k -> {
201      LOG.info("creating orphan task " + k);
202      SplitLogCounters.tot_mgr_orphan_task_acquired.increment();
203      return new Task();
204    });
205  }
206
207  private String submitTaskAndWait(TaskBatch batch, String name)
208    throws KeeperException, InterruptedException {
209    String tasknode = ZKSplitLog.getEncodedNodeName(zkw, name);
210    NodeCreationListener listener = new NodeCreationListener(zkw, tasknode);
211    zkw.registerListener(listener);
212    ZKUtil.watchAndCheckExists(zkw, tasknode);
213
214    slm.enqueueSplitTask(name, batch);
215    assertEquals(1, batch.installed);
216    assertTrue(findOrCreateOrphanTask(tasknode).batch == batch);
217    assertEquals(1L, tot_mgr_node_create_queued.sum());
218
219    LOG.debug("waiting for task node creation");
220    listener.waitForCreation();
221    LOG.debug("task created");
222    return tasknode;
223  }
224
225  /**
226   * Test whether the splitlog correctly creates a task in zookeeper
227   */
228  @Test
229  public void testTaskCreation() throws Exception {
230
231    LOG.info("TestTaskCreation - test the creation of a task in zk");
232    slm = new SplitLogManager(master, conf);
233    TaskBatch batch = new TaskBatch();
234
235    String tasknode = submitTaskAndWait(batch, "foo/1");
236
237    byte[] data = ZKUtil.getData(zkw, tasknode);
238    SplitLogTask slt = SplitLogTask.parseFrom(data);
239    LOG.info("Task node created " + slt.toString());
240    assertTrue(slt.isUnassigned(master.getServerName()));
241  }
242
243  @Test
244  public void testOrphanTaskAcquisition() throws Exception {
245    LOG.info("TestOrphanTaskAcquisition");
246
247    String tasknode = ZKSplitLog.getEncodedNodeName(zkw, "orphan/test/slash");
248    SplitLogTask slt = new SplitLogTask.Owned(master.getServerName());
249    zkw.getRecoverableZooKeeper().create(tasknode, slt.toByteArray(), Ids.OPEN_ACL_UNSAFE,
250      CreateMode.PERSISTENT);
251
252    slm = new SplitLogManager(master, conf);
253    waitForCounter(tot_mgr_orphan_task_acquired, 0, 1, to / 2);
254    Task task = findOrCreateOrphanTask(tasknode);
255    assertTrue(task.isOrphan());
256    waitForCounter(tot_mgr_heartbeat, 0, 1, to / 2);
257    assertFalse(task.isUnassigned());
258    long curt = EnvironmentEdgeManager.currentTime();
259    assertTrue((task.last_update <= curt) && (task.last_update > (curt - 1000)));
260    LOG.info("waiting for manager to resubmit the orphan task");
261    waitForCounter(tot_mgr_resubmit, 0, 1, to + to / 2);
262    assertTrue(task.isUnassigned());
263    waitForCounter(tot_mgr_rescan, 0, 1, to + to / 2);
264  }
265
266  @Test
267  public void testUnassignedOrphan() throws Exception {
268    LOG.info("TestUnassignedOrphan - an unassigned task is resubmitted at" + " startup");
269    String tasknode = ZKSplitLog.getEncodedNodeName(zkw, "orphan/test/slash");
270    // create an unassigned orphan task
271    SplitLogTask slt = new SplitLogTask.Unassigned(master.getServerName());
272    zkw.getRecoverableZooKeeper().create(tasknode, slt.toByteArray(), Ids.OPEN_ACL_UNSAFE,
273      CreateMode.PERSISTENT);
274    int version = ZKUtil.checkExists(zkw, tasknode);
275
276    slm = new SplitLogManager(master, conf);
277    waitForCounter(tot_mgr_orphan_task_acquired, 0, 1, to / 2);
278    Task task = findOrCreateOrphanTask(tasknode);
279    assertTrue(task.isOrphan());
280    assertTrue(task.isUnassigned());
281    // wait for RESCAN node to be created
282    waitForCounter(tot_mgr_rescan, 0, 1, to / 2);
283    Task task2 = findOrCreateOrphanTask(tasknode);
284    assertTrue(task == task2);
285    LOG.debug("task = " + task);
286    assertEquals(1L, tot_mgr_resubmit.sum());
287    assertEquals(1, task.incarnation.get());
288    assertEquals(0, task.unforcedResubmits.get());
289    assertTrue(task.isOrphan());
290    assertTrue(task.isUnassigned());
291    assertTrue(ZKUtil.checkExists(zkw, tasknode) > version);
292  }
293
294  @Test
295  public void testMultipleResubmits() throws Exception {
296    LOG.info("TestMultipleResbmits - no indefinite resubmissions");
297    conf.setInt("hbase.splitlog.max.resubmit", 2);
298    slm = new SplitLogManager(master, conf);
299    TaskBatch batch = new TaskBatch();
300
301    String tasknode = submitTaskAndWait(batch, "foo/1");
302    int version = ZKUtil.checkExists(zkw, tasknode);
303    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
304    final ServerName worker2 = ServerName.valueOf("worker2,1,1");
305    final ServerName worker3 = ServerName.valueOf("worker3,1,1");
306    SplitLogTask slt = new SplitLogTask.Owned(worker1);
307    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
308    waitForCounter(tot_mgr_heartbeat, 0, 1, to / 2);
309    waitForCounter(tot_mgr_resubmit, 0, 1, to + to / 2);
310    int version1 = ZKUtil.checkExists(zkw, tasknode);
311    assertTrue(version1 > version);
312    slt = new SplitLogTask.Owned(worker2);
313    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
314    waitForCounter(tot_mgr_heartbeat, 1, 2, to / 2);
315    waitForCounter(tot_mgr_resubmit, 1, 2, to + to / 2);
316    int version2 = ZKUtil.checkExists(zkw, tasknode);
317    assertTrue(version2 > version1);
318    slt = new SplitLogTask.Owned(worker3);
319    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
320    waitForCounter(tot_mgr_heartbeat, 2, 3, to / 2);
321    waitForCounter(tot_mgr_resubmit_threshold_reached, 0, 1, to + to / 2);
322    Thread.sleep(to + to / 2);
323    assertEquals(2L, tot_mgr_resubmit.sum() - tot_mgr_resubmit_force.sum());
324  }
325
326  @Test
327  public void testRescanCleanup() throws Exception {
328    LOG.info("TestRescanCleanup - ensure RESCAN nodes are cleaned up");
329
330    slm = new SplitLogManager(master, conf);
331    TaskBatch batch = new TaskBatch();
332
333    String tasknode = submitTaskAndWait(batch, "foo/1");
334    int version = ZKUtil.checkExists(zkw, tasknode);
335    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
336    SplitLogTask slt = new SplitLogTask.Owned(worker1);
337    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
338    waitForCounter(tot_mgr_heartbeat, 0, 1, to / 2);
339    waitForCounter(new Expr() {
340      @Override
341      public long eval() {
342        return (tot_mgr_resubmit.sum() + tot_mgr_resubmit_failed.sum());
343      }
344    }, 0, 1, 5 * 60000); // wait long enough
345    Assert.assertEquals("Could not run test. Lost ZK connection?", 0,
346      tot_mgr_resubmit_failed.sum());
347    int version1 = ZKUtil.checkExists(zkw, tasknode);
348    assertTrue(version1 > version);
349    byte[] taskstate = ZKUtil.getData(zkw, tasknode);
350    slt = SplitLogTask.parseFrom(taskstate);
351    assertTrue(slt.isUnassigned(master.getServerName()));
352
353    waitForCounter(tot_mgr_rescan_deleted, 0, 1, to / 2);
354  }
355
356  @Test
357  public void testTaskDone() throws Exception {
358    LOG.info("TestTaskDone - cleanup task node once in DONE state");
359
360    slm = new SplitLogManager(master, conf);
361    TaskBatch batch = new TaskBatch();
362    String tasknode = submitTaskAndWait(batch, "foo/1");
363    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
364    SplitLogTask slt = new SplitLogTask.Done(worker1);
365    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
366    synchronized (batch) {
367      while (batch.installed != batch.done) {
368        batch.wait();
369      }
370    }
371    waitForCounter(tot_mgr_task_deleted, 0, 1, to / 2);
372    assertTrue(ZKUtil.checkExists(zkw, tasknode) == -1);
373  }
374
375  @Test
376  public void testTaskErr() throws Exception {
377    LOG.info("TestTaskErr - cleanup task node once in ERR state");
378
379    conf.setInt("hbase.splitlog.max.resubmit", 0);
380    slm = new SplitLogManager(master, conf);
381    TaskBatch batch = new TaskBatch();
382
383    String tasknode = submitTaskAndWait(batch, "foo/1");
384    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
385    SplitLogTask slt = new SplitLogTask.Err(worker1);
386    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
387
388    synchronized (batch) {
389      while (batch.installed != batch.error) {
390        batch.wait();
391      }
392    }
393    waitForCounter(tot_mgr_task_deleted, 0, 1, to / 2);
394    assertTrue(ZKUtil.checkExists(zkw, tasknode) == -1);
395    conf.setInt("hbase.splitlog.max.resubmit", ZKSplitLogManagerCoordination.DEFAULT_MAX_RESUBMIT);
396  }
397
398  @Test
399  public void testTaskResigned() throws Exception {
400    LOG.info("TestTaskResigned - resubmit task node once in RESIGNED state");
401    assertEquals(0, tot_mgr_resubmit.sum());
402    slm = new SplitLogManager(master, conf);
403    assertEquals(0, tot_mgr_resubmit.sum());
404    TaskBatch batch = new TaskBatch();
405    String tasknode = submitTaskAndWait(batch, "foo/1");
406    assertEquals(0, tot_mgr_resubmit.sum());
407    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
408    assertEquals(0, tot_mgr_resubmit.sum());
409    SplitLogTask slt = new SplitLogTask.Resigned(worker1);
410    assertEquals(0, tot_mgr_resubmit.sum());
411    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
412    ZKUtil.checkExists(zkw, tasknode);
413    // Could be small race here.
414    if (tot_mgr_resubmit.sum() == 0) {
415      waitForCounter(tot_mgr_resubmit, 0, 1, to / 2);
416    }
417    assertEquals(1, tot_mgr_resubmit.sum());
418
419    byte[] taskstate = ZKUtil.getData(zkw, tasknode);
420    slt = SplitLogTask.parseFrom(taskstate);
421    assertTrue(slt.isUnassigned(master.getServerName()));
422  }
423
424  @Test
425  public void testUnassignedTimeout() throws Exception {
426    LOG.info("TestUnassignedTimeout - iff all tasks are unassigned then" + " resubmit");
427
428    // create an orphan task in OWNED state
429    String tasknode1 = ZKSplitLog.getEncodedNodeName(zkw, "orphan/1");
430    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
431    SplitLogTask slt = new SplitLogTask.Owned(worker1);
432    zkw.getRecoverableZooKeeper().create(tasknode1, slt.toByteArray(), Ids.OPEN_ACL_UNSAFE,
433      CreateMode.PERSISTENT);
434
435    slm = new SplitLogManager(master, conf);
436    waitForCounter(tot_mgr_orphan_task_acquired, 0, 1, to / 2);
437
438    // submit another task which will stay in unassigned mode
439    TaskBatch batch = new TaskBatch();
440    submitTaskAndWait(batch, "foo/1");
441
442    // keep updating the orphan owned node every to/2 seconds
443    for (int i = 0; i < (3 * to) / 100; i++) {
444      Thread.sleep(100);
445      final ServerName worker2 = ServerName.valueOf("worker1,1,1");
446      slt = new SplitLogTask.Owned(worker2);
447      ZKUtil.setData(zkw, tasknode1, slt.toByteArray());
448    }
449
450    // since we have stopped heartbeating the owned node therefore it should
451    // get resubmitted
452    LOG.info("waiting for manager to resubmit the orphan task");
453    waitForCounter(tot_mgr_resubmit, 0, 1, to + to / 2);
454
455    // now all the nodes are unassigned. manager should post another rescan
456    waitForCounter(tot_mgr_resubmit_unassigned, 0, 1, 2 * to + to / 2);
457  }
458
459  @Test
460  public void testDeadWorker() throws Exception {
461    LOG.info("testDeadWorker");
462
463    conf.setLong("hbase.splitlog.max.resubmit", 0);
464    slm = new SplitLogManager(master, conf);
465    TaskBatch batch = new TaskBatch();
466
467    String tasknode = submitTaskAndWait(batch, "foo/1");
468    int version = ZKUtil.checkExists(zkw, tasknode);
469    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
470    SplitLogTask slt = new SplitLogTask.Owned(worker1);
471    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
472    if (tot_mgr_heartbeat.sum() == 0) {
473      waitForCounter(tot_mgr_heartbeat, 0, 1, to / 2);
474    }
475    slm.handleDeadWorker(worker1);
476    if (tot_mgr_resubmit.sum() == 0) {
477      waitForCounter(tot_mgr_resubmit, 0, 1, to + to / 2);
478    }
479    if (tot_mgr_resubmit_dead_server_task.sum() == 0) {
480      waitForCounter(tot_mgr_resubmit_dead_server_task, 0, 1, to + to / 2);
481    }
482
483    int version1 = ZKUtil.checkExists(zkw, tasknode);
484    assertTrue(version1 > version);
485    byte[] taskstate = ZKUtil.getData(zkw, tasknode);
486    slt = SplitLogTask.parseFrom(taskstate);
487    assertTrue(slt.isUnassigned(master.getServerName()));
488    return;
489  }
490
491  @Test
492  public void testWorkerCrash() throws Exception {
493    slm = new SplitLogManager(master, conf);
494    TaskBatch batch = new TaskBatch();
495
496    String tasknode = submitTaskAndWait(batch, "foo/1");
497    final ServerName worker1 = ServerName.valueOf("worker1,1,1");
498
499    SplitLogTask slt = new SplitLogTask.Owned(worker1);
500    ZKUtil.setData(zkw, tasknode, slt.toByteArray());
501    if (tot_mgr_heartbeat.sum() == 0) {
502      waitForCounter(tot_mgr_heartbeat, 0, 1, to / 2);
503    }
504
505    // Not yet resubmitted.
506    Assert.assertEquals(0, tot_mgr_resubmit.sum());
507
508    // This server becomes dead
509    Mockito.when(sm.isServerOnline(worker1)).thenReturn(false);
510
511    Thread.sleep(1300); // The timeout checker is done every 1000 ms (hardcoded).
512
513    // It has been resubmitted
514    Assert.assertEquals(1, tot_mgr_resubmit.sum());
515  }
516
517  @Test
518  public void testEmptyLogDir() throws Exception {
519    LOG.info("testEmptyLogDir");
520    slm = new SplitLogManager(master, conf);
521    FileSystem fs = TEST_UTIL.getTestFileSystem();
522    Path emptyLogDirPath =
523      new Path(new Path(fs.getWorkingDirectory(), HConstants.HREGION_LOGDIR_NAME),
524        ServerName.valueOf("emptyLogDir", 1, 1).toString());
525    fs.mkdirs(emptyLogDirPath);
526    slm.splitLogDistributed(emptyLogDirPath);
527    assertFalse(fs.exists(emptyLogDirPath));
528  }
529
530  @Test
531  public void testLogFilesAreArchived() throws Exception {
532    LOG.info("testLogFilesAreArchived");
533    slm = new SplitLogManager(master, conf);
534    FileSystem fs = TEST_UTIL.getTestFileSystem();
535    Path dir = TEST_UTIL.getDataTestDirOnTestFS("testLogFilesAreArchived");
536    conf.set(HConstants.HBASE_DIR, dir.toString());
537    String serverName = ServerName.valueOf("foo", 1, 1).toString();
538    Path logDirPath = new Path(new Path(dir, HConstants.HREGION_LOGDIR_NAME), serverName);
539    fs.mkdirs(logDirPath);
540    // create an empty log file
541    String logFile = new Path(logDirPath, TEST_UTIL.getRandomUUID().toString()).toString();
542    fs.create(new Path(logDirPath, logFile)).close();
543
544    // spin up a thread mocking split done.
545    new Thread() {
546      @Override
547      public void run() {
548        boolean done = false;
549        while (!done) {
550          for (Map.Entry<String, Task> entry : slm.getTasks().entrySet()) {
551            final ServerName worker1 = ServerName.valueOf("worker1,1,1");
552            SplitLogTask slt = new SplitLogTask.Done(worker1);
553            boolean encounteredZKException = false;
554            try {
555              ZKUtil.setData(zkw, entry.getKey(), slt.toByteArray());
556            } catch (KeeperException e) {
557              LOG.warn(e.toString(), e);
558              encounteredZKException = true;
559            }
560            if (!encounteredZKException) {
561              done = true;
562            }
563          }
564        }
565      }
566    }.start();
567
568    slm.splitLogDistributed(logDirPath);
569
570    assertFalse(fs.exists(logDirPath));
571  }
572}