Search in sources :

Example 6 with ConcurrentOpenHashMap

use of org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap in project incubator-pulsar by apache.

the class ConcurrentOpenHashMapTest method testComputeIfAbsent.

@Test
public void testComputeIfAbsent() {
    ConcurrentOpenHashMap<Integer, Integer> map = new ConcurrentOpenHashMap<>(16, 1);
    AtomicInteger counter = new AtomicInteger();
    Function<Integer, Integer> provider = key -> counter.getAndIncrement();
    assertEquals(map.computeIfAbsent(0, provider).intValue(), 0);
    assertEquals(map.get(0).intValue(), 0);
    assertEquals(map.computeIfAbsent(1, provider).intValue(), 1);
    assertEquals(map.get(1).intValue(), 1);
    assertEquals(map.computeIfAbsent(1, provider).intValue(), 1);
    assertEquals(map.get(1).intValue(), 1);
    assertEquals(map.computeIfAbsent(2, provider).intValue(), 2);
    assertEquals(map.get(2).intValue(), 2);
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Assert.assertNull(org.testng.Assert.assertNull) Assert.fail(org.testng.Assert.fail) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Assert.assertEquals(org.testng.Assert.assertEquals) HashMap(java.util.HashMap) Random(java.util.Random) Test(org.testng.annotations.Test) Function(java.util.function.Function) Executors(java.util.concurrent.Executors) ArrayList(java.util.ArrayList) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) Future(java.util.concurrent.Future) Lists(com.google.common.collect.Lists) ConcurrentOpenHashMap(org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Assert.assertTrue(org.testng.Assert.assertTrue) Assert.assertFalse(org.testng.Assert.assertFalse) Collections(java.util.Collections) ExecutorService(java.util.concurrent.ExecutorService) ConcurrentOpenHashMap(org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Test(org.testng.annotations.Test)

Example 7 with ConcurrentOpenHashMap

use of org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap in project incubator-pulsar by apache.

the class ConcurrentOpenHashMapTest method concurrentInsertions.

@Test
public void concurrentInsertions() throws Throwable {
    ConcurrentOpenHashMap<Long, String> map = new ConcurrentOpenHashMap<>(16, 1);
    ExecutorService executor = Executors.newCachedThreadPool();
    final int nThreads = 16;
    final int N = 100_000;
    String value = "value";
    List<Future<?>> futures = new ArrayList<>();
    for (int i = 0; i < nThreads; i++) {
        final int threadIdx = i;
        futures.add(executor.submit(() -> {
            Random random = new Random();
            for (int j = 0; j < N; j++) {
                long key = random.nextLong();
                // Ensure keys are uniques
                key -= key % (threadIdx + 1);
                map.put(key, value);
            }
        }));
    }
    for (Future<?> future : futures) {
        future.get();
    }
    assertEquals(map.size(), N * nThreads);
    executor.shutdown();
}
Also used : ConcurrentOpenHashMap(org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap) Random(java.util.Random) ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) Future(java.util.concurrent.Future) Test(org.testng.annotations.Test)

Example 8 with ConcurrentOpenHashMap

use of org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap in project incubator-pulsar by apache.

the class ManagedLedgerOfflineBacklog method calculateCursorBacklogs.

private void calculateCursorBacklogs(final ManagedLedgerFactoryImpl factory, final TopicName topicName, final NavigableMap<Long, MLDataFormats.ManagedLedgerInfo.LedgerInfo> ledgers, final PersistentOfflineTopicStats offlineTopicStats) throws Exception {
    if (ledgers.size() == 0) {
        return;
    }
    String managedLedgerName = topicName.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(org.apache.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 9 with ConcurrentOpenHashMap

use of org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap in project incubator-pulsar by apache.

the class BrokerService method removeTopicFromCache.

public void removeTopicFromCache(String topic) {
    try {
        TopicName topicName = TopicName.get(topic);
        NamespaceBundle namespaceBundle = pulsar.getNamespaceService().getBundle(topicName);
        checkArgument(namespaceBundle instanceof NamespaceBundle);
        String bundleName = namespaceBundle.toString();
        String namespaceName = topicName.getNamespaceObject().toString();
        synchronized (multiLayerTopicsMap) {
            ConcurrentOpenHashMap<String, ConcurrentOpenHashMap<String, Topic>> namespaceMap = multiLayerTopicsMap.get(namespaceName);
            ConcurrentOpenHashMap<String, Topic> bundleMap = namespaceMap.get(bundleName);
            bundleMap.remove(topic);
            if (bundleMap.isEmpty()) {
                namespaceMap.remove(bundleName);
            }
            if (namespaceMap.isEmpty()) {
                multiLayerTopicsMap.remove(namespaceName);
                final ClusterReplicationMetrics clusterReplicationMetrics = pulsarStats.getClusterReplicationMetrics();
                replicationClients.forEach((cluster, client) -> {
                    clusterReplicationMetrics.remove(clusterReplicationMetrics.getKeyName(namespaceName, cluster));
                });
            }
        }
    } catch (Exception e) {
        log.warn("Got exception when retrieving bundle name during removeTopicFromCache", e);
    }
    topics.remove(topic);
}
Also used : NamespaceBundle(org.apache.pulsar.common.naming.NamespaceBundle) ConcurrentOpenHashMap(org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap) ClusterReplicationMetrics(org.apache.pulsar.broker.stats.ClusterReplicationMetrics) PersistentTopic(org.apache.pulsar.broker.service.persistent.PersistentTopic) NonPersistentTopic(org.apache.pulsar.broker.service.nonpersistent.NonPersistentTopic) ServiceUnitNotReadyException(org.apache.pulsar.broker.service.BrokerServiceException.ServiceUnitNotReadyException) NamingException(org.apache.pulsar.broker.service.BrokerServiceException.NamingException) NotAllowedException(org.apache.pulsar.broker.service.BrokerServiceException.NotAllowedException) ServerMetadataException(org.apache.pulsar.broker.service.BrokerServiceException.ServerMetadataException) IOException(java.io.IOException) PulsarClientException(org.apache.pulsar.client.api.PulsarClientException) ManagedLedgerException(org.apache.bookkeeper.mledger.ManagedLedgerException) KeeperException(org.apache.zookeeper.KeeperException) PersistenceException(org.apache.pulsar.broker.service.BrokerServiceException.PersistenceException) TopicName(org.apache.pulsar.common.naming.TopicName)

Aggregations

ConcurrentOpenHashMap (org.apache.pulsar.common.util.collections.ConcurrentOpenHashMap)9 PersistentTopic (org.apache.pulsar.broker.service.persistent.PersistentTopic)5 Field (java.lang.reflect.Field)4 ExecutorService (java.util.concurrent.ExecutorService)4 ManagedLedgerException (org.apache.bookkeeper.mledger.ManagedLedgerException)4 Test (org.testng.annotations.Test)4 ArrayList (java.util.ArrayList)3 List (java.util.List)3 Random (java.util.Random)3 NamingException (org.apache.pulsar.broker.service.BrokerServiceException.NamingException)3 TopicName (org.apache.pulsar.common.naming.TopicName)3 Lists (com.google.common.collect.Lists)2 IOException (java.io.IOException)2 Collections (java.util.Collections)2 HashMap (java.util.HashMap)2 Future (java.util.concurrent.Future)2 PersistentDispatcherSingleActiveConsumer (org.apache.pulsar.broker.service.persistent.PersistentDispatcherSingleActiveConsumer)2 PersistentSubscription (org.apache.pulsar.broker.service.persistent.PersistentSubscription)2 PulsarClient (org.apache.pulsar.client.api.PulsarClient)2 PulsarClientImpl (org.apache.pulsar.client.impl.PulsarClientImpl)2