/**
* Licensed to Cloudera, Inc. under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Cloudera, Inc. 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 com.cloudera.flume.agent.durability;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import com.cloudera.flume.conf.FlumeSpecException;
import com.cloudera.flume.core.Event;
import com.cloudera.flume.core.EventImpl;
import com.cloudera.flume.core.EventSink;
import com.cloudera.flume.core.EventSource;
import com.cloudera.flume.handlers.debug.ConsoleEventSink;
import com.cloudera.flume.handlers.rolling.ProcessTagger;
import com.cloudera.flume.handlers.rolling.Tagger;
import com.cloudera.util.BenchmarkHarness;
import com.cloudera.util.FileUtil;
public class TestNaiveFileWALManager {
// has 5 good entries.
final static String WAL_OK = "src/data/hadoop_logs_5.hdfs";
public static Logger LOG = Logger.getLogger(TestNaiveFileWALManager.class);
@Before
public void setUp() {
LOG.setLevel(Level.DEBUG);
}
/**
* Tests import to make sure it gets into the logged state properly.
*/
@Test
public void testImport() throws IOException {
File dir = FileUtil.mktempdir();
// putting in large ridiculous constant
NaiveFileWALManager wal = new NaiveFileWALManager(dir);
wal.open();
File logdir = new File(dir, NaiveFileWALManager.IMPORTDIR);
File src = new File(WAL_OK);
File dest = new File(logdir, "ok.0000000.20091104-101213997-0800.seq");
FileUtil.dumbfilecopy(src, dest);
dest.deleteOnExit();
assertEquals(0, wal.getWritingTags().size());
assertEquals(0, wal.getLoggedTags().size());
assertEquals(0, wal.getSendingTags().size());
assertEquals(0, wal.getSentTags().size());
wal.importData();
assertEquals(0, wal.getWritingTags().size());
assertEquals(1, wal.getLoggedTags().size());
assertEquals(0, wal.getSendingTags().size());
assertEquals(0, wal.getSentTags().size());
wal.stopDrains();
}
@Test
public void testTransitions() throws IOException {
File dir = FileUtil.mktempdir();
// putting in large ridiculous constant
NaiveFileWALManager wal = new NaiveFileWALManager(dir);
wal.open();
// get a sink write to it and then be done with it.
Tagger t = new ProcessTagger();
EventSink sink = wal.newWritingSink(t);
sink.open();
sink.append(new EventImpl("foo".getBytes()));
assertEquals(1, wal.getWritingTags().size());
// close moves to logged state.
sink.close();
assertEquals(0, wal.getWritingTags().size());
assertEquals(1, wal.getLoggedTags().size());
// logged values can transition to the sending state by getting a sender.
EventSource curSource = wal.getUnackedSource();
// no state change
assertEquals(0, wal.getWritingTags().size());
assertEquals(0, wal.getLoggedTags().size());
assertEquals(1, wal.getSendingTags().size());
// open changes state
curSource.open();
assertEquals(0, wal.getLoggedTags().size());
assertEquals(1, wal.getSendingTags().size());
// read next event
Event e = null;
ConsoleEventSink console = new ConsoleEventSink();
while ((e = curSource.next()) != null) {
console.append(e);
}
curSource.close();
assertEquals(0, wal.getSendingTags().size());
assertEquals(1, wal.getSentTags().size());
// trigger to make it move from sent to acked/done
String tag = wal.getSentTags().iterator().next();
wal.toAcked(tag);
assertEquals(0, wal.getSentTags().size());
}
/**
* This test puts a file in each log dir and makes sure they are all
* recovered.
*/
@Test
public void testRecovers() throws IOException, FlumeSpecException {
BenchmarkHarness.setupLocalWriteDir();
File tmp = BenchmarkHarness.tmpdir;
// putting in large ridiculous constant
NaiveFileWALManager wal = new NaiveFileWALManager(tmp);
wal.open(); // create dirs
File acked = new File(WAL_OK);
// copy files and then recover them.
FileUtil.dumbfilecopy(acked, new File(wal.writingDir,
"writing.00000000.20100204-015814F430-0800.seq"));
FileUtil.dumbfilecopy(acked, new File(wal.loggedDir,
"logged.00000000.20100204-015814F430-0800.seq"));
FileUtil.dumbfilecopy(acked, new File(wal.sendingDir,
"sending.00000000.20100204-015814F430-0800.seq"));
FileUtil.dumbfilecopy(acked, new File(wal.sentDir,
"send.00000000.20100204-015814F430-0800.seq"));
FileUtil.dumbfilecopy(acked, new File(wal.importDir,
"import.00000000.20100204-015814F430-0800.seq"));
FileUtil.dumbfilecopy(acked, new File(wal.errorDir,
"error.00000000.20100204-015814F430-0800.seq"));
wal.recover();
// check to make sure wal file is gone
// assertTrue(new File(tmp, "import").list().length == 0);
assertEquals(0, new File(tmp, "writing").list().length);
assertEquals(0, new File(tmp, "sending").list().length);
assertEquals(0, new File(tmp, "sent").list().length);
assertEquals(0, new File(tmp, "done").list().length);
assertEquals(1, new File(tmp, "error").list().length);
assertEquals(4, new File(tmp, "logged").list().length);
BenchmarkHarness.cleanupLocalWriteDir();
}
/**
* Tests import to make sure it gets into the logged state properly.
*/
public void doTestBadOpen(String conflict) throws IOException {
File src = new File(WAL_OK);
File tmpdir = FileUtil.mktempdir();
FileUtil.dumbfilecopy(src, new File(tmpdir, conflict));
NaiveFileWALManager wal = new NaiveFileWALManager(tmpdir);
try {
wal.open();
} catch (IOException ioe) {
throw ioe;
} finally {
FileUtil.rmr(tmpdir);
}
}
/**
* Tests import to make sure we handle errors with dir problems
*/
@Test(expected = IOException.class)
public void testBadOpenImport() throws IOException {
doTestBadOpen(NaiveFileWALManager.IMPORTDIR);
}
/**
* Tests import to make sure we handle errors with dir problems
*/
@Test(expected = IOException.class)
public void testBadOpenWriting() throws IOException {
doTestBadOpen(NaiveFileWALManager.WRITINGDIR);
}
/**
* Tests import to make sure we handle errors with dir problems
*/
@Test(expected = IOException.class)
public void testBadOpenLogged() throws IOException {
doTestBadOpen(NaiveFileWALManager.LOGGEDDIR);
}
/**
* Tests import to make sure we handle errors with dir problems
*/
@Test(expected = IOException.class)
public void testBadOpenSending() throws IOException {
doTestBadOpen(NaiveFileWALManager.SENDINGDIR);
}
/**
* Tests import to make sure we handle errors with dir problems
*/
@Test(expected = IOException.class)
public void testBadOpenSent() throws IOException {
doTestBadOpen(NaiveFileWALManager.SENTDIR);
}
/**
* Tests import to make sure we handle errors with dir problems
*/
@Test(expected = IOException.class)
public void testBadOpenError() throws IOException {
doTestBadOpen(NaiveFileWALManager.ERRORDIR);
}
/**
* Tests import to make sure we handle errors with dir problems
*/
@Test(expected = IOException.class)
public void testBadOpenDone() throws IOException {
doTestBadOpen(NaiveFileWALManager.DONEDIR);
}
/**
* Tests import to make sure it gets into the logged state properly.
*/
public void doTestBadRecover(String conflict) throws IOException {
File tmpdir = FileUtil.mktempdir();
File dir = new File(new File(tmpdir, conflict), "foo");
dir.mkdirs();
NaiveFileWALManager wal = new NaiveFileWALManager(tmpdir);
wal.open();
try {
wal.recover();
} catch (IOException ioe) {
throw ioe;
} finally {
FileUtil.rmr(tmpdir);
}
}
@Test(expected = IOException.class)
public void testBadRecoverSent() throws IOException {
doTestBadRecover(NaiveFileWALManager.SENTDIR);
}
@Test(expected = IOException.class)
public void testBadRecoverSending() throws IOException {
doTestBadRecover(NaiveFileWALManager.SENDINGDIR);
}
@Test(expected = IOException.class)
public void testBadRecoverWriting() throws IOException {
doTestBadRecover(NaiveFileWALManager.WRITINGDIR);
}
}