Search in sources :

Example 41 with ResultSetFuture

use of com.datastax.driver.core.ResultSetFuture in project flink by apache.

the class CassandraTupleWriteAheadSinkTest method testAckLoopExitOnException.

@Test(timeout = 20000)
public void testAckLoopExitOnException() throws Exception {
    final AtomicReference<Runnable> runnableFuture = new AtomicReference<>();
    final ClusterBuilder clusterBuilder = new ClusterBuilder() {

        private static final long serialVersionUID = 4624400760492936756L;

        @Override
        protected Cluster buildCluster(Cluster.Builder builder) {
            try {
                BoundStatement boundStatement = mock(BoundStatement.class);
                when(boundStatement.setDefaultTimestamp(any(long.class))).thenReturn(boundStatement);
                PreparedStatement preparedStatement = mock(PreparedStatement.class);
                when(preparedStatement.bind(Matchers.anyVararg())).thenReturn(boundStatement);
                ResultSetFuture future = mock(ResultSetFuture.class);
                when(future.get()).thenThrow(new RuntimeException("Expected exception."));
                doAnswer(new Answer<Void>() {

                    @Override
                    public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
                        synchronized (runnableFuture) {
                            runnableFuture.set((((Runnable) invocationOnMock.getArguments()[0])));
                            runnableFuture.notifyAll();
                        }
                        return null;
                    }
                }).when(future).addListener(any(Runnable.class), any(Executor.class));
                Session session = mock(Session.class);
                when(session.prepare(anyString())).thenReturn(preparedStatement);
                when(session.executeAsync(any(BoundStatement.class))).thenReturn(future);
                Cluster cluster = mock(Cluster.class);
                when(cluster.connect()).thenReturn(session);
                return cluster;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    };
    // Our asynchronous executor thread
    new Thread(new Runnable() {

        @Override
        public void run() {
            synchronized (runnableFuture) {
                while (runnableFuture.get() == null) {
                    try {
                        runnableFuture.wait();
                    } catch (InterruptedException e) {
                    // ignore interrupts
                    }
                }
            }
            runnableFuture.get().run();
        }
    }).start();
    CheckpointCommitter cc = mock(CheckpointCommitter.class);
    final CassandraTupleWriteAheadSink<Tuple0> sink = new CassandraTupleWriteAheadSink<>("abc", TupleTypeInfo.of(Tuple0.class).createSerializer(new ExecutionConfig()), clusterBuilder, cc);
    OneInputStreamOperatorTestHarness<Tuple0, Tuple0> harness = new OneInputStreamOperatorTestHarness<>(sink);
    harness.getEnvironment().getTaskConfiguration().setBoolean("checkpointing", true);
    harness.setup();
    sink.open();
    // we should leave the loop and return false since we've seen an exception
    assertFalse(sink.sendValues(Collections.singleton(new Tuple0()), 1L, 0L));
    sink.close();
}
Also used : ResultSetFuture(com.datastax.driver.core.ResultSetFuture) ExecutionConfig(org.apache.flink.api.common.ExecutionConfig) CheckpointCommitter(org.apache.flink.streaming.runtime.operators.CheckpointCommitter) Executor(java.util.concurrent.Executor) Cluster(com.datastax.driver.core.Cluster) AtomicReference(java.util.concurrent.atomic.AtomicReference) PreparedStatement(com.datastax.driver.core.PreparedStatement) OneInputStreamOperatorTestHarness(org.apache.flink.streaming.util.OneInputStreamOperatorTestHarness) Tuple0(org.apache.flink.api.java.tuple.Tuple0) InvocationOnMock(org.mockito.invocation.InvocationOnMock) BoundStatement(com.datastax.driver.core.BoundStatement) Session(com.datastax.driver.core.Session) Test(org.junit.Test)

Example 42 with ResultSetFuture

use of com.datastax.driver.core.ResultSetFuture in project flink by apache.

the class CassandraRowWriteAheadSink method sendValues.

@Override
protected boolean sendValues(Iterable<Row> values, long checkpointId, long timestamp) throws Exception {
    final AtomicInteger updatesCount = new AtomicInteger(0);
    final AtomicInteger updatesConfirmed = new AtomicInteger(0);
    final AtomicReference<Throwable> exception = new AtomicReference<>();
    FutureCallback<ResultSet> callback = new FutureCallback<ResultSet>() {

        @Override
        public void onSuccess(ResultSet resultSet) {
            updatesConfirmed.incrementAndGet();
            if (updatesCount.get() > 0) {
                // only set if all updates have been sent
                if (updatesCount.get() == updatesConfirmed.get()) {
                    synchronized (updatesConfirmed) {
                        updatesConfirmed.notifyAll();
                    }
                }
            }
        }

        @Override
        public void onFailure(Throwable throwable) {
            if (exception.compareAndSet(null, throwable)) {
                LOG.error("Error while sending value.", throwable);
                synchronized (updatesConfirmed) {
                    updatesConfirmed.notifyAll();
                }
            }
        }
    };
    // set values for prepared statement
    int updatesSent = 0;
    for (Row value : values) {
        for (int x = 0; x < arity; x++) {
            fields[x] = value.getField(x);
        }
        // insert values and send to cassandra
        BoundStatement s = preparedStatement.bind(fields);
        s.setDefaultTimestamp(timestamp);
        ResultSetFuture result = session.executeAsync(s);
        updatesSent++;
        if (result != null) {
            // add callback to detect errors
            Futures.addCallback(result, callback);
        }
    }
    updatesCount.set(updatesSent);
    synchronized (updatesConfirmed) {
        while (exception.get() == null && updatesSent != updatesConfirmed.get()) {
            updatesConfirmed.wait();
        }
    }
    if (exception.get() != null) {
        LOG.warn("Sending a value failed.", exception.get());
        return false;
    } else {
        return true;
    }
}
Also used : ResultSetFuture(com.datastax.driver.core.ResultSetFuture) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ResultSet(com.datastax.driver.core.ResultSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) Row(org.apache.flink.types.Row) BoundStatement(com.datastax.driver.core.BoundStatement) FutureCallback(com.google.common.util.concurrent.FutureCallback)

Example 43 with ResultSetFuture

use of com.datastax.driver.core.ResultSetFuture in project flink by apache.

the class CassandraTupleWriteAheadSink method sendValues.

@Override
protected boolean sendValues(Iterable<IN> values, long checkpointId, long timestamp) throws Exception {
    final AtomicInteger updatesCount = new AtomicInteger(0);
    final AtomicInteger updatesConfirmed = new AtomicInteger(0);
    final AtomicReference<Throwable> exception = new AtomicReference<>();
    FutureCallback<ResultSet> callback = new FutureCallback<ResultSet>() {

        @Override
        public void onSuccess(ResultSet resultSet) {
            updatesConfirmed.incrementAndGet();
            if (updatesCount.get() > 0) {
                // only set if all updates have been sent
                if (updatesCount.get() == updatesConfirmed.get()) {
                    synchronized (updatesConfirmed) {
                        updatesConfirmed.notifyAll();
                    }
                }
            }
        }

        @Override
        public void onFailure(Throwable throwable) {
            if (exception.compareAndSet(null, throwable)) {
                LOG.error("Error while sending value.", throwable);
                synchronized (updatesConfirmed) {
                    updatesConfirmed.notifyAll();
                }
            }
        }
    };
    // set values for prepared statement
    int updatesSent = 0;
    for (IN value : values) {
        for (int x = 0; x < value.getArity(); x++) {
            fields[x] = value.getField(x);
        }
        // insert values and send to cassandra
        BoundStatement s = preparedStatement.bind(fields);
        s.setDefaultTimestamp(timestamp);
        ResultSetFuture result = session.executeAsync(s);
        updatesSent++;
        if (result != null) {
            // add callback to detect errors
            Futures.addCallback(result, callback);
        }
    }
    updatesCount.set(updatesSent);
    synchronized (updatesConfirmed) {
        while (exception.get() == null && updatesSent != updatesConfirmed.get()) {
            updatesConfirmed.wait();
        }
    }
    if (exception.get() != null) {
        LOG.warn("Sending a value failed.", exception.get());
        return false;
    } else {
        return true;
    }
}
Also used : ResultSetFuture(com.datastax.driver.core.ResultSetFuture) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ResultSet(com.datastax.driver.core.ResultSet) AtomicReference(java.util.concurrent.atomic.AtomicReference) BoundStatement(com.datastax.driver.core.BoundStatement) FutureCallback(com.google.common.util.concurrent.FutureCallback)

Example 44 with ResultSetFuture

use of com.datastax.driver.core.ResultSetFuture in project ignite by apache.

the class CassandraSessionImpl method execute.

/**
 * {@inheritDoc}
 */
@Override
public <R, V> R execute(BatchExecutionAssistant<R, V> assistant, Iterable<? extends V> data) {
    if (data == null || !data.iterator().hasNext())
        return assistant.processedData();
    int attempt = 0;
    String errorMsg = "Failed to execute Cassandra " + assistant.operationName() + " operation";
    Throwable error = new IgniteException(errorMsg);
    RandomSleeper sleeper = newSleeper();
    int dataSize = 0;
    incrementSessionRefs();
    try {
        while (attempt < CQL_EXECUTION_ATTEMPTS_COUNT) {
            if (attempt != 0) {
                log.warning("Trying " + (attempt + 1) + " attempt to execute Cassandra batch " + assistant.operationName() + " operation to process rest " + (dataSize - assistant.processedCount()) + " of " + dataSize + " elements");
            }
            // clean errors info before next communication with Cassandra
            Throwable unknownEx = null;
            Throwable tblAbsenceEx = null;
            Throwable hostsAvailEx = null;
            Throwable prepStatEx = null;
            List<Cache.Entry<Integer, ResultSetFuture>> futResults = new LinkedList<>();
            WrappedPreparedStatement preparedSt = prepareStatement(assistant.getTable(), assistant.getStatement(), assistant.getPersistenceSettings(), assistant.tableExistenceRequired());
            if (preparedSt == null)
                return null;
            WrappedSession ses = null;
            int seqNum = 0;
            for (V obj : data) {
                if (!assistant.alreadyProcessed(seqNum)) {
                    try {
                        ses = session();
                        Statement statement = tuneStatementExecutionOptions(assistant.bindStatement(preparedSt, obj));
                        ResultSetFuture fut = ses.executeAsync(statement);
                        futResults.add(new CacheEntryImpl<>(seqNum, fut));
                    } catch (Throwable e) {
                        if (CassandraHelper.isTableAbsenceError(e)) {
                            // If there are table absence error and it is not required for the operation we can return.
                            if (!assistant.tableExistenceRequired())
                                return assistant.processedData();
                            tblAbsenceEx = e;
                            handleTableAbsenceError(assistant.getTable(), assistant.getPersistenceSettings());
                        } else if (CassandraHelper.isHostsAvailabilityError(e)) {
                            hostsAvailEx = e;
                            // Handle host availability only once.
                            if (hostsAvailEx == null)
                                handleHostsAvailabilityError(ses == null ? 0 : ses.generation, e, attempt, errorMsg);
                        } else if (CassandraHelper.isPreparedStatementClusterError(e)) {
                            prepStatEx = e;
                            handlePreparedStatementClusterError(preparedSt.generation, e);
                            preparedSt = prepareStatement(assistant.getTable(), assistant.getStatement(), assistant.getPersistenceSettings(), assistant.tableExistenceRequired());
                            if (preparedSt == null)
                                return null;
                        } else
                            unknownEx = e;
                    }
                }
                seqNum++;
            }
            dataSize = seqNum;
            // For an error which we don't know how to handle, we will not try next attempts and terminate.
            if (unknownEx != null)
                throw new IgniteException(errorMsg, unknownEx);
            // Remembering any of last errors.
            if (tblAbsenceEx != null)
                error = tblAbsenceEx;
            else if (hostsAvailEx != null)
                error = hostsAvailEx;
            else if (prepStatEx != null)
                error = prepStatEx;
            // Clean errors info before next communication with Cassandra.
            unknownEx = null;
            tblAbsenceEx = null;
            hostsAvailEx = null;
            prepStatEx = null;
            for (Cache.Entry<Integer, ResultSetFuture> futureResult : futResults) {
                try {
                    ResultSet resSet = futureResult.getValue().getUninterruptibly();
                    Row row = resSet != null && resSet.iterator().hasNext() ? resSet.iterator().next() : null;
                    assistant.process(row, futureResult.getKey());
                } catch (Throwable e) {
                    if (CassandraHelper.isTableAbsenceError(e))
                        tblAbsenceEx = e;
                    else if (CassandraHelper.isHostsAvailabilityError(e))
                        hostsAvailEx = e;
                    else if (CassandraHelper.isPreparedStatementClusterError(e))
                        prepStatEx = e;
                    else
                        unknownEx = e;
                }
            }
            // For an error which we don't know how to handle, we will not try next attempts and terminate.
            if (unknownEx != null)
                throw new IgniteException(errorMsg, unknownEx);
            // If there are no errors occurred it means that operation successfully completed and we can return.
            if (tblAbsenceEx == null && hostsAvailEx == null && prepStatEx == null && assistant.processedCount() == dataSize)
                return assistant.processedData();
            if (tblAbsenceEx != null) {
                // If there are table absence error and it is not required for the operation we can return.
                if (!assistant.tableExistenceRequired())
                    return assistant.processedData();
                error = tblAbsenceEx;
                handleTableAbsenceError(assistant.getTable(), assistant.getPersistenceSettings());
            }
            if (hostsAvailEx != null) {
                error = hostsAvailEx;
                handleHostsAvailabilityError(ses.generation, hostsAvailEx, attempt, errorMsg);
            }
            if (prepStatEx != null) {
                error = prepStatEx;
                handlePreparedStatementClusterError(preparedSt.generation, prepStatEx);
            }
            if (!CassandraHelper.isTableAbsenceError(error))
                sleeper.sleep();
            attempt++;
        }
    } catch (Throwable e) {
        error = e;
    } finally {
        decrementSessionRefs();
    }
    errorMsg = "Failed to process " + (dataSize - assistant.processedCount()) + " of " + dataSize + " elements, during " + assistant.operationName() + " operation with Cassandra";
    LT.warn(log, error, errorMsg, false, false);
    throw new IgniteException(errorMsg, error);
}
Also used : ResultSetFuture(com.datastax.driver.core.ResultSetFuture) PreparedStatement(com.datastax.driver.core.PreparedStatement) BoundStatement(com.datastax.driver.core.BoundStatement) BatchStatement(com.datastax.driver.core.BatchStatement) Statement(com.datastax.driver.core.Statement) LinkedList(java.util.LinkedList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) IgniteException(org.apache.ignite.IgniteException) ResultSet(com.datastax.driver.core.ResultSet) RandomSleeper(org.apache.ignite.cache.store.cassandra.common.RandomSleeper) Row(com.datastax.driver.core.Row) Cache(javax.cache.Cache)

Example 45 with ResultSetFuture

use of com.datastax.driver.core.ResultSetFuture in project ignite by apache.

the class CassandraSessionImpl method execute.

/**
 * {@inheritDoc}
 */
@Override
public void execute(BatchLoaderAssistant assistant) {
    int attempt = 0;
    String errorMsg = "Failed to execute Cassandra " + assistant.operationName() + " operation";
    Throwable error = new IgniteException(errorMsg);
    RandomSleeper sleeper = newSleeper();
    incrementSessionRefs();
    try {
        while (attempt < CQL_EXECUTION_ATTEMPTS_COUNT) {
            if (attempt != 0)
                log.warning("Trying " + (attempt + 1) + " attempt to load Ignite cache");
            Statement statement = tuneStatementExecutionOptions(assistant.getStatement());
            WrappedSession ses = null;
            try {
                ses = session();
                ResultSetFuture fut = ses.executeAsync(statement);
                ResultSet resSet = fut.getUninterruptibly();
                if (resSet == null || !resSet.iterator().hasNext())
                    return;
                for (Row row : resSet) assistant.process(row);
                return;
            } catch (Throwable e) {
                error = e;
                if (CassandraHelper.isTableAbsenceError(e))
                    return;
                else if (CassandraHelper.isHostsAvailabilityError(e))
                    handleHostsAvailabilityError(ses == null ? 0 : ses.generation, e, attempt, errorMsg);
                else
                    // For an error which we don't know how to handle, we will not try next attempts and terminate.
                    throw new IgniteException(errorMsg, e);
            }
            sleeper.sleep();
            attempt++;
        }
    } catch (Throwable e) {
        error = e;
    } finally {
        decrementSessionRefs();
    }
    log.error(errorMsg, error);
    throw new IgniteException(errorMsg, error);
}
Also used : ResultSetFuture(com.datastax.driver.core.ResultSetFuture) IgniteException(org.apache.ignite.IgniteException) PreparedStatement(com.datastax.driver.core.PreparedStatement) BoundStatement(com.datastax.driver.core.BoundStatement) BatchStatement(com.datastax.driver.core.BatchStatement) Statement(com.datastax.driver.core.Statement) ResultSet(com.datastax.driver.core.ResultSet) RandomSleeper(org.apache.ignite.cache.store.cassandra.common.RandomSleeper) Row(com.datastax.driver.core.Row)

Aggregations

ResultSetFuture (com.datastax.driver.core.ResultSetFuture)78 Test (org.junit.Test)35 UUID (java.util.UUID)26 ResultSet (com.datastax.driver.core.ResultSet)20 EntityWithCollections (com.datastax.driver.mapping.entity.EntityWithCollections)13 BoundStatement (com.datastax.driver.core.BoundStatement)12 PreparedStatement (com.datastax.driver.core.PreparedStatement)10 ArrayList (java.util.ArrayList)8 Date (java.util.Date)8 Row (com.datastax.driver.core.Row)7 Statement (com.datastax.driver.core.Statement)7 List (java.util.List)6 Session (com.datastax.driver.core.Session)5 Simple (com.datastax.driver.mapping.entity.Simple)5 Cell (com.palantir.atlasdb.keyvalue.api.Cell)5 BigDecimal (java.math.BigDecimal)5 HashSet (java.util.HashSet)5 Result (com.datastax.driver.mapping.Result)4 WriteOptions (com.datastax.driver.mapping.option.WriteOptions)4 Nullable (javax.annotation.Nullable)4