Java tutorial
/* * Copyright (c) 2017 SUSE LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. * See the License for the specific language governing permissions and * limitations under the License. */ package monasca.persister.repository.cassandra; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.codahale.metrics.Counter; import com.codahale.metrics.Timer; import com.datastax.driver.core.BatchStatement; import com.datastax.driver.core.BatchStatement.Type; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSetFuture; import com.datastax.driver.core.Session; import com.datastax.driver.core.Statement; import com.datastax.driver.core.exceptions.BootstrappingException; import com.datastax.driver.core.exceptions.DriverException; import com.datastax.driver.core.exceptions.NoHostAvailableException; import com.datastax.driver.core.exceptions.OperationTimedOutException; import com.datastax.driver.core.exceptions.OverloadedException; import com.datastax.driver.core.exceptions.QueryConsistencyException; import com.datastax.driver.core.exceptions.UnavailableException; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import io.dropwizard.setup.Environment; import monasca.persister.repository.RepoException; public abstract class CassandraRepo { private static Logger logger = LoggerFactory.getLogger(CassandraRepo.class); final Environment environment; final Timer commitTimer; CassandraCluster cluster; Session session; int maxWriteRetries; int batchSize; long lastFlushTimeStamp; Deque<Statement> queue; Counter metricCompleted; Counter metricFailed; public CassandraRepo(CassandraCluster cluster, Environment env, int maxWriteRetries, int batchSize) { this.cluster = cluster; this.maxWriteRetries = maxWriteRetries; this.batchSize = batchSize; this.environment = env; this.commitTimer = this.environment.metrics().timer(getClass().getName() + "." + "commit-timer"); lastFlushTimeStamp = System.currentTimeMillis(); queue = new ArrayDeque<>(batchSize); this.metricCompleted = environment.metrics() .counter(getClass().getName() + "." + "metrics-persisted-counter"); this.metricFailed = environment.metrics().counter(getClass().getName() + "." + "metrics-failed-counter"); } protected void executeQuery(String id, Statement query, long startTime) throws DriverException { _executeQuery(id, query, startTime, 0); } private void _executeQuery(final String id, final Statement query, final long startTime, final int retryCount) { try { session.execute(query); commitTimer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); // ResultSetFuture future = session.executeAsync(query); // Futures.addCallback(future, new FutureCallback<ResultSet>() { // @Override // public void onSuccess(ResultSet result) { // metricCompleted.inc(); // commitTimer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); // } // // @Override // public void onFailure(Throwable t) { // if (t instanceof NoHostAvailableException | t instanceof // BootstrappingException // | t instanceof OverloadedException | t instanceof QueryConsistencyException // | t instanceof UnavailableException) { // retryQuery(id, query, startTime, retryCount, (DriverException) t); // } else { // metricFailed.inc(); // commitTimer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); // logger.error("Failed to execute query.", t); // } // } // }, MoreExecutors.sameThreadExecutor()); } catch (NoHostAvailableException | BootstrappingException | OverloadedException | QueryConsistencyException | UnavailableException | OperationTimedOutException e) { retryQuery(id, query, startTime, retryCount, e); } catch (DriverException e) { metricFailed.inc(((BatchStatement) query).size()); commitTimer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); throw e; } } private void retryQuery(String id, Statement query, final long startTime, int retryCount, DriverException e) throws DriverException { if (retryCount >= maxWriteRetries) { logger.error("[{}]: Query aborted after {} retry: ", id, retryCount, e.getMessage()); metricFailed.inc(((BatchStatement) query).size()); commitTimer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); throw e; } else { logger.warn("[{}]: Query failed, retrying {} of {}: {} ", id, retryCount, maxWriteRetries, e.getMessage()); try { Thread.sleep(1000 * (1 << retryCount)); } catch (InterruptedException ie) { logger.debug("[{}]: Interrupted: {}", id, ie); } _executeQuery(id, query, startTime, retryCount++); } } public int handleFlush_batch(String id) { Statement query; int flushedCount = 0; BatchStatement batch = new BatchStatement(Type.UNLOGGED); while ((query = queue.poll()) != null) { flushedCount++; batch.add(query); } executeQuery(id, batch, System.nanoTime()); metricCompleted.inc(flushedCount); return flushedCount; } public int handleFlush(String id) throws RepoException { long startTime = System.nanoTime(); int flushedCount = 0; List<ResultSetFuture> results = new ArrayList<>(queue.size()); Statement query; while ((query = queue.poll()) != null) { flushedCount++; results.add(session.executeAsync(query)); } List<ListenableFuture<ResultSet>> futures = Futures.inCompletionOrder(results); boolean cancel = false; Exception ex = null; for (ListenableFuture<ResultSet> future : futures) { if (cancel) { future.cancel(false); continue; } try { future.get(); } catch (InterruptedException | ExecutionException e) { cancel = true; ex = e; } } commitTimer.update(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); if (ex != null) { throw new RepoException(ex); } return flushedCount; } }