Search in sources :

Example 21 with Notification

use of org.apache.pulsar.metadata.api.Notification in project pulsar by apache.

the class LocalMemoryMetadataStore method storeDelete.

@Override
public CompletableFuture<Void> storeDelete(String path, Optional<Long> optExpectedVersion) {
    if (!isValidPath(path)) {
        return FutureUtil.failedFuture(new MetadataStoreException.InvalidPathException(path));
    }
    synchronized (map) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        Value value = map.get(path);
        if (value == null) {
            execute(() -> future.completeExceptionally(new NotFoundException("")), future);
        } else if (optExpectedVersion.isPresent() && optExpectedVersion.get() != value.version) {
            execute(() -> future.completeExceptionally(new BadVersionException("")), future);
        } else {
            map.remove(path);
            receivedNotification(new Notification(NotificationType.Deleted, path));
            notifyParentChildrenChanged(path);
            execute(() -> future.complete(null), future);
        }
        return future;
    }
}
Also used : MetadataStoreException(org.apache.pulsar.metadata.api.MetadataStoreException) CompletableFuture(java.util.concurrent.CompletableFuture) NotFoundException(org.apache.pulsar.metadata.api.MetadataStoreException.NotFoundException) BadVersionException(org.apache.pulsar.metadata.api.MetadataStoreException.BadVersionException) Notification(org.apache.pulsar.metadata.api.Notification)

Example 22 with Notification

use of org.apache.pulsar.metadata.api.Notification in project pulsar by apache.

the class LocalMemoryMetadataStore method storePut.

@Override
public CompletableFuture<Stat> storePut(String path, byte[] data, Optional<Long> optExpectedVersion, EnumSet<CreateOption> options) {
    if (!isValidPath(path)) {
        return FutureUtil.failedFuture(new MetadataStoreException.InvalidPathException(path));
    }
    synchronized (map) {
        boolean hasVersion = optExpectedVersion.isPresent();
        int expectedVersion = optExpectedVersion.orElse(-1L).intValue();
        if (options.contains(CreateOption.Sequential)) {
            path += Long.toString(sequentialIdGenerator.getAndIncrement());
        }
        long now = System.currentTimeMillis();
        CompletableFuture<Stat> future = new CompletableFuture<>();
        if (hasVersion && expectedVersion == -1) {
            Value newValue = new Value(0, data, now, now, options.contains(CreateOption.Ephemeral));
            Value existingValue = map.putIfAbsent(path, newValue);
            if (existingValue != null) {
                execute(() -> future.completeExceptionally(new BadVersionException("")), future);
            } else {
                receivedNotification(new Notification(NotificationType.Created, path));
                notifyParentChildrenChanged(path);
                String finalPath = path;
                execute(() -> future.complete(new Stat(finalPath, 0, now, now, newValue.isEphemeral(), true)), future);
            }
        } else {
            Value existingValue = map.get(path);
            long existingVersion = existingValue != null ? existingValue.version : -1;
            if (hasVersion && expectedVersion != existingVersion) {
                execute(() -> future.completeExceptionally(new BadVersionException("")), future);
            } else {
                long newVersion = existingValue != null ? existingValue.version + 1 : 0;
                long createdTimestamp = existingValue != null ? existingValue.createdTimestamp : now;
                Value newValue = new Value(newVersion, data, createdTimestamp, now, options.contains(CreateOption.Ephemeral));
                map.put(path, newValue);
                NotificationType type = existingValue == null ? NotificationType.Created : NotificationType.Modified;
                receivedNotification(new Notification(type, path));
                if (type == NotificationType.Created) {
                    notifyParentChildrenChanged(path);
                }
                String finalPath = path;
                execute(() -> future.complete(new Stat(finalPath, newValue.version, newValue.createdTimestamp, newValue.modifiedTimestamp, false, true)), future);
            }
        }
        return future;
    }
}
Also used : BadVersionException(org.apache.pulsar.metadata.api.MetadataStoreException.BadVersionException) Notification(org.apache.pulsar.metadata.api.Notification) MetadataStoreException(org.apache.pulsar.metadata.api.MetadataStoreException) CompletableFuture(java.util.concurrent.CompletableFuture) Stat(org.apache.pulsar.metadata.api.Stat) NotificationType(org.apache.pulsar.metadata.api.NotificationType)

Example 23 with Notification

use of org.apache.pulsar.metadata.api.Notification in project pulsar by apache.

the class EtcdMetadataStore method handleWatchResponse.

private void handleWatchResponse(WatchResponse watchResponse) {
    watchResponse.getEvents().forEach(we -> {
        String path = we.getKeyValue().getKey().toString(StandardCharsets.UTF_8);
        if (we.getEventType() == WatchEvent.EventType.PUT) {
            if (we.getKeyValue().getVersion() == 1) {
                receivedNotification(new Notification(NotificationType.Created, path));
                notifyParentChildrenChanged(path);
            } else {
                receivedNotification(new Notification(NotificationType.Modified, path));
            }
        } else if (we.getEventType() == WatchEvent.EventType.DELETE) {
            receivedNotification(new Notification(NotificationType.Deleted, path));
            notifyParentChildrenChanged(path);
        }
    });
}
Also used : Notification(org.apache.pulsar.metadata.api.Notification)

Example 24 with Notification

use of org.apache.pulsar.metadata.api.Notification in project pulsar by apache.

the class MetadataStoreTest method notificationListeners.

@Test(dataProvider = "impl")
public void notificationListeners(String provider, Supplier<String> urlSupplier) throws Exception {
    @Cleanup MetadataStore store = MetadataStoreFactory.create(urlSupplier.get(), MetadataStoreConfig.builder().build());
    BlockingQueue<Notification> notifications = new LinkedBlockingDeque<>();
    store.registerListener(n -> {
        notifications.add(n);
    });
    String key1 = newKey();
    assertFalse(store.get(key1).join().isPresent());
    // Trigger created notification
    Stat stat = store.put(key1, "value-1".getBytes(), Optional.empty()).join();
    assertTrue(store.get(key1).join().isPresent());
    assertEquals(store.getChildren(key1).join(), Collections.emptyList());
    assertEquals(stat.getVersion(), 0);
    Notification n = notifications.poll(3, TimeUnit.SECONDS);
    assertNotNull(n);
    assertEquals(n.getType(), NotificationType.Created);
    assertEquals(n.getPath(), key1);
    // Trigger modified notification
    stat = store.put(key1, "value-2".getBytes(), Optional.empty()).join();
    n = notifications.poll(3, TimeUnit.SECONDS);
    assertNotNull(n);
    assertEquals(n.getType(), NotificationType.Modified);
    assertEquals(n.getPath(), key1);
    assertEquals(stat.getVersion(), 1);
    // Trigger modified notification on the parent
    String key1Child = key1 + "/xx";
    assertFalse(store.get(key1Child).join().isPresent());
    store.put(key1Child, "value-2".getBytes(), Optional.empty()).join();
    n = notifications.poll(3, TimeUnit.SECONDS);
    assertNotNull(n);
    assertEquals(n.getType(), NotificationType.Created);
    assertEquals(n.getPath(), key1Child);
    n = notifications.poll(3, TimeUnit.SECONDS);
    assertNotNull(n);
    assertEquals(n.getType(), NotificationType.ChildrenChanged);
    assertEquals(n.getPath(), key1);
    assertTrue(store.exists(key1Child).join());
    assertEquals(store.getChildren(key1).join(), Collections.singletonList("xx"));
    store.delete(key1Child, Optional.empty()).join();
    n = notifications.poll(3, TimeUnit.SECONDS);
    assertNotNull(n);
    assertEquals(n.getType(), NotificationType.Deleted);
    assertEquals(n.getPath(), key1Child);
    // Parent should be notified of the deletion
    n = notifications.poll(3, TimeUnit.SECONDS);
    assertNotNull(n);
    assertEquals(n.getType(), NotificationType.ChildrenChanged);
    assertEquals(n.getPath(), key1);
}
Also used : MetadataStore(org.apache.pulsar.metadata.api.MetadataStore) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Stat(org.apache.pulsar.metadata.api.Stat) Cleanup(lombok.Cleanup) Notification(org.apache.pulsar.metadata.api.Notification) Test(org.testng.annotations.Test)

Example 25 with Notification

use of org.apache.pulsar.metadata.api.Notification in project pulsar by apache.

the class ModularLoadManagerImplTest method testLoadShedding.

// Test that load shedding works
@Test
public void testLoadShedding() throws Exception {
    final NamespaceBundleStats stats1 = new NamespaceBundleStats();
    final NamespaceBundleStats stats2 = new NamespaceBundleStats();
    stats1.msgRateIn = 100;
    stats2.msgRateIn = 200;
    final Map<String, NamespaceBundleStats> statsMap = new ConcurrentHashMap<>();
    statsMap.put(mockBundleName(1), stats1);
    statsMap.put(mockBundleName(2), stats2);
    final LocalBrokerData localBrokerData = new LocalBrokerData();
    localBrokerData.update(new SystemResourceUsage(), statsMap);
    final Namespaces namespacesSpy1 = spy(pulsar1.getAdminClient().namespaces());
    AtomicReference<String> bundleReference = new AtomicReference<>();
    doAnswer(invocation -> {
        bundleReference.set(invocation.getArguments()[0].toString() + '/' + invocation.getArguments()[1]);
        return null;
    }).when(namespacesSpy1).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    setField(pulsar1.getAdminClient(), "namespaces", namespacesSpy1);
    pulsar1.getConfiguration().setLoadBalancerEnabled(true);
    final LoadData loadData = (LoadData) getField(primaryLoadManager, "loadData");
    final Map<String, BrokerData> brokerDataMap = loadData.getBrokerData();
    final BrokerData brokerDataSpy1 = spy(brokerDataMap.get(primaryHost));
    when(brokerDataSpy1.getLocalData()).thenReturn(localBrokerData);
    brokerDataMap.put(primaryHost, brokerDataSpy1);
    // Need to update all the bundle data for the shredder to see the spy.
    primaryLoadManager.handleDataNotification(new Notification(NotificationType.Created, LoadManager.LOADBALANCE_BROKERS_ROOT + "/broker:8080"));
    Thread.sleep(100);
    localBrokerData.setCpu(new ResourceUsage(80, 100));
    primaryLoadManager.doLoadShedding();
    // 80% is below overload threshold: verify nothing is unloaded.
    verify(namespacesSpy1, Mockito.times(0)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    localBrokerData.setCpu(new ResourceUsage(90, 100));
    primaryLoadManager.doLoadShedding();
    // Most expensive bundle will be unloaded.
    verify(namespacesSpy1, Mockito.times(1)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    assertEquals(bundleReference.get(), mockBundleName(2));
    primaryLoadManager.doLoadShedding();
    // Now less expensive bundle will be unloaded (normally other bundle would move off and nothing would be
    // unloaded, but this is not the case due to the spy's behavior).
    verify(namespacesSpy1, Mockito.times(2)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    assertEquals(bundleReference.get(), mockBundleName(1));
    primaryLoadManager.doLoadShedding();
    // Now both are in grace period: neither should be unloaded.
    verify(namespacesSpy1, Mockito.times(2)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
}
Also used : Namespaces(org.apache.pulsar.client.admin.Namespaces) LocalBrokerData(org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData) BrokerData(org.apache.pulsar.broker.BrokerData) TimeAverageBrokerData(org.apache.pulsar.broker.TimeAverageBrokerData) LocalBrokerData(org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData) SystemResourceUsage(org.apache.pulsar.policies.data.loadbalancer.SystemResourceUsage) ResourceUsage(org.apache.pulsar.policies.data.loadbalancer.ResourceUsage) SystemResourceUsage(org.apache.pulsar.policies.data.loadbalancer.SystemResourceUsage) AtomicReference(java.util.concurrent.atomic.AtomicReference) Notification(org.apache.pulsar.metadata.api.Notification) NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Test(org.testng.annotations.Test)

Aggregations

Notification (org.apache.pulsar.metadata.api.Notification)25 Stat (org.apache.pulsar.metadata.api.Stat)9 NotificationType (org.apache.pulsar.metadata.api.NotificationType)6 Transaction (org.rocksdb.Transaction)6 Test (org.testng.annotations.Test)6 MetadataStoreException (org.apache.pulsar.metadata.api.MetadataStoreException)4 BadVersionException (org.apache.pulsar.metadata.api.MetadataStoreException.BadVersionException)4 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 LinkedBlockingDeque (java.util.concurrent.LinkedBlockingDeque)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 Cleanup (lombok.Cleanup)3 Namespaces (org.apache.pulsar.client.admin.Namespaces)3 MetadataStore (org.apache.pulsar.metadata.api.MetadataStore)3 LocalBrokerData (org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData)3 NamespaceBundleStats (org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats)3 ResourceUsage (org.apache.pulsar.policies.data.loadbalancer.ResourceUsage)3 SystemResourceUsage (org.apache.pulsar.policies.data.loadbalancer.SystemResourceUsage)3 CompletableFuture (java.util.concurrent.CompletableFuture)2 BrokerData (org.apache.pulsar.policies.data.loadbalancer.BrokerData)2 TimeAverageBrokerData (org.apache.pulsar.policies.data.loadbalancer.TimeAverageBrokerData)2