Search in sources :

Example 1 with BookKeeper

use of org.apache.bookkeeper.client.BookKeeper in project pulsar by yahoo.

the class ManagedLedgerOfflineBacklog method readLedgerMeta.

private void readLedgerMeta(final ManagedLedgerFactoryImpl factory, final DestinationName dn, final NavigableMap<Long, MLDataFormats.ManagedLedgerInfo.LedgerInfo> ledgers) throws Exception {
    String managedLedgerName = dn.getPersistenceNamingEncoding();
    MetaStore store = factory.getMetaStore();
    BookKeeper bk = factory.getBookKeeper();
    final CountDownLatch mlMetaCounter = new CountDownLatch(1);
    store.getManagedLedgerInfo(managedLedgerName, new MetaStore.MetaStoreCallback<MLDataFormats.ManagedLedgerInfo>() {

        @Override
        public void operationComplete(MLDataFormats.ManagedLedgerInfo mlInfo, MetaStore.Stat version) {
            for (MLDataFormats.ManagedLedgerInfo.LedgerInfo ls : mlInfo.getLedgerInfoList()) {
                ledgers.put(ls.getLedgerId(), ls);
            }
            // find no of entries in last ledger
            if (ledgers.size() > 0) {
                final long id = ledgers.lastKey();
                AsyncCallback.OpenCallback opencb = (rc, lh, ctx1) -> {
                    if (log.isDebugEnabled()) {
                        log.debug("[{}] Opened ledger {}: ", managedLedgerName, id, BKException.getMessage(rc));
                    }
                    if (rc == BKException.Code.OK) {
                        MLDataFormats.ManagedLedgerInfo.LedgerInfo info = MLDataFormats.ManagedLedgerInfo.LedgerInfo.newBuilder().setLedgerId(id).setEntries(lh.getLastAddConfirmed() + 1).setSize(lh.getLength()).setTimestamp(System.currentTimeMillis()).build();
                        ledgers.put(id, info);
                        mlMetaCounter.countDown();
                    } else if (rc == BKException.Code.NoSuchLedgerExistsException) {
                        log.warn("[{}] Ledger not found: {}", managedLedgerName, ledgers.lastKey());
                        ledgers.remove(ledgers.lastKey());
                        mlMetaCounter.countDown();
                    } else {
                        log.error("[{}] Failed to open ledger {}: {}", managedLedgerName, id, BKException.getMessage(rc));
                        mlMetaCounter.countDown();
                    }
                };
                if (log.isDebugEnabled()) {
                    log.debug("[{}] Opening ledger {}", managedLedgerName, id);
                }
                try {
                    bk.asyncOpenLedgerNoRecovery(id, digestType, password, opencb, null);
                } catch (Exception e) {
                    log.warn("[{}] Failed to open ledger {}: {}", managedLedgerName, id, e);
                    mlMetaCounter.countDown();
                }
            } else {
                log.warn("[{}] Ledger list empty", managedLedgerName);
                mlMetaCounter.countDown();
            }
        }

        @Override
        public void operationFailed(ManagedLedgerException.MetaStoreException e) {
            log.warn("[{}] Unable to obtain managed ledger metadata - {}", e);
            mlMetaCounter.countDown();
        }
    });
    if (accurate) {
        // block until however long it takes for operation to complete
        mlMetaCounter.await();
    } else {
        mlMetaCounter.await(META_READ_TIMEOUT_SECONDS, TimeUnit.SECONDS);
    }
}
Also used : BookKeeper(org.apache.bookkeeper.client.BookKeeper) CountDownLatch(java.util.concurrent.CountDownLatch) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) BKException(org.apache.bookkeeper.client.BKException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) MLDataFormats(org.apache.bookkeeper.mledger.proto.MLDataFormats)

Example 2 with BookKeeper

use of org.apache.bookkeeper.client.BookKeeper in project pulsar by yahoo.

the class ManagedLedgerOfflineBacklog method calculateCursorBacklogs.

private void calculateCursorBacklogs(final ManagedLedgerFactoryImpl factory, final DestinationName dn, final NavigableMap<Long, MLDataFormats.ManagedLedgerInfo.LedgerInfo> ledgers, final PersistentOfflineTopicStats offlineTopicStats) throws Exception {
    if (ledgers.size() == 0) {
        return;
    }
    String managedLedgerName = dn.getPersistenceNamingEncoding();
    MetaStore store = factory.getMetaStore();
    BookKeeper bk = factory.getBookKeeper();
    final CountDownLatch allCursorsCounter = new CountDownLatch(1);
    final long errorInReadingCursor = (long) -1;
    ConcurrentOpenHashMap<String, Long> ledgerRetryMap = new ConcurrentOpenHashMap<>();
    final MLDataFormats.ManagedLedgerInfo.LedgerInfo ledgerInfo = ledgers.lastEntry().getValue();
    final PositionImpl lastLedgerPosition = new PositionImpl(ledgerInfo.getLedgerId(), ledgerInfo.getEntries() - 1);
    if (log.isDebugEnabled()) {
        log.debug("[{}] Last ledger position {}", managedLedgerName, lastLedgerPosition);
    }
    store.getCursors(managedLedgerName, new MetaStore.MetaStoreCallback<List<String>>() {

        @Override
        public void operationComplete(List<String> cursors, MetaStore.Stat v) {
            // Load existing cursors
            if (log.isDebugEnabled()) {
                log.debug("[{}] Found {} cursors", managedLedgerName, cursors.size());
            }
            if (cursors.isEmpty()) {
                allCursorsCounter.countDown();
                return;
            }
            final CountDownLatch cursorCounter = new CountDownLatch(cursors.size());
            for (final String cursorName : cursors) {
                // determine subscription position from cursor ledger
                if (log.isDebugEnabled()) {
                    log.debug("[{}] Loading cursor {}", managedLedgerName, cursorName);
                }
                AsyncCallback.OpenCallback cursorLedgerOpenCb = (rc, lh, ctx1) -> {
                    long ledgerId = lh.getId();
                    if (log.isDebugEnabled()) {
                        log.debug("[{}] Opened cursor ledger {} for cursor {}. rc={}", managedLedgerName, ledgerId, cursorName, rc);
                    }
                    if (rc != BKException.Code.OK) {
                        log.warn("[{}] Error opening metadata ledger {} for cursor {}: {}", managedLedgerName, ledgerId, cursorName, BKException.getMessage(rc));
                        cursorCounter.countDown();
                        return;
                    }
                    long lac = lh.getLastAddConfirmed();
                    if (log.isDebugEnabled()) {
                        log.debug("[{}] Cursor {} LAC {} read from ledger {}", managedLedgerName, cursorName, lac, ledgerId);
                    }
                    if (lac == LedgerHandle.INVALID_ENTRY_ID) {
                        // save the ledger id and cursor to retry outside of this call back
                        // since we are trying to read the same cursor ledger, we will block until
                        // this current callback completes, since an attempt to read the entry
                        // will block behind this current operation to complete
                        ledgerRetryMap.put(cursorName, ledgerId);
                        log.info("[{}] Cursor {} LAC {} read from ledger {}", managedLedgerName, cursorName, lac, ledgerId);
                        cursorCounter.countDown();
                        return;
                    }
                    final long entryId = lac;
                    // read last acked message position for subscription
                    lh.asyncReadEntries(entryId, entryId, new AsyncCallback.ReadCallback() {

                        @Override
                        public void readComplete(int rc, LedgerHandle lh, Enumeration<LedgerEntry> seq, Object ctx) {
                            try {
                                if (log.isDebugEnabled()) {
                                    log.debug("readComplete rc={} entryId={}", rc, entryId);
                                }
                                if (rc != BKException.Code.OK) {
                                    log.warn("[{}] Error reading from metadata ledger {} for cursor {}: {}", managedLedgerName, ledgerId, cursorName, BKException.getMessage(rc));
                                    // indicate that this cursor should be excluded
                                    offlineTopicStats.addCursorDetails(cursorName, errorInReadingCursor, lh.getId());
                                } else {
                                    LedgerEntry entry = seq.nextElement();
                                    MLDataFormats.PositionInfo positionInfo;
                                    try {
                                        positionInfo = MLDataFormats.PositionInfo.parseFrom(entry.getEntry());
                                    } catch (InvalidProtocolBufferException e) {
                                        log.warn("[{}] Error reading position from metadata ledger {} for cursor {}: {}", managedLedgerName, ledgerId, cursorName, e);
                                        offlineTopicStats.addCursorDetails(cursorName, errorInReadingCursor, lh.getId());
                                        return;
                                    }
                                    final PositionImpl lastAckedMessagePosition = new PositionImpl(positionInfo);
                                    if (log.isDebugEnabled()) {
                                        log.debug("[{}] Cursor {} MD {} read last ledger position {}", managedLedgerName, cursorName, lastAckedMessagePosition, lastLedgerPosition);
                                    }
                                    // calculate cursor backlog
                                    Range<PositionImpl> range = Range.openClosed(lastAckedMessagePosition, lastLedgerPosition);
                                    if (log.isDebugEnabled()) {
                                        log.debug("[{}] Calculating backlog for cursor {} using range {}", managedLedgerName, cursorName, range);
                                    }
                                    long cursorBacklog = getNumberOfEntries(range, ledgers);
                                    offlineTopicStats.messageBacklog += cursorBacklog;
                                    offlineTopicStats.addCursorDetails(cursorName, cursorBacklog, lh.getId());
                                }
                            } finally {
                                cursorCounter.countDown();
                            }
                        }
                    }, null);
                };
                // end of cursor meta read callback
                store.asyncGetCursorInfo(managedLedgerName, cursorName, new MetaStore.MetaStoreCallback<MLDataFormats.ManagedCursorInfo>() {

                    @Override
                    public void operationComplete(MLDataFormats.ManagedCursorInfo info, MetaStore.Stat version) {
                        long cursorLedgerId = info.getCursorsLedgerId();
                        if (log.isDebugEnabled()) {
                            log.debug("[{}] Cursor {} meta-data read ledger id {}", managedLedgerName, cursorName, cursorLedgerId);
                        }
                        if (cursorLedgerId != -1) {
                            bk.asyncOpenLedgerNoRecovery(cursorLedgerId, digestType, password, cursorLedgerOpenCb, null);
                        } else {
                            PositionImpl lastAckedMessagePosition = new PositionImpl(info.getMarkDeleteLedgerId(), info.getMarkDeleteEntryId());
                            Range<PositionImpl> range = Range.openClosed(lastAckedMessagePosition, lastLedgerPosition);
                            if (log.isDebugEnabled()) {
                                log.debug("[{}] Calculating backlog for cursor {} using range {}", managedLedgerName, cursorName, range);
                            }
                            long cursorBacklog = getNumberOfEntries(range, ledgers);
                            offlineTopicStats.messageBacklog += cursorBacklog;
                            offlineTopicStats.addCursorDetails(cursorName, cursorBacklog, cursorLedgerId);
                            cursorCounter.countDown();
                        }
                    }

                    @Override
                    public void operationFailed(ManagedLedgerException.MetaStoreException e) {
                        log.warn("[{}] Unable to obtain cursor ledger for cursor {}: {}", managedLedgerName, cursorName, e);
                        cursorCounter.countDown();
                    }
                });
            }
            // for every cursor find backlog
            try {
                if (accurate) {
                    cursorCounter.await();
                } else {
                    cursorCounter.await(META_READ_TIMEOUT_SECONDS, TimeUnit.SECONDS);
                }
            } catch (Exception e) {
                log.warn("[{}] Error reading subscription positions{}", managedLedgerName, e);
            } finally {
                allCursorsCounter.countDown();
            }
        }

        @Override
        public void operationFailed(ManagedLedgerException.MetaStoreException e) {
            log.warn("[{}] Failed to get the cursors list", managedLedgerName, e);
            allCursorsCounter.countDown();
        }
    });
    if (accurate) {
        allCursorsCounter.await();
    } else {
        allCursorsCounter.await(META_READ_TIMEOUT_SECONDS, TimeUnit.SECONDS);
    }
    // go through ledgers where LAC was -1
    if (accurate && ledgerRetryMap.size() > 0) {
        ledgerRetryMap.forEach((cursorName, ledgerId) -> {
            if (log.isDebugEnabled()) {
                log.debug("Cursor {} Ledger {} Trying to obtain MD from BkAdmin", cursorName, ledgerId);
            }
            PositionImpl lastAckedMessagePosition = tryGetMDPosition(bk, ledgerId, cursorName);
            if (lastAckedMessagePosition == null) {
                log.warn("[{}] Cursor {} read from ledger {}. Unable to determine cursor position", managedLedgerName, cursorName, ledgerId);
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("[{}] Cursor {} read from ledger using bk admin {}. position {}", managedLedgerName, cursorName, ledgerId, lastAckedMessagePosition);
                }
                // calculate cursor backlog
                Range<PositionImpl> range = Range.openClosed(lastAckedMessagePosition, lastLedgerPosition);
                if (log.isDebugEnabled()) {
                    log.debug("[{}] Calculating backlog for cursor {} using range {}", managedLedgerName, cursorName, range);
                }
                long cursorBacklog = getNumberOfEntries(range, ledgers);
                offlineTopicStats.messageBacklog += cursorBacklog;
                offlineTopicStats.addCursorDetails(cursorName, cursorBacklog, ledgerId);
            }
        });
    }
}
Also used : ConcurrentOpenHashMap(com.yahoo.pulsar.common.util.collections.ConcurrentOpenHashMap) AsyncCallback(org.apache.bookkeeper.client.AsyncCallback) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) MLDataFormats(org.apache.bookkeeper.mledger.proto.MLDataFormats) List(java.util.List) LedgerHandle(org.apache.bookkeeper.client.LedgerHandle) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) BookKeeper(org.apache.bookkeeper.client.BookKeeper) CountDownLatch(java.util.concurrent.CountDownLatch) Range(com.google.common.collect.Range) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) BKException(org.apache.bookkeeper.client.BKException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) LedgerEntry(org.apache.bookkeeper.client.LedgerEntry)

Example 3 with BookKeeper

use of org.apache.bookkeeper.client.BookKeeper in project pulsar by yahoo.

the class ManagedLedgerFactoryImpl method asyncOpen.

@Override
public void asyncOpen(final String name, final ManagedLedgerConfig config, final OpenLedgerCallback callback, final Object ctx) {
    // If the ledger state is bad, remove it from the map.
    CompletableFuture<ManagedLedgerImpl> existingFuture = ledgers.get(name);
    if (existingFuture != null && existingFuture.isDone()) {
        try {
            ManagedLedgerImpl l = existingFuture.get();
            if (l.getState().equals(State.Fenced.toString()) || l.getState().equals(State.Closed.toString())) {
                // Managed ledger is in unusable state. Recreate it.
                log.warn("[{}] Attempted to open ledger in {} state. Removing from the map to recreate it", name, l.getState());
                ledgers.remove(name, existingFuture);
            }
        } catch (Exception e) {
            // Unable to get the future
            log.warn("[{}] Got exception while trying to retrieve ledger", name, e);
        }
    }
    // Ensure only one managed ledger is created and initialized
    ledgers.computeIfAbsent(name, (mlName) -> {
        // Create the managed ledger
        CompletableFuture<ManagedLedgerImpl> future = new CompletableFuture<>();
        final ManagedLedgerImpl newledger = new ManagedLedgerImpl(this, bookKeeper, store, config, executor, orderedExecutor, name);
        newledger.initialize(new ManagedLedgerInitializeLedgerCallback() {

            @Override
            public void initializeComplete() {
                future.complete(newledger);
            }

            @Override
            public void initializeFailed(ManagedLedgerException e) {
                // Clean the map if initialization fails
                ledgers.remove(name, future);
                future.completeExceptionally(e);
            }
        }, null);
        return future;
    }).thenAccept(ml -> {
        callback.openLedgerComplete(ml, ctx);
    }).exceptionally(exception -> {
        callback.openLedgerFailed((ManagedLedgerException) exception.getCause(), ctx);
        return null;
    });
}
Also used : ScheduledFuture(java.util.concurrent.ScheduledFuture) DefaultThreadFactory(io.netty.util.concurrent.DefaultThreadFactory) ManagedLedgerFactory(org.apache.bookkeeper.mledger.ManagedLedgerFactory) ManagedLedgerFactoryMXBean(org.apache.bookkeeper.mledger.ManagedLedgerFactoryMXBean) State(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.State) LoggerFactory(org.slf4j.LoggerFactory) CompletableFuture(java.util.concurrent.CompletableFuture) States(org.apache.zookeeper.ZooKeeper.States) ManagedLedger(org.apache.bookkeeper.mledger.ManagedLedger) ManagedLedgerConfig(org.apache.bookkeeper.mledger.ManagedLedgerConfig) Map(java.util.Map) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ManagedLedgerFactoryConfig(org.apache.bookkeeper.mledger.ManagedLedgerFactoryConfig) Predicates(com.google.common.base.Predicates) ZooKeeper(org.apache.zookeeper.ZooKeeper) ManagedLedgerInitializeLedgerCallback(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.ManagedLedgerInitializeLedgerCallback) Logger(org.slf4j.Logger) OrderedSafeExecutor(org.apache.bookkeeper.util.OrderedSafeExecutor) Watcher(org.apache.zookeeper.Watcher) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) BookKeeper(org.apache.bookkeeper.client.BookKeeper) Maps(com.google.common.collect.Maps) Executors(java.util.concurrent.Executors) BKException(org.apache.bookkeeper.client.BKException) TimeUnit(java.util.concurrent.TimeUnit) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) CountDownLatch(java.util.concurrent.CountDownLatch) OpenLedgerCallback(org.apache.bookkeeper.mledger.AsyncCallbacks.OpenLedgerCallback) ClientConfiguration(org.apache.bookkeeper.conf.ClientConfiguration) AsyncCallbacks(org.apache.bookkeeper.mledger.AsyncCallbacks) CompletableFuture(java.util.concurrent.CompletableFuture) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) ManagedLedgerInitializeLedgerCallback(org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl.ManagedLedgerInitializeLedgerCallback) BKException(org.apache.bookkeeper.client.BKException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException)

Example 4 with BookKeeper

use of org.apache.bookkeeper.client.BookKeeper in project pulsar by yahoo.

the class BookKeeperClientFactoryImpl method create.

@Override
public BookKeeper create(ServiceConfiguration conf, ZooKeeper zkClient) throws IOException {
    ClientConfiguration bkConf = new ClientConfiguration();
    if (conf.getBookkeeperClientAuthenticationPlugin() != null && conf.getBookkeeperClientAuthenticationPlugin().trim().length() > 0) {
        bkConf.setClientAuthProviderFactoryClass(conf.getBookkeeperClientAuthenticationPlugin());
        bkConf.setProperty(conf.getBookkeeperClientAuthenticationParametersName(), conf.getBookkeeperClientAuthenticationParameters());
    }
    bkConf.setThrottleValue(0);
    bkConf.setAddEntryTimeout((int) conf.getBookkeeperClientTimeoutInSeconds());
    bkConf.setReadEntryTimeout((int) conf.getBookkeeperClientTimeoutInSeconds());
    bkConf.setSpeculativeReadTimeout(conf.getBookkeeperClientSpeculativeReadTimeoutInMillis());
    bkConf.setNumChannelsPerBookie(16);
    bkConf.setUseV2WireProtocol(true);
    bkConf.setLedgerManagerFactoryClassName(HierarchicalLedgerManagerFactory.class.getName());
    if (conf.isBookkeeperClientHealthCheckEnabled()) {
        bkConf.enableBookieHealthCheck();
        bkConf.setBookieHealthCheckInterval(conf.getBookkeeperHealthCheckIntervalSec(), TimeUnit.SECONDS);
        bkConf.setBookieErrorThresholdPerInterval(conf.getBookkeeperClientHealthCheckErrorThresholdPerInterval());
        bkConf.setBookieQuarantineTime((int) conf.getBookkeeperClientHealthCheckQuarantineTimeInSeconds(), TimeUnit.SECONDS);
    }
    if (conf.isBookkeeperClientRackawarePolicyEnabled()) {
        bkConf.setEnsemblePlacementPolicy(RackawareEnsemblePlacementPolicy.class);
        bkConf.setProperty(RackawareEnsemblePlacementPolicy.REPP_DNS_RESOLVER_CLASS, ZkBookieRackAffinityMapping.class.getName());
        bkConf.setProperty(ZooKeeperCache.ZK_CACHE_INSTANCE, new ZooKeeperCache(zkClient) {
        });
    }
    if (conf.getBookkeeperClientIsolationGroups() != null && !conf.getBookkeeperClientIsolationGroups().isEmpty()) {
        bkConf.setEnsemblePlacementPolicy(ZkIsolatedBookieEnsemblePlacementPolicy.class);
        bkConf.setProperty(ZkIsolatedBookieEnsemblePlacementPolicy.ISOLATION_BOOKIE_GROUPS, conf.getBookkeeperClientIsolationGroups());
        if (bkConf.getProperty(ZooKeeperCache.ZK_CACHE_INSTANCE) == null) {
            bkConf.setProperty(ZooKeeperCache.ZK_CACHE_INSTANCE, new ZooKeeperCache(zkClient) {
            });
        }
    }
    try {
        return new BookKeeper(bkConf, zkClient);
    } catch (InterruptedException | KeeperException e) {
        throw new IOException(e);
    }
}
Also used : BookKeeper(org.apache.bookkeeper.client.BookKeeper) HierarchicalLedgerManagerFactory(org.apache.bookkeeper.meta.HierarchicalLedgerManagerFactory) IOException(java.io.IOException) ZkBookieRackAffinityMapping(com.yahoo.pulsar.zookeeper.ZkBookieRackAffinityMapping) ClientConfiguration(org.apache.bookkeeper.conf.ClientConfiguration) ZooKeeperCache(com.yahoo.pulsar.zookeeper.ZooKeeperCache) KeeperException(org.apache.zookeeper.KeeperException)

Example 5 with BookKeeper

use of org.apache.bookkeeper.client.BookKeeper in project herddb by diennea.

the class BookkeeperFailuresTest method testBookieNotAvailableDuringTransaction.

@Test
public void testBookieNotAvailableDuringTransaction() throws Exception {
    ServerConfiguration serverconfig_1 = new ServerConfiguration(folder.newFolder().toPath());
    serverconfig_1.set(ServerConfiguration.PROPERTY_NODEID, "server1");
    serverconfig_1.set(ServerConfiguration.PROPERTY_PORT, 7867);
    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();
        // create table is done out of the transaction (this is very like autocommit=true)
        server.getManager().executeStatement(new CreateTableStatement(table), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        StatementExecutionResult executeStatement = server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 1)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.AUTOTRANSACTION_TRANSACTION);
        long transactionId = executeStatement.transactionId;
        server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 2)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), new TransactionContext(transactionId));
        server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 3)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), new TransactionContext(transactionId));
        TableSpaceManager tableSpaceManager = server.getManager().getTableSpaceManager(TableSpace.DEFAULT);
        BookkeeperCommitLog log = (BookkeeperCommitLog) tableSpaceManager.getLog();
        long ledgerId = log.getLastSequenceNumber().ledgerId;
        assertTrue(ledgerId >= 1);
        Transaction transaction = tableSpaceManager.getTransactions().stream().filter(t -> t.transactionId == transactionId).findFirst().get();
        // Transaction will synch, so every addEntry will be acked, but will not be "confirmed" yet
        transaction.synch();
        try (DataScanner scan = scan(server.getManager(), "select * from t1", Collections.emptyList(), new TransactionContext(transactionId))) {
            assertEquals(3, scan.consume().size());
        }
        try (DataScanner scan = scan(server.getManager(), "select * from t1", Collections.emptyList(), TransactionContext.NO_TRANSACTION)) {
            // no record, but the table exists!
            assertEquals(0, scan.consume().size());
        }
        // we do not want auto-recovery
        server.getManager().setActivatorPauseStatus(true);
        testEnv.stopBookie();
        // transaction will continue and see the failure only the time of the commit
        try {
            server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 4)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), new TransactionContext(transactionId));
            // this will piggyback the LAC for the transaction
            System.out.println("Insert of c,4 OK");
        } catch (StatementExecutionException expected) {
            System.out.println("Insert of c,4 failed " + expected);
            // in can happen that the log gets closed
            assertEquals(herddb.log.LogNotAvailableException.class, expected.getCause().getClass());
        }
        try {
            server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 5)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), new TransactionContext(transactionId));
            // this will piggyback the LAC for the transaction
            System.out.println("Insert of c,5 OK");
        } catch (StatementExecutionException expected) {
            System.out.println("Insert of c,5 failed " + expected);
            // in can happen that the log gets closed
            assertEquals(herddb.log.LogNotAvailableException.class, expected.getCause().getClass());
        }
        try {
            server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 6)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), new TransactionContext(transactionId));
            // this will piggyback the LAC for the transaction
            System.out.println("Insert of c,6 OK");
        } catch (StatementExecutionException expected) {
            System.out.println("Insert of c,6 failed " + expected);
            // in can happen that the log gets closed
            assertEquals(herddb.log.LogNotAvailableException.class, expected.getCause().getClass());
        }
        try {
            server.getManager().executeStatement(new CommitTransactionStatement(TableSpace.DEFAULT, transactionId), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
            // this will fail alweays
            fail();
        } catch (StatementExecutionException expected) {
            System.out.println("Commit failed as expected:" + expected);
        }
        testEnv.startBookie(false);
        while (true) {
            System.out.println("status leader:" + tableSpaceManager.isLeader() + " failed:" + tableSpaceManager.isFailed());
            if (tableSpaceManager.isFailed()) {
                break;
            }
            Thread.sleep(100);
        }
        try (BookKeeper bk = createBookKeeper();
            LedgerHandle handle = bk.openLedgerNoRecovery(ledgerId, BookKeeper.DigestType.CRC32, "herddb".getBytes(StandardCharsets.UTF_8))) {
            BookKeeperAdmin admin = new BookKeeperAdmin(bk);
            try {
                LedgerMetadata ledgerMetadata = admin.getLedgerMetadata(handle);
                System.out.println("current ledger metadata before recovery: " + ledgerMetadata);
            } finally {
                admin.close();
            }
        }
        server.getManager().setActivatorPauseStatus(false);
        server.getManager().triggerActivator(ActivatorRunRequest.TABLESPACEMANAGEMENT);
        while (true) {
            TableSpaceManager tableSpaceManager_after_failure = server.getManager().getTableSpaceManager(TableSpace.DEFAULT);
            System.out.println("tableSpaceManager_after_failure:" + tableSpaceManager_after_failure);
            System.out.println("tableSpaceManager:" + tableSpaceManager);
            if (tableSpaceManager_after_failure != null && tableSpaceManager_after_failure != tableSpaceManager) {
                break;
            }
            Thread.sleep(1000);
            server.getManager().triggerActivator(ActivatorRunRequest.TABLESPACEMANAGEMENT);
        }
        TableSpaceManager tableSpaceManager_after_failure = server.getManager().getTableSpaceManager(TableSpace.DEFAULT);
        Assert.assertNotNull(tableSpaceManager_after_failure);
        assertNotSame(tableSpaceManager_after_failure, tableSpaceManager);
        assertTrue(!tableSpaceManager_after_failure.isFailed());
        // the insert should succeed because the trasaction has been rolledback automatically
        server.getManager().executeUpdate(new InsertStatement(TableSpace.DEFAULT, "t1", RecordSerializer.makeRecord(table, "c", 4)), StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), TransactionContext.NO_TRANSACTION);
        try (DataScanner scan = scan(server.getManager(), "select * from t1", Collections.emptyList())) {
            assertEquals(1, scan.consume().size());
        }
    }
}
Also used : Table(herddb.model.Table) CommitTransactionStatement(herddb.model.commands.CommitTransactionStatement) LedgerHandle(org.apache.bookkeeper.client.LedgerHandle) CreateTableStatement(herddb.model.commands.CreateTableStatement) BookKeeper(org.apache.bookkeeper.client.BookKeeper) InsertStatement(herddb.model.commands.InsertStatement) StatementExecutionException(herddb.model.StatementExecutionException) DataScanner(herddb.model.DataScanner) Transaction(herddb.model.Transaction) LedgerMetadata(org.apache.bookkeeper.client.LedgerMetadata) TransactionContext(herddb.model.TransactionContext) StatementExecutionResult(herddb.model.StatementExecutionResult) TableSpaceManager(herddb.core.TableSpaceManager) BookkeeperCommitLog(herddb.cluster.BookkeeperCommitLog) BookKeeperAdmin(org.apache.bookkeeper.client.BookKeeperAdmin) Test(org.junit.Test)

Aggregations

BookKeeper (org.apache.bookkeeper.client.BookKeeper)71 LedgerHandle (org.apache.bookkeeper.client.LedgerHandle)45 ClientConfiguration (org.apache.bookkeeper.conf.ClientConfiguration)24 Test (org.junit.Test)20 BKException (org.apache.bookkeeper.client.BKException)18 IOException (java.io.IOException)17 ServerConfiguration (org.apache.bookkeeper.conf.ServerConfiguration)12 List (java.util.List)11 CompletableFuture (java.util.concurrent.CompletableFuture)10 CountDownLatch (java.util.concurrent.CountDownLatch)10 LedgerEntry (org.apache.bookkeeper.client.LedgerEntry)10 ArrayList (java.util.ArrayList)9 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)8 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)7 AsyncCallback (org.apache.bookkeeper.client.AsyncCallback)7 HttpServiceResponse (org.apache.bookkeeper.http.service.HttpServiceResponse)7 File (java.io.File)6 Map (java.util.Map)6 Random (java.util.Random)6 TimeUnit (java.util.concurrent.TimeUnit)6