package org.skywalking.apm.collector.worker;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetItemResponse;
import org.elasticsearch.action.get.MultiGetRequestBuilder;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.client.Client;
import org.skywalking.apm.collector.actor.*;
import org.skywalking.apm.collector.worker.storage.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author pengys5
*/
public abstract class PersistenceMember<T extends Window & PersistenceData, D extends Data> extends AbstractLocalSyncWorker {
private Logger logger = LogManager.getFormatterLogger(PersistenceMember.class);
public PersistenceMember(Role role, ClusterWorkerContext clusterContext, LocalWorkerContext selfContext) {
super(role, clusterContext, selfContext);
persistenceData = initializeData();
}
private T persistenceData;
public abstract T initializeData();
protected T getPersistenceData() {
return persistenceData;
}
public abstract String esIndex();
public abstract String esType();
public abstract void analyse(Object message) throws Exception;
@Override
final public void preStart() throws ProviderNotFoundException {
}
@Override
protected void onWork(Object request, Object response) throws Exception {
if (request instanceof FlushAndSwitch) {
persistenceData.switchPointer();
while (persistenceData.getLast().isHolding()) {
Thread.sleep(10);
}
if (response instanceof LinkedList) {
prepareIndex((LinkedList) response);
} else {
logger.error("unhandled response, response instance must LinkedList, but is %s", response.getClass().toString());
}
} else {
analyse(request);
}
}
private MultiGetResponse searchFromEs(Map<String, D> dataMap) {
Client client = EsClient.INSTANCE.getClient();
MultiGetRequestBuilder multiGetRequestBuilder = client.prepareMultiGet();
HasDataFlag flag = new HasDataFlag();
dataMap.forEach((key, value) -> {
multiGetRequestBuilder.add(esIndex(), esType(), value.getId());
flag.doTagHasData();
});
if (flag.isHasData()) {
return multiGetRequestBuilder.get();
} else {
return null;
}
}
final void extractData(Map<String, D> dataMap) {
MultiGetResponse multiGetResponse = searchFromEs(dataMap);
if (multiGetResponse != null) {
for (MultiGetItemResponse itemResponse : multiGetResponse) {
GetResponse response = itemResponse.getResponse();
if (response != null && response.isExists()) {
if (dataMap.containsKey(response.getId())) {
dataMap.get(response.getId()).merge(response.getSource());
}
}
}
}
}
protected abstract void prepareIndex(List<IndexRequestBuilder> builderList);
class HasDataFlag {
private boolean hasData;
HasDataFlag() {
hasData = false;
}
boolean isHasData() {
return hasData;
}
void doTagHasData() {
this.hasData = true;
}
}
}