//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.tplink.smb.eventcenter.port.local;
import com.tplink.smb.eventcenter.api.BaseEvent;
import com.tplink.smb.eventcenter.api.Event;
import com.tplink.smb.eventcenter.api.EventCenter;
import com.tplink.smb.eventcenter.api.EventFuture;
import com.tplink.smb.eventcenter.api.EventHandler;
import com.tplink.smb.eventcenter.api.EventV2;
import com.tplink.smb.eventcenter.api.GenericEventFuture;
import com.tplink.smb.eventcenter.api.GenericEventHandler;
import com.tplink.smb.eventcenter.api.constant.EventCenterSendResult;
import com.tplink.smb.eventcenter.api.constant.GenericEventCenterSendResult;
import com.tplink.smb.eventcenter.api.constant.PartitionAssignorMode;
import com.tplink.smb.eventcenter.api.constant.SerializeEnum;
import com.tplink.smb.eventcenter.api.exception.DuplicateGroupIdException;
import com.tplink.smb.eventcenter.core.DataProcessor;
import com.tplink.smb.eventcenter.core.GenericDataProcessor;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nonnull;
import javax.annotation.PreDestroy;
import lombok.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
public class LocalEventCenter implements EventCenter {
private static final Logger log = LoggerFactory.getLogger(LocalEventCenter.class);
private final ConcurrentHashMap<String, AtomicReference<Set<String>>> topicGroupMap = new ConcurrentHashMap(4);
private final ConcurrentHashMap<String, EventHandler> groupHandlerMap = new ConcurrentHashMap(4);
private final ConcurrentHashMap<String, ExecutorService> groupExecutorMap = new ConcurrentHashMap(4);
private final ConcurrentHashMap<String, AtomicReference<Set<String>>> genericTopicGroupMap = new ConcurrentHashMap(4);
private final ConcurrentHashMap<String, GenericEventHandler<?>> genericGroupHandlerMap = new ConcurrentHashMap(4);
private final ConcurrentHashMap<String, ExecutorService> genericGroupExecutorMap = new ConcurrentHashMap(4);
private final String METHOD_NOT_IMPLEMENT = "Method not implement yet, use send instead.";
public LocalEventCenter() {
}
public void send(@Nonnull String topic, @Nonnull Event event) {
this.send(topic, (String)null, (Integer)null, (Event)event, (EventFuture)null);
}
public void send(@Nonnull String topic, @Nonnull Event event, EventFuture eventFuture) {
this.send(topic, (String)null, (Integer)null, (Event)event, (EventFuture)eventFuture);
}
public void send(@Nonnull String topic, String key, @Nonnull Event event) {
this.send(topic, (String)key, (Integer)null, (Event)event, (EventFuture)null);
}
public void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event) {
this.send(topic, (String)null, (Integer)partition, (Event)event, (EventFuture)null);
}
public void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull Event event, EventFuture eventFuture) {
this.send(topic, (String)null, (Integer)partition, (Event)event, (EventFuture)eventFuture);
}
public void send(@Nonnull String topic, String key, @Nonnull Event event, EventFuture eventFuture) {
this.send(topic, (String)key, (Integer)null, (Event)event, (EventFuture)eventFuture);
}
private void send(@Nonnull String topic, String key, Integer partition, @Nonnull Event event, EventFuture eventFuture) {
event.setTimeStamp(System.currentTimeMillis());
if (log.isTraceEnabled()) {
log.trace("before handle event: {}", event);
}
if (!this.dispatchEvent(topic, event)) {
log.warn("Failed to knock event, filterKey: {}, topic:{}", event.getFilterKey(), topic);
} else {
if (Objects.nonNull(eventFuture)) {
EventCenterSendResult eventCenterSendResult = new EventCenterSendResult(topic, key, event, System.currentTimeMillis(), partition);
eventFuture.onSuccess(eventCenterSendResult);
}
if (log.isTraceEnabled()) {
log.trace("after handle event: {}", event);
}
}
}
public void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) {
String groupId = UUID.randomUUID().toString();
this.registerUnicast(topic, groupId, handler, executorService);
}
public void registerBroadcast(@Nonnull String topic, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) {
this.registerBroadcast(topic, handler, executorService);
}
public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService) {
this.register(topic, groupId, handler, executorService);
}
public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode) {
this.registerUnicast(topic, groupId, handler, executorService);
}
public void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) {
String groupId = UUID.randomUUID().toString();
this.registerUnicastWithoutThreadPool(topic, groupId, handler, partitionAssignorMode);
}
public void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull EventHandler handler, PartitionAssignorMode partitionAssignorMode) {
this.register(topic, groupId, handler, (ExecutorService)null);
}
public void unregister(@Nonnull String topic, @Nonnull EventHandler handler) {
boolean haveHandler = false;
String groupId = null;
for(Map.Entry<String, EventHandler> entry : this.groupHandlerMap.entrySet()) {
EventHandler eventHandler = (EventHandler)entry.getValue();
if (Objects.equals(eventHandler, handler)) {
groupId = (String)entry.getKey();
haveHandler = true;
break;
}
}
if (haveHandler) {
this.groupHandlerMap.remove(groupId);
this.groupExecutorMap.remove(groupId);
AtomicReference<Set<String>> atomicReference = (AtomicReference)this.topicGroupMap.get(topic);
this.doUnRegister(groupId, atomicReference);
} else {
log.warn("No such handler could be found to unregister!");
}
}
public <T> void sendGenerically(@Nonnull String topic, @Nonnull T event) {
this.sendGenerically(topic, (String)null, (Integer)null, event, (GenericEventFuture)null);
}
public <T> void sendGenerically(@Nonnull String topic, @Nonnull T event, GenericEventFuture<T> genericEventFuture) {
this.sendGenerically(topic, (String)null, (Integer)null, event, genericEventFuture);
}
public <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event) {
this.sendGenerically(topic, key, (Integer)null, event, (GenericEventFuture)null);
}
public <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event) {
this.sendGenerically(topic, (String)null, partition, event, (GenericEventFuture)null);
}
public <T> void sendGenerically(@Nonnull String topic, @Nonnull Integer partition, @Nonnull T event, GenericEventFuture<T> genericEventFuture) {
this.sendGenerically(topic, (String)null, partition, event, genericEventFuture);
}
public <T> void sendGenerically(@Nonnull String topic, String key, @Nonnull T event, GenericEventFuture<T> genericEventFuture) {
this.sendGenerically(topic, key, (Integer)null, event, genericEventFuture);
}
private <T> void sendGenerically(@Nonnull String topic, String key, Integer partition, @Nonnull T event, GenericEventFuture<T> genericEventFuture) {
if (log.isTraceEnabled()) {
log.trace("before handle event: {}", event);
}
if (!this.dispatchEvent(topic, event)) {
log.warn("Failed to knock event, topic: {}, key:{}", topic, key);
} else {
if (Objects.nonNull(genericEventFuture)) {
GenericEventCenterSendResult<T> genericEventCenterSendResult = new GenericEventCenterSendResult(topic, key, event, System.currentTimeMillis(), partition);
genericEventFuture.onSuccess(genericEventCenterSendResult);
}
if (log.isTraceEnabled()) {
log.trace("after handle event: {}", event);
}
}
}
public <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz is marked non-null but is null");
} else {
String groupId = UUID.randomUUID().toString();
this.registerUnicastGenerically(topic, groupId, handler, executorService, clazz);
}
}
public <T> void registerBroadcastGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz is marked non-null but is null");
} else {
this.registerBroadcastGenerically(topic, handler, executorService, clazz);
}
}
public <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, @NonNull Class<T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz is marked non-null but is null");
} else {
this.register(topic, groupId, handler, executorService);
}
}
public <T> void registerUnicastGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz is marked non-null but is null");
} else {
this.registerUnicastGenerically(topic, groupId, handler, executorService, clazz);
}
}
public <T> void registerBroadcastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz is marked non-null but is null");
} else {
String groupId = UUID.randomUUID().toString();
this.registerUnicastWithoutThreadPoolGenerically(topic, groupId, handler, partitionAssignorMode, clazz);
}
}
public <T> void registerUnicastWithoutThreadPoolGenerically(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler<T> handler, PartitionAssignorMode partitionAssignorMode, @NonNull Class<T> clazz) {
if (clazz == null) {
throw new NullPointerException("clazz is marked non-null but is null");
} else {
this.register(topic, groupId, (GenericEventHandler)handler, (ExecutorService)null);
}
}
public <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler) {
boolean haveHandler = false;
String groupId = null;
for(Map.Entry<String, GenericEventHandler<?>> entry : this.genericGroupHandlerMap.entrySet()) {
GenericEventHandler<?> eventHandler = (GenericEventHandler)entry.getValue();
if (Objects.equals(eventHandler, handler)) {
groupId = (String)entry.getKey();
haveHandler = true;
break;
}
}
if (haveHandler) {
this.genericGroupHandlerMap.remove(groupId);
this.genericGroupExecutorMap.remove(groupId);
AtomicReference<Set<String>> atomicReference = (AtomicReference)this.genericTopicGroupMap.get(topic);
this.doUnRegister(groupId, atomicReference);
} else {
log.warn("No such handler could be found to unregister!");
}
}
public <T> void unregisterGenerically(@Nonnull String topic, @Nonnull GenericEventHandler<T> handler, boolean isDestroyExecutorService) {
this.unregisterGenerically(topic, handler);
}
public void unregister(@Nonnull String topic, @Nonnull EventHandler eventHandler, boolean isDestroyExecutorService) {
this.unregister(topic, eventHandler);
}
public void unregisterAllTopics() {
this.destroy();
}
@PreDestroy
public void destroy() {
this.topicGroupMap.clear();
this.groupHandlerMap.clear();
this.groupExecutorMap.clear();
this.genericTopicGroupMap.clear();
this.genericGroupHandlerMap.clear();
this.genericGroupExecutorMap.clear();
}
private void doUnRegister(String groupId, AtomicReference<Set<String>> atomicReference) {
boolean isUpdate;
do {
Set<String> oldGroups = (Set)atomicReference.get();
Set<String> newGroups;
if (CollectionUtils.isEmpty((Collection)atomicReference.get())) {
newGroups = new HashSet();
} else {
newGroups = new HashSet(oldGroups);
}
newGroups.remove(groupId);
isUpdate = atomicReference.compareAndSet(oldGroups, newGroups);
} while(!isUpdate);
}
private boolean dispatchEvent(String topic, Event event) {
if (!this.topicGroupMap.containsKey(topic)) {
log.warn("no handlers for topic: {},", topic);
return false;
} else {
AtomicReference<Set<String>> atomicReference = (AtomicReference)this.topicGroupMap.get(topic);
if (!Objects.isNull(atomicReference) && !CollectionUtils.isEmpty((Collection)atomicReference.get())) {
for(String groupId : (Set)atomicReference.get()) {
EventHandler eventHandler = (EventHandler)this.groupHandlerMap.get(groupId);
ExecutorService executorService = (ExecutorService)this.groupExecutorMap.get(groupId);
log.debug("handlers: {},", eventHandler.getClass());
if (Objects.nonNull(executorService)) {
executorService.submit(new DataProcessor(event, eventHandler));
} else {
this.dataProcessor(event, eventHandler);
}
}
return true;
} else {
return true;
}
}
}
private void register(String topic, String groupId, EventHandler handler, ExecutorService executorService) {
try {
AtomicReference<Set<String>> atomicReference = this.doRegister(groupId, (AtomicReference)this.topicGroupMap.computeIfAbsent(topic, (k) -> new AtomicReference()));
this.topicGroupMap.put(topic, atomicReference);
this.groupHandlerMap.put(groupId, handler);
this.groupExecutorMap.put(groupId, executorService);
} catch (DuplicateGroupIdException var6) {
log.warn("The groupId has been registered! Please check the value of groupId:{}.topic:{}", groupId, topic);
}
}
private void dataProcessor(Event event, EventHandler eventHandler) {
try {
eventHandler.handleEvent(event);
} catch (Exception e) {
log.error("Fail to process event, filterKey:{}, handler:{}", new Object[]{event.getFilterKey(), eventHandler, e});
}
}
private <T> boolean dispatchEvent(String topic, T event) {
if (!this.genericTopicGroupMap.containsKey(topic)) {
log.warn("no handlers for topic: {},", topic);
return false;
} else {
AtomicReference<Set<String>> atomicReference = (AtomicReference)this.genericTopicGroupMap.get(topic);
if (!Objects.isNull(atomicReference) && !CollectionUtils.isEmpty((Collection)atomicReference.get())) {
for(String groupId : (Set)atomicReference.get()) {
GenericEventHandler<T> eventHandler = (GenericEventHandler)this.genericGroupHandlerMap.get(groupId);
ExecutorService executorService = (ExecutorService)this.genericGroupExecutorMap.get(groupId);
log.debug("handlers: {},", eventHandler.getClass());
if (Objects.nonNull(executorService)) {
executorService.submit(new GenericDataProcessor(event, eventHandler));
} else {
this.dataProcessor(event, eventHandler);
}
}
return true;
} else {
return true;
}
}
}
private <T> void register(String topic, String groupId, GenericEventHandler<T> handler, ExecutorService executorService) {
try {
AtomicReference<Set<String>> atomicReference = this.doRegister(groupId, (AtomicReference)this.genericTopicGroupMap.computeIfAbsent(topic, (k) -> new AtomicReference()));
this.genericTopicGroupMap.put(topic, atomicReference);
this.genericGroupHandlerMap.put(groupId, handler);
this.genericGroupExecutorMap.put(groupId, executorService);
} catch (DuplicateGroupIdException var6) {
log.warn("The groupId has been registered! Please check the value of groupId:{}.topic:{}", groupId, topic);
}
}
private AtomicReference<Set<String>> doRegister(String groupId, AtomicReference<Set<String>> atomicReference) throws DuplicateGroupIdException {
boolean isUpdate;
do {
Set<String> oldGroups = (Set)atomicReference.get();
Set<String> newGroups;
if (CollectionUtils.isEmpty(oldGroups)) {
newGroups = new HashSet();
} else {
if (oldGroups.contains(groupId)) {
throw new DuplicateGroupIdException();
}
newGroups = new HashSet((Collection)atomicReference.get());
}
newGroups.add(groupId);
isUpdate = atomicReference.compareAndSet(oldGroups, newGroups);
} while(!isUpdate);
return atomicReference;
}
private <T> void dataProcessor(T event, GenericEventHandler<T> eventHandler) {
try {
eventHandler.handleEvent(event);
} catch (Exception e) {
log.error("Fail to process event, handler:{}", eventHandler, e);
}
}
public void send(@Nonnull String topic, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.sendWithKryo(topic, (String)null, (Integer)null, (EventV2)event, (GenericEventFuture)null);
break;
default:
log.debug("Method not implement yet, use send instead.");
}
}
public void send(@Nonnull String topic, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.sendWithKryo(topic, (String)null, (Integer)null, (EventV2)event, eventFuture);
break;
default:
log.debug("Method not implement yet, use send instead.");
}
}
public void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.sendWithKryo(topic, key, (Integer)null, (EventV2)event, (GenericEventFuture)null);
break;
default:
log.debug("Method not implement yet, use send instead.");
}
}
public void send(@Nonnull String topic, String key, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.sendWithKryo(topic, key, (Integer)null, (EventV2)event, eventFuture);
break;
default:
log.debug("Method not implement yet, use send instead.");
}
}
public void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.sendWithKryo(topic, (String)null, partition, (EventV2)event, (GenericEventFuture)null);
break;
default:
log.debug("Method not implement yet, use send instead.");
}
}
public void send(@Nonnull String topic, @Nonnull Integer partition, @Nonnull BaseEvent event, GenericEventFuture eventFuture, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.sendWithKryo(topic, (String)null, partition, (EventV2)event, eventFuture);
break;
default:
log.debug("Method not implement yet, use send instead.");
}
}
private <T> void sendWithKryo(@Nonnull String topic, String key, Integer partition, @Nonnull EventV2<T> event, GenericEventFuture eventFuture) {
event.setTimeStamp(System.currentTimeMillis());
if (log.isTraceEnabled()) {
log.trace("before handle event: {}", event);
}
if (!this.dispatchEvent(topic, (Object)event)) {
log.warn("Failed to knock event, filterKey: {}, topic:{}", event.getFilterKey(), topic);
} else {
if (Objects.nonNull(eventFuture)) {
GenericEventCenterSendResult<T> genericEventCenterSendResult = new GenericEventCenterSendResult(topic, key, event.getMessage(), System.currentTimeMillis(), partition);
eventFuture.onSuccess(genericEventCenterSendResult);
}
if (log.isTraceEnabled()) {
log.trace("after handle event: {}", event);
}
}
}
public void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
String groupId = UUID.randomUUID().toString();
this.registerUnicast(topic, groupId, handler, executorService, serializeEnum);
break;
default:
this.registerBroadcastGenerically(topic, handler, executorService, EventV2.class);
}
}
public void registerBroadcast(@Nonnull String topic, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
String groupId = UUID.randomUUID().toString();
this.registerUnicast(topic, groupId, handler, executorService, partitionAssignorMode, serializeEnum);
break;
default:
this.registerBroadcastGenerically(topic, handler, executorService, partitionAssignorMode, EventV2.class);
}
}
public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.registerUnicast(topic, groupId, handler, executorService, (PartitionAssignorMode)null, serializeEnum);
break;
default:
this.registerUnicastGenerically(topic, groupId, handler, executorService, (PartitionAssignorMode)null, EventV2.class);
}
}
public void registerUnicast(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, @Nonnull ExecutorService executorService, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.registerUnicastGenerically(topic, groupId, handler, executorService, EventV2.class);
break;
default:
this.registerUnicastGenerically(topic, groupId, handler, executorService, partitionAssignorMode, EventV2.class);
}
}
public void registerBroadcastWithoutThreadPool(@Nonnull String topic, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
String groupId = UUID.randomUUID().toString();
this.registerUnicastWithoutThreadPoolGenerically(topic, groupId, handler, partitionAssignorMode, EventV2.class);
break;
default:
this.registerBroadcastWithoutThreadPoolGenerically(topic, handler, partitionAssignorMode, EventV2.class);
}
}
public void registerUnicastWithoutThreadPool(@Nonnull String topic, @Nonnull String groupId, @Nonnull GenericEventHandler handler, PartitionAssignorMode partitionAssignorMode, @Nonnull SerializeEnum serializeEnum) {
switch (serializeEnum) {
case KRYO:
this.register(topic, groupId, (GenericEventHandler)handler, (ExecutorService)null);
break;
default:
this.registerUnicastWithoutThreadPoolGenerically(topic, groupId, handler, partitionAssignorMode, EventV2.class);
}
}
}
这是项目中local版本的消息中心的实现,理解一下