use of herddb.cluster.BookkeeperCommitLog in project herddb by diennea.
the class BookKeeperCommitLogTest method testFollowEmptyLedgerBookieDown.
@Test
public void testFollowEmptyLedgerBookieDown() throws Exception {
BookieId secondBookie = testEnv.startNewBookie();
final String tableSpaceUUID = UUID.randomUUID().toString();
final String name = TableSpace.DEFAULT;
final String nodeid = "nodeid";
ServerConfiguration serverConfiguration = newServerConfigurationWithAutoPort();
try (ZookeeperMetadataStorageManager man = new ZookeeperMetadataStorageManager(testEnv.getAddress(), testEnv.getTimeout(), testEnv.getPath());
BookkeeperCommitLogManager logManager = new BookkeeperCommitLogManager(man, serverConfiguration, NullStatsLogger.INSTANCE)) {
logManager.setEnsemble(2);
logManager.setWriteQuorumSize(2);
logManager.setAckQuorumSize(2);
man.start();
logManager.start();
try (BookkeeperCommitLog writer = logManager.createCommitLog(tableSpaceUUID, name, nodeid)) {
writer.startWriting(1);
// create a ledger, up to 0.14.x no "logical" write happens, so Bookies are not aware of the
// the ledger
// stop one bookie
testEnv.stopBookie(secondBookie);
// but since 0.15.0 we are now writing a NOOP entry at the beginning of the ledger in order to workaround this issue.
try (BookkeeperCommitLog reader = logManager.createCommitLog(tableSpaceUUID, name, nodeid)) {
reader.recovery(LogSequenceNumber.START_OF_TIME, (a, b) -> {
}, false);
}
}
}
}
use of herddb.cluster.BookkeeperCommitLog in project herddb by diennea.
the class BookKeeperCommitLogTest method testBookieFailureSyncWrites.
@Test
public void testBookieFailureSyncWrites() throws Exception {
final String tableSpaceUUID = UUID.randomUUID().toString();
final String name = TableSpace.DEFAULT;
final String nodeid = "nodeid";
ServerConfiguration serverConfiguration = newServerConfigurationWithAutoPort();
try (ZookeeperMetadataStorageManager man = new ZookeeperMetadataStorageManager(testEnv.getAddress(), testEnv.getTimeout(), testEnv.getPath());
BookkeeperCommitLogManager logManager = new BookkeeperCommitLogManager(man, serverConfiguration, NullStatsLogger.INSTANCE)) {
man.start();
logManager.start();
try (BookkeeperCommitLog writer = logManager.createCommitLog(tableSpaceUUID, name, nodeid)) {
writer.startWriting(1);
writer.log(LogEntryFactory.beginTransaction(1), true).getLogSequenceNumber();
this.testEnv.pauseBookie();
// this is deemed to fail and we will close the log
TestUtils.assertThrows(LogNotAvailableException.class, () -> writer.log(LogEntryFactory.beginTransaction(2), true).getLogSequenceNumber());
assertTrue(writer.isFailed());
// this one will fail as well
TestUtils.assertThrows(LogNotAvailableException.class, () -> writer.log(LogEntryFactory.beginTransaction(2), true).getLogSequenceNumber());
// no way to recover this instance of BookkeeperCommitLog
// we will bounce the leader and it will restart with a full recovery
// in a production env you do not have only one bookie, and the failure
// of a single bookie will be handled with an ensemble change
this.testEnv.resumeBookie();
TestUtils.assertThrows(LogNotAvailableException.class, () -> writer.log(LogEntryFactory.beginTransaction(2), true).getLogSequenceNumber());
}
// check expected reads
try (BookkeeperCommitLog reader = logManager.createCommitLog(tableSpaceUUID, name, nodeid)) {
List<Map.Entry<LogSequenceNumber, LogEntry>> list = new ArrayList<>();
reader.recovery(LogSequenceNumber.START_OF_TIME, (lsn, entry) -> {
if (entry.type != LogEntryType.NOOP) {
list.add(new AbstractMap.SimpleImmutableEntry<>(lsn, entry));
}
}, false);
assertEquals(1, list.size());
assertTrue(list.get(0).getKey().after(LogSequenceNumber.START_OF_TIME));
}
}
}
use of herddb.cluster.BookkeeperCommitLog in project herddb by diennea.
the class LedgerClosedTest method testLedgerClosedError.
@Test
public void testLedgerClosedError() throws Exception {
ServerConfiguration serverconfig_1 = newServerConfigurationWithAutoPort(folder.newFolder().toPath());
serverconfig_1.set(ServerConfiguration.PROPERTY_NODEID, "server1");
serverconfig_1.set(ServerConfiguration.PROPERTY_MODE, ServerConfiguration.PROPERTY_MODE_CLUSTER);
serverconfig_1.set(ServerConfiguration.PROPERTY_ZOOKEEPER_ADDRESS, testEnv.getAddress());
serverconfig_1.set(ServerConfiguration.PROPERTY_ZOOKEEPER_PATH, testEnv.getPath());
serverconfig_1.set(ServerConfiguration.PROPERTY_ZOOKEEPER_SESSIONTIMEOUT, testEnv.getTimeout());
serverconfig_1.set(ServerConfiguration.PROPERTY_ENFORCE_LEADERSHIP, false);
try (Server server = new Server(serverconfig_1)) {
server.start();
server.waitForStandaloneBoot();
Table table = Table.builder().name("t1").column("c", ColumnTypes.INTEGER).primaryKey("c").build();
server.getManager().executeStatement(new CreateTableStatement(table), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 1)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 2)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 3)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
TableSpaceManager tableSpaceManager = server.getManager().getTableSpaceManager(TableSpace.DEFAULT);
BookkeeperCommitLog log = (BookkeeperCommitLog) tableSpaceManager.getLog();
long ledgerId = log.getLastSequenceNumber().ledgerId;
assertTrue(ledgerId >= 0);
// we do not want auto-recovery in ase of log failures
server.getManager().setActivatorPauseStatus(true);
assertEquals(ledgerId, log.getWriter().getOut().getId());
// force close of the LedgerHandle
// this may happen internally in BK in case of internal errors
log.getWriter().getOut().close();
// we should recover
server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 4)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
assertNotEquals(ledgerId, log.getWriter().getOut().getId());
ServerConfiguration serverconfig_2 = newServerConfigurationWithAutoPort(folder.newFolder().toPath());
serverconfig_2.set(ServerConfiguration.PROPERTY_NODEID, "server2");
serverconfig_2.set(ServerConfiguration.PROPERTY_MODE, ServerConfiguration.PROPERTY_MODE_CLUSTER);
serverconfig_2.set(ServerConfiguration.PROPERTY_ZOOKEEPER_ADDRESS, testEnv.getAddress());
serverconfig_2.set(ServerConfiguration.PROPERTY_ZOOKEEPER_PATH, testEnv.getPath());
serverconfig_2.set(ServerConfiguration.PROPERTY_ZOOKEEPER_SESSIONTIMEOUT, testEnv.getTimeout());
serverconfig_2.set(ServerConfiguration.PROPERTY_ENFORCE_LEADERSHIP, false);
// set server2 as new leader
server.getManager().executeStatement(new AlterTableSpaceStatement(TableSpace.DEFAULT, new HashSet<>(Arrays.asList("server1", "server2")), "server2", 1, 0), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
// stop server1
server.close();
// boot a new leader, it will recover from bookkeeper
try (Server server2 = new Server(serverconfig_2)) {
server2.start();
// wait for the boot of the new leader
server2.waitForTableSpaceBoot(TableSpace.DEFAULT, true);
// the server must have all of the data
try (DataScanner scan = scan(server2.getManager(), "SELECT * FROM t1", Collections.emptyList())) {
List<DataAccessor> consume = scan.consume();
assertEquals(4, consume.size());
}
}
}
}
use of herddb.cluster.BookkeeperCommitLog in project herddb by diennea.
the class BootAsNewLeaderTest method testLeaderOnlineLogNoMoreAvailableDataAlreadyPresentBootAsNewLeader.
@Test
public void testLeaderOnlineLogNoMoreAvailableDataAlreadyPresentBootAsNewLeader() throws Exception {
final AtomicInteger countErase = new AtomicInteger();
SystemInstrumentation.addListener(new SystemInstrumentation.SingleInstrumentationPointListener("eraseTablespaceData") {
@Override
public void acceptSingle(Object... args) throws Exception {
countErase.incrementAndGet();
}
});
ServerConfiguration serverconfig_1 = newServerConfigurationWithAutoPort(folder.newFolder().toPath());
serverconfig_1.set(ServerConfiguration.PROPERTY_NODEID, "server1");
serverconfig_1.set(ServerConfiguration.PROPERTY_MODE, ServerConfiguration.PROPERTY_MODE_CLUSTER);
serverconfig_1.set(ServerConfiguration.PROPERTY_ZOOKEEPER_ADDRESS, testEnv.getAddress());
serverconfig_1.set(ServerConfiguration.PROPERTY_ZOOKEEPER_PATH, testEnv.getPath());
serverconfig_1.set(ServerConfiguration.PROPERTY_ZOOKEEPER_SESSIONTIMEOUT, testEnv.getTimeout());
serverconfig_1.set(ServerConfiguration.PROPERTY_ENFORCE_LEADERSHIP, false);
serverconfig_1.set(ServerConfiguration.PROPERTY_BOOKKEEPER_LEDGERS_RETENTION_PERIOD, 1);
serverconfig_1.set(ServerConfiguration.PROPERTY_CHECKPOINT_PERIOD, 0);
// disabled
serverconfig_1.set(ServerConfiguration.PROPERTY_BOOKKEEPER_MAX_IDLE_TIME, 0);
ServerConfiguration serverconfig_2 = serverconfig_1.copy().set(ServerConfiguration.PROPERTY_NODEID, "server2").set(ServerConfiguration.PROPERTY_BASEDIR, folder.newFolder().toPath().toAbsolutePath());
Table table = Table.builder().name("t1").column("c", ColumnTypes.INTEGER).column("s", ColumnTypes.INTEGER).primaryKey("c").build();
Index index = Index.builder().onTable(table).type(Index.TYPE_BRIN).column("s", ColumnTypes.STRING).build();
try (Server server_1 = new Server(serverconfig_1)) {
server_1.start();
server_1.waitForStandaloneBoot();
server_1.getManager().executeStatement(new CreateTableStatement(table), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server_1.getManager().executeStatement(new CreateIndexStatement(index), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server_1.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 1, "s", "1")), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server_1.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 2, "s", "2")), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server_1.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 3, "s", "3")), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server_1.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 4, "s", "4")), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server_1.getManager().executeStatement(new AlterTableSpaceStatement(TableSpace.DEFAULT, new HashSet<>(Arrays.asList("server1", "server2")), "server1", 1, 0), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
TranslatedQuery translated = server_1.getManager().getPlanner().translate(TableSpace.DEFAULT, "SELECT * FROM " + TableSpace.DEFAULT + ".t1 WHERE s=1", Collections.emptyList(), true, true, false, -1);
ScanStatement statement = translated.plan.mainStatement.unwrap(ScanStatement.class);
assertTrue(statement.getPredicate().getIndexOperation() instanceof SecondaryIndexSeek);
try (DataScanner scan = server_1.getManager().scan(statement, translated.context, TransactionContext.NO_TRANSACTION)) {
assertEquals(1, scan.consume().size());
}
}
String tableSpaceUUID;
try (Server server_1 = new Server(serverconfig_1)) {
server_1.start();
server_1.waitForStandaloneBoot();
{
ZookeeperMetadataStorageManager man = (ZookeeperMetadataStorageManager) server_1.getMetadataStorageManager();
tableSpaceUUID = man.describeTableSpace(TableSpace.DEFAULT).uuid;
LedgersInfo ledgersList = ZookeeperMetadataStorageManager.readActualLedgersListFromZookeeper(man.getZooKeeper(), testEnv.getPath() + "/ledgers", tableSpaceUUID);
assertEquals(2, ledgersList.getActiveLedgers().size());
}
server_1.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 5, "s", "5")), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
server_1.getManager().checkpoint();
}
try (Server server_1 = new Server(serverconfig_1)) {
server_1.start();
server_1.waitForStandaloneBoot();
{
ZookeeperMetadataStorageManager man = (ZookeeperMetadataStorageManager) server_1.getMetadataStorageManager();
LedgersInfo ledgersList = ZookeeperMetadataStorageManager.readActualLedgersListFromZookeeper(man.getZooKeeper(), testEnv.getPath() + "/ledgers", tableSpaceUUID);
assertEquals(2, ledgersList.getActiveLedgers().size());
}
server_1.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 6, "s", "6")), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
{
ZookeeperMetadataStorageManager man = (ZookeeperMetadataStorageManager) server_1.getMetadataStorageManager();
LedgersInfo ledgersList = ZookeeperMetadataStorageManager.readActualLedgersListFromZookeeper(man.getZooKeeper(), testEnv.getPath() + "/ledgers", tableSpaceUUID);
assertEquals(2, ledgersList.getActiveLedgers().size());
}
server_1.getManager().checkpoint();
}
assertEquals(0, countErase.get());
LogSequenceNumber server2checkpointPosition;
try (Server server_1 = new Server(serverconfig_1)) {
server_1.start();
server_1.waitForStandaloneBoot();
// start server_2, and flush data locally
try (Server server_2 = new Server(serverconfig_2)) {
server_2.start();
assertTrue(server_2.getManager().waitForTablespace(TableSpace.DEFAULT, 60000, false));
// wait for data to arrive on server_2
for (int i = 0; i < 100; i++) {
GetResult found = server_2.getManager().get(new GetStatement(TableSpace.DEFAULT, "t1", Bytes.from_int(1), null, false), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
if (found.found()) {
break;
}
Thread.sleep(100);
}
// force a checkpoint, data is flushed to disk
server_2.getManager().checkpoint();
server2checkpointPosition = server_2.getManager().getTableSpaceManager(TableSpace.DEFAULT).getLog().getLastSequenceNumber();
System.out.println("server2 checkpoint time: " + server2checkpointPosition);
}
}
// start again server_1, in order to create a new ledger
try (Server server_1 = new Server(serverconfig_1)) {
server_1.start();
server_1.waitForStandaloneBoot();
BookkeeperCommitLog ll = (BookkeeperCommitLog) server_1.getManager().getTableSpaceManager(TableSpace.DEFAULT).getLog();
// server_1 make much progress
ll.rollNewLedger();
ll.rollNewLedger();
ll.rollNewLedger();
ll.rollNewLedger();
ll.rollNewLedger();
ll.rollNewLedger();
ll.rollNewLedger();
ll.rollNewLedger();
// a checkpoint will delete old ledgers
server_1.getManager().checkpoint();
{
ZookeeperMetadataStorageManager man = (ZookeeperMetadataStorageManager) server_1.getMetadataStorageManager();
LedgersInfo ledgersList = ZookeeperMetadataStorageManager.readActualLedgersListFromZookeeper(man.getZooKeeper(), testEnv.getPath() + "/ledgers", tableSpaceUUID);
System.out.println("ledgerList: " + ledgersList);
assertEquals(1, ledgersList.getActiveLedgers().size());
assertTrue(!ledgersList.getActiveLedgers().contains(ledgersList.getFirstLedger()));
// we want to be sure that server_2 cannot recover from log
assertTrue(!ledgersList.getActiveLedgers().contains(server2checkpointPosition.ledgerId));
}
assertEquals(1, countErase.get());
// make server2 boot as leader, it will fence out server1
// but server1 is not writing so it won't know from BK
// it will see his new role from zookeeper (with a 'watch' notification)
server_1.getManager().executeStatement(new AlterTableSpaceStatement(TableSpace.DEFAULT, new HashSet<>(Arrays.asList("server1", "server2")), "server2", 1, 0), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
// trying to become leader
try (Server server_2 = new Server(serverconfig_2)) {
server_2.start();
assertFalse(server_2.getManager().waitForTablespace(TableSpace.DEFAULT, 10000, true));
}
// make server_1 leader again
server_1.getManager().executeStatement(new AlterTableSpaceStatement(TableSpace.DEFAULT, new HashSet<>(Arrays.asList("server1", "server2")), "server1", 1, 0), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
// now server_2 must be able to boot, downloading data from server_1 and easing local state
try (Server server_2 = new Server(serverconfig_2)) {
server_2.start();
assertFalse(server_2.getManager().waitForTablespace(TableSpace.DEFAULT, 60000, true));
}
// make server_2 leader again
server_1.getManager().executeStatement(new AlterTableSpaceStatement(TableSpace.DEFAULT, new HashSet<>(Arrays.asList("server1", "server2")), "server2", 1, 0), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
// stop server_1
server_1.close();
// it must have enough local data to boot
try (Server server_2 = new Server(serverconfig_2)) {
server_2.start();
assertTrue(server_2.getManager().waitForTablespace(TableSpace.DEFAULT, 60000, true));
}
}
}
use of herddb.cluster.BookkeeperCommitLog in project herddb by diennea.
the class BookKeeperCommitLogTest method testMaxLedgerSize.
@Test
public void testMaxLedgerSize() throws Exception {
final String tableSpaceUUID = UUID.randomUUID().toString();
final String name = TableSpace.DEFAULT;
final String nodeid = "nodeid";
final int maxLedgerSize = 1024;
final LogEntry entry = LogEntryFactory.beginTransaction(1);
final int estimateSize = entry.serialize().length;
final int numberOfLedgers = 10;
final int numberOfEntries = 1 + numberOfLedgers * maxLedgerSize / estimateSize;
ServerConfiguration serverConfiguration = newServerConfigurationWithAutoPort();
try (ZookeeperMetadataStorageManager man = new ZookeeperMetadataStorageManager(testEnv.getAddress(), testEnv.getTimeout(), testEnv.getPath());
BookkeeperCommitLogManager logManager = new BookkeeperCommitLogManager(man, serverConfiguration, NullStatsLogger.INSTANCE)) {
logManager.setMaxLedgerSizeBytes(maxLedgerSize);
man.start();
logManager.start();
try (BookkeeperCommitLog writer = logManager.createCommitLog(tableSpaceUUID, name, nodeid)) {
// do not pollute the count with NOOP entries
writer.setWriteLedgerHeader(false);
writer.startWriting(1);
for (int i = 0; i < numberOfEntries; i++) {
writer.log(entry, false);
}
writer.log(entry, true).getLogSequenceNumber();
}
try (BookkeeperCommitLog reader = logManager.createCommitLog(tableSpaceUUID, name, nodeid)) {
List<Map.Entry<LogSequenceNumber, LogEntry>> list = new ArrayList<>();
Set<Long> ledgerIds = new HashSet<>();
reader.recovery(LogSequenceNumber.START_OF_TIME, (a, b) -> {
if (b.type != LogEntryType.NOOP) {
list.add(new AbstractMap.SimpleImmutableEntry<>(a, b));
ledgerIds.add(a.ledgerId);
}
}, false);
assertEquals(numberOfEntries + 1, list.size());
assertEquals(numberOfLedgers, ledgerIds.size());
}
}
}
Aggregations