Monitoring: Change ExportBulk so that it has states

Original commit: elastic/x-pack-elasticsearch@8dc55dc0d2
This commit is contained in:
Tanguy Leroux 2016-04-04 17:47:00 +02:00
parent b65787f7dd
commit 4df6f0f701
4 changed files with 109 additions and 51 deletions

View File

@ -6,13 +6,16 @@
package org.elasticsearch.marvel.agent.exporter;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
/**
*
* An export bulk holds one of more documents until it got flushed. The {@link ExportBulk#flush()} usually triggers the exporting of the
* documents to their final destination.
*/
public abstract class ExportBulk {
protected final String name;
private final AtomicReference<State> state = new AtomicReference<>(State.INITIALIZING);
public ExportBulk(String name) {
this.name = name;
@ -23,19 +26,48 @@ public abstract class ExportBulk {
return name;
}
public abstract ExportBulk add(Collection<MonitoringDoc> docs) throws ExportException;
public abstract void flush() throws ExportException;
public final void close(boolean flush) throws ExportException {
ExportException exception = null;
if (flush) {
flush();
/**
* Add documents to the exporting bulk
*/
public void add(Collection<MonitoringDoc> docs) throws ExportException {
if (state.get() == State.INITIALIZING) {
doAdd(docs);
}
}
// now closing
protected abstract void doAdd(Collection<MonitoringDoc> docs) throws ExportException;
/**
* Flush the exporting bulk
*/
public void flush() throws ExportException {
if (state.compareAndSet(State.INITIALIZING, State.FLUSHING)) {
doFlush();
}
}
protected abstract void doFlush();
/**
* Close the exporting bulk
*/
public void close(boolean flush) throws ExportException {
if (state.getAndSet(State.CLOSED) != State.CLOSED) {
ExportException exception = null;
try {
onClose();
if (flush) {
doFlush();
}
} catch (ExportException e) {
if (exception != null) {
exception.addSuppressed(e);
} else {
exception = e;
}
} finally {
try {
doClose();
} catch (Exception e) {
if (exception != null) {
exception.addSuppressed(e);
@ -43,16 +75,24 @@ public abstract class ExportBulk {
exception = new ExportException("Exception when closing export bulk", e);
}
}
}
// rethrow exception
if (exception != null) {
throw exception;
}
}
protected void onClose() throws Exception {
}
protected abstract void doClose() throws ExportException;
protected boolean isClosed() {
return state.get() == State.CLOSED;
}
/**
* This class holds multiple export bulks exposed as a single compound bulk.
*/
public static class Compound extends ExportBulk {
private final Collection<ExportBulk> bulks;
@ -63,7 +103,7 @@ public abstract class ExportBulk {
}
@Override
public ExportBulk add(Collection<MonitoringDoc> docs) throws ExportException {
protected void doAdd(Collection<MonitoringDoc> docs) throws ExportException {
ExportException exception = null;
for (ExportBulk bulk : bulks) {
try {
@ -78,11 +118,10 @@ public abstract class ExportBulk {
if (exception != null) {
throw exception;
}
return this;
}
@Override
public void flush() throws ExportException {
protected void doFlush() {
ExportException exception = null;
for (ExportBulk bulk : bulks) {
try {
@ -100,11 +139,13 @@ public abstract class ExportBulk {
}
@Override
protected void onClose() throws Exception {
protected void doClose() throws ExportException {
ExportException exception = null;
for (ExportBulk bulk : bulks) {
try {
bulk.onClose();
// We can close without flushing since doFlush()
// would have been called by the parent class
bulk.close(false);
} catch (ExportException e) {
if (exception == null) {
exception = new ExportException("failed to close export bulks");
@ -117,4 +158,10 @@ public abstract class ExportBulk {
}
}
}
private enum State {
INITIALIZING,
FLUSHING,
CLOSED
}
}

View File

@ -237,8 +237,7 @@ public class HttpExporter extends Exporter {
@SuppressWarnings("unchecked")
private void sendCloseExportingConnection(HttpURLConnection conn) throws IOException {
logger.trace("sending content");
OutputStream os = conn.getOutputStream();
os.close();
closeExportingConnection(conn);
if (conn.getResponseCode() != 200) {
logConnectionError("remote target didn't respond with 200 OK", conn);
return;
@ -263,6 +262,12 @@ public class HttpExporter extends Exporter {
}
}
private void closeExportingConnection(HttpURLConnection connection) throws IOException {
try (OutputStream os = connection.getOutputStream()) {
logger.debug("closing exporting connection [{}]", connection);
}
}
/**
* open a connection to any host, validating it has the template installed if needed
*
@ -701,7 +706,7 @@ public class HttpExporter extends Exporter {
}
@Override
public Bulk add(Collection<MonitoringDoc> docs) throws ExportException {
public void doAdd(Collection<MonitoringDoc> docs) throws ExportException {
try {
if ((docs != null) && (!docs.isEmpty())) {
if (connection == null) {
@ -731,14 +736,13 @@ public class HttpExporter extends Exporter {
} catch (Exception e) {
throw new ExportException("failed to add documents to export bulk [{}]", name);
}
return this;
}
@Override
public void flush() throws ExportException {
public void doFlush() throws ExportException {
if (connection != null) {
try {
flush(connection);
sendCloseExportingConnection(connection);
} catch (Exception e) {
throw new ExportException("failed to flush export bulk [{}]", e, name);
} finally {
@ -747,8 +751,17 @@ public class HttpExporter extends Exporter {
}
}
private void flush(HttpURLConnection connection) throws IOException {
sendCloseExportingConnection(connection);
@Override
protected void doClose() throws ExportException {
if (connection != null) {
try {
closeExportingConnection(connection);
} catch (Exception e) {
throw new ExportException("failed to close export bulk [{}]", e, name);
} finally {
connection = null;
}
}
}
}

View File

@ -20,18 +20,16 @@ import org.elasticsearch.marvel.support.init.proxy.MonitoringClientProxy;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* LocalBulk exports monitoring data in the local cluster using bulk requests. Its usage is not thread safe since the
* {@link LocalBulk#add(Collection)}, {@link LocalBulk#flush()} and {@link LocalBulk#onClose()} methods are not synchronized.
* {@link LocalBulk#add(Collection)}, {@link LocalBulk#flush()} and {@link LocalBulk#doClose()} methods are not synchronized.
*/
public class LocalBulk extends ExportBulk {
private final ESLogger logger;
private final MonitoringClientProxy client;
private final ResolversRegistry resolvers;
private final AtomicBoolean closed;
private BulkRequestBuilder requestBuilder;
@ -41,16 +39,15 @@ public class LocalBulk extends ExportBulk {
this.logger = logger;
this.client = client;
this.resolvers = resolvers;
this.closed = new AtomicBoolean(false);
}
@Override
public ExportBulk add(Collection<MonitoringDoc> docs) throws ExportException {
public void doAdd(Collection<MonitoringDoc> docs) throws ExportException {
ExportException exception = null;
for (MonitoringDoc doc : docs) {
if (closed.get()) {
return this;
if (isClosed()) {
return;
}
if (requestBuilder == null) {
requestBuilder = client.prepareBulk();
@ -77,13 +74,11 @@ public class LocalBulk extends ExportBulk {
if (exception != null) {
throw exception;
}
return this;
}
@Override
public void flush() throws ExportException {
if (closed.get() || requestBuilder == null || requestBuilder.numberOfActions() == 0) {
public void doFlush() throws ExportException {
if (requestBuilder == null || requestBuilder.numberOfActions() == 0 || isClosed()) {
return;
}
try {
@ -114,8 +109,8 @@ public class LocalBulk extends ExportBulk {
}
@Override
protected void onClose() throws Exception {
if (closed.compareAndSet(false, true)) {
protected void doClose() throws ExportException {
if (isClosed() == false) {
requestBuilder = null;
}
}

View File

@ -413,13 +413,16 @@ public class ExportersTests extends ESTestCase {
}
@Override
public ExportBulk add(Collection<MonitoringDoc> docs) throws ExportException {
protected void doAdd(Collection<MonitoringDoc> docs) throws ExportException {
count.addAndGet(docs.size());
return this;
}
@Override
public void flush() throws ExportException {
protected void doFlush() {
}
@Override
protected void doClose() throws ExportException {
}
AtomicInteger getCount() {