Search in sources :

Example 11 with ConditionalMutation

use of org.apache.accumulo.core.data.ConditionalMutation in project accumulo by apache.

the class FaultyConditionalWriter method write.

@Override
public Iterator<Result> write(Iterator<ConditionalMutation> mutations) {
    ArrayList<Result> resultList = new ArrayList<>();
    ArrayList<ConditionalMutation> writes = new ArrayList<>();
    while (mutations.hasNext()) {
        ConditionalMutation cm = mutations.next();
        if (rand.nextDouble() <= up && rand.nextDouble() > wp)
            resultList.add(new Result(Status.UNKNOWN, cm, null));
        else
            writes.add(cm);
    }
    if (writes.size() > 0) {
        Iterator<Result> results = cw.write(writes.iterator());
        while (results.hasNext()) {
            Result result = results.next();
            if (rand.nextDouble() <= up && rand.nextDouble() <= wp)
                result = new Result(Status.UNKNOWN, result.getMutation(), result.getTabletServer());
            resultList.add(result);
        }
    }
    return resultList.iterator();
}
Also used : ConditionalMutation(org.apache.accumulo.core.data.ConditionalMutation) ArrayList(java.util.ArrayList)

Example 12 with ConditionalMutation

use of org.apache.accumulo.core.data.ConditionalMutation in project incubator-rya by apache.

the class PcjTables method updateCardinality.

/**
 * Update the cardinality of a PCJ by a {@code delta}.
 *
 * @param accumuloConn - A connection to the Accumulo that hosts the PCJ table. (not null)
 * @param pcjTableName - The name of the PCJ table that will have its cardinality updated. (not null)
 * @param delta - How much the cardinality will change.
 * @throws PCJStorageException The cardinality could not be updated.
 */
private void updateCardinality(final Connector accumuloConn, final String pcjTableName, final long delta) throws PCJStorageException {
    checkNotNull(accumuloConn);
    checkNotNull(pcjTableName);
    ConditionalWriter conditionalWriter = null;
    try {
        conditionalWriter = accumuloConn.createConditionalWriter(pcjTableName, new ConditionalWriterConfig());
        boolean updated = false;
        while (!updated) {
            // Write the conditional update request to Accumulo.
            final long cardinality = getPcjMetadata(accumuloConn, pcjTableName).getCardinality();
            final ConditionalMutation mutation = makeUpdateCardinalityMutation(cardinality, delta);
            final ConditionalWriter.Result result = conditionalWriter.write(mutation);
            // Interpret the result.
            switch(result.getStatus()) {
                case ACCEPTED:
                    updated = true;
                    break;
                case REJECTED:
                    break;
                case UNKNOWN:
                    // We do not know if the mutation succeeded. At best, we
                    // can hope the metadata hasn't been updated
                    // since we originally fetched it and try again.
                    // Otherwise, continue forwards as if it worked. It's
                    // okay if this number is slightly off.
                    final long newCardinality = getPcjMetadata(accumuloConn, pcjTableName).getCardinality();
                    if (newCardinality != cardinality) {
                        updated = true;
                    }
                    break;
                case VIOLATED:
                    throw new PCJStorageException("The cardinality could not be updated because the commit violated a table constraint.");
                case INVISIBLE_VISIBILITY:
                    throw new PCJStorageException("The condition contains a visibility the updater can not satisfy.");
            }
        }
    } catch (AccumuloException | AccumuloSecurityException | TableNotFoundException e) {
        throw new PCJStorageException("Could not update the cardinality value of the PCJ Table named: " + pcjTableName, e);
    } finally {
        if (conditionalWriter != null) {
            conditionalWriter.close();
        }
    }
}
Also used : ConditionalWriter(org.apache.accumulo.core.client.ConditionalWriter) AccumuloException(org.apache.accumulo.core.client.AccumuloException) TableNotFoundException(org.apache.accumulo.core.client.TableNotFoundException) ConditionalMutation(org.apache.accumulo.core.data.ConditionalMutation) ConditionalWriterConfig(org.apache.accumulo.core.client.ConditionalWriterConfig) AccumuloSecurityException(org.apache.accumulo.core.client.AccumuloSecurityException) PCJStorageException(org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException)

Example 13 with ConditionalMutation

use of org.apache.accumulo.core.data.ConditionalMutation in project incubator-rya by apache.

the class PcjTables method makeUpdateCardinalityMutation.

/**
 * Creates a {@link ConditionalMutation} that only updates the cardinality
 * of the PCJ table if the old value has not changed by the time this mutation
 * is committed to Accumulo.
 *
 * @param current - The current cardinality value.
 * @param delta - How much the cardinality will change.
 * @return The mutation that will perform the conditional update.
 */
private static ConditionalMutation makeUpdateCardinalityMutation(final long current, final long delta) {
    // Try to update the cardinality by the delta.
    final ConditionalMutation mutation = new ConditionalMutation(PCJ_METADATA_ROW_ID);
    final Condition lastCardinalityStillCurrent = new Condition(PCJ_METADATA_FAMILY, PCJ_METADATA_CARDINALITY);
    // Require the old cardinality to be the value we just read.
    final byte[] currentCardinalityBytes = longLexicoder.encode(current);
    lastCardinalityStillCurrent.setValue(currentCardinalityBytes);
    mutation.addCondition(lastCardinalityStillCurrent);
    // If that is the case, then update to the new value.
    final Value newCardinality = new Value(longLexicoder.encode(current + delta));
    mutation.put(PCJ_METADATA_FAMILY, PCJ_METADATA_CARDINALITY, newCardinality);
    return mutation;
}
Also used : Condition(org.apache.accumulo.core.data.Condition) ConditionalMutation(org.apache.accumulo.core.data.ConditionalMutation) Value(org.apache.accumulo.core.data.Value)

Example 14 with ConditionalMutation

use of org.apache.accumulo.core.data.ConditionalMutation in project accumulo-examples by apache.

the class ARS method cancel.

public void cancel(String what, String when, String who) throws Exception {
    String row = what + ":" + when;
    // its important to use an isolated scanner so that only whole mutations are seen
    try (ConditionalWriter cwriter = conn.createConditionalWriter(rTable, new ConditionalWriterConfig());
        Scanner scanner = new IsolatedScanner(conn.createScanner(rTable, Authorizations.EMPTY))) {
        while (true) {
            scanner.setRange(new Range(row));
            int seq = -1;
            String reservation = null;
            for (Entry<Key, Value> entry : scanner) {
                String cf = entry.getKey().getColumnFamilyData().toString();
                String cq = entry.getKey().getColumnQualifierData().toString();
                String val = entry.getValue().toString();
                if (cf.equals("tx") && cq.equals("seq")) {
                    seq = Integer.parseInt(val);
                } else if (cf.equals("res") && val.equals(who)) {
                    reservation = cq;
                }
            }
            if (reservation != null) {
                ConditionalMutation update = new ConditionalMutation(row, new Condition("tx", "seq").setValue(seq + ""));
                update.putDelete("res", reservation);
                update.put("tx", "seq", (seq + 1) + "");
                Status status = cwriter.write(update).getStatus();
                switch(status) {
                    case ACCEPTED:
                        // successfully canceled reservation
                        return;
                    case REJECTED:
                    case UNKNOWN:
                        // EXCERCISE exponential back-off could be used here
                        break;
                    default:
                        throw new RuntimeException("Unexpected status " + status);
                }
            } else {
                // not reserved, nothing to do
                break;
            }
        }
    }
}
Also used : Condition(org.apache.accumulo.core.data.Condition) Status(org.apache.accumulo.core.client.ConditionalWriter.Status) IsolatedScanner(org.apache.accumulo.core.client.IsolatedScanner) Scanner(org.apache.accumulo.core.client.Scanner) Range(org.apache.accumulo.core.data.Range) ConditionalWriter(org.apache.accumulo.core.client.ConditionalWriter) ConditionalMutation(org.apache.accumulo.core.data.ConditionalMutation) Value(org.apache.accumulo.core.data.Value) ConditionalWriterConfig(org.apache.accumulo.core.client.ConditionalWriterConfig) IsolatedScanner(org.apache.accumulo.core.client.IsolatedScanner) Key(org.apache.accumulo.core.data.Key)

Example 15 with ConditionalMutation

use of org.apache.accumulo.core.data.ConditionalMutation in project accumulo-examples by apache.

the class ARS method reserve.

public ReservationResult reserve(String what, String when, String who) throws Exception {
    String row = what + ":" + when;
    // EXCERCISE This code assumes there is no reservation and tries to create one. If a reservation exist then the update will fail. This is a good strategy
    // when it is expected there are usually no reservations. Could modify the code to scan first.
    // The following mutation requires that the column tx:seq does not exist and will fail if it does.
    ConditionalMutation update = new ConditionalMutation(row, new Condition("tx", "seq"));
    update.put("tx", "seq", "0");
    update.put("res", String.format("%04d", 0), who);
    ReservationResult result = ReservationResult.RESERVED;
    // it is important to use an isolated scanner so that only whole mutations are seen
    try (ConditionalWriter cwriter = conn.createConditionalWriter(rTable, new ConditionalWriterConfig());
        Scanner scanner = new IsolatedScanner(conn.createScanner(rTable, Authorizations.EMPTY))) {
        while (true) {
            Status status = cwriter.write(update).getStatus();
            switch(status) {
                case ACCEPTED:
                    return result;
                case REJECTED:
                case UNKNOWN:
                    // read the row and decide what to do
                    break;
                default:
                    throw new RuntimeException("Unexpected status " + status);
            }
            // EXCERCISE in the case of many threads trying to reserve a slot, this approach of immediately retrying is inefficient. Exponential back-off is good
            // general solution to solve contention problems like this. However in this particular case, exponential back-off could penalize the earliest threads
            // that attempted to make a reservation by putting them later in the list. A more complex solution could involve having independent sub-queues within
            // the row that approximately maintain arrival order and use exponential back off to fairly merge the sub-queues into the main queue.
            scanner.setRange(new Range(row));
            int seq = -1;
            int maxReservation = -1;
            for (Entry<Key, Value> entry : scanner) {
                String cf = entry.getKey().getColumnFamilyData().toString();
                String cq = entry.getKey().getColumnQualifierData().toString();
                String val = entry.getValue().toString();
                if (cf.equals("tx") && cq.equals("seq")) {
                    seq = Integer.parseInt(val);
                } else if (cf.equals("res")) {
                    // data differently in Accumulo so that finding the reserver could be done quickly.
                    if (val.equals(who))
                        if (maxReservation == -1)
                            // already have the first reservation
                            return ReservationResult.RESERVED;
                        else
                            // already on wait list
                            return ReservationResult.WAIT_LISTED;
                    // EXCERCISE the way this code finds the max reservation is very inefficient.... it would be better if it did not have to scan the entire row.
                    // One possibility is to just use the sequence number. Could also consider sorting the data in another way and/or using an iterator.
                    maxReservation = Integer.parseInt(cq);
                }
            }
            Condition condition = new Condition("tx", "seq");
            if (seq >= 0)
                // only expect a seq # if one was seen
                condition.setValue(seq + "");
            update = new ConditionalMutation(row, condition);
            update.put("tx", "seq", (seq + 1) + "");
            update.put("res", String.format("%04d", maxReservation + 1), who);
            // EXCERCISE if set capacity is implemented, then result should take capacity into account
            if (maxReservation == -1)
                // if successful, will be first reservation
                result = ReservationResult.RESERVED;
            else
                result = ReservationResult.WAIT_LISTED;
        }
    }
}
Also used : Condition(org.apache.accumulo.core.data.Condition) Status(org.apache.accumulo.core.client.ConditionalWriter.Status) IsolatedScanner(org.apache.accumulo.core.client.IsolatedScanner) Scanner(org.apache.accumulo.core.client.Scanner) Range(org.apache.accumulo.core.data.Range) ConditionalWriter(org.apache.accumulo.core.client.ConditionalWriter) ConditionalMutation(org.apache.accumulo.core.data.ConditionalMutation) Value(org.apache.accumulo.core.data.Value) ConditionalWriterConfig(org.apache.accumulo.core.client.ConditionalWriterConfig) IsolatedScanner(org.apache.accumulo.core.client.IsolatedScanner) Key(org.apache.accumulo.core.data.Key)

Aggregations

ConditionalMutation (org.apache.accumulo.core.data.ConditionalMutation)26 ConditionalWriter (org.apache.accumulo.core.client.ConditionalWriter)24 ConditionalWriterConfig (org.apache.accumulo.core.client.ConditionalWriterConfig)22 Condition (org.apache.accumulo.core.data.Condition)21 Connector (org.apache.accumulo.core.client.Connector)19 Test (org.junit.Test)18 Result (org.apache.accumulo.core.client.ConditionalWriter.Result)12 IsolatedScanner (org.apache.accumulo.core.client.IsolatedScanner)12 Scanner (org.apache.accumulo.core.client.Scanner)12 Value (org.apache.accumulo.core.data.Value)11 Status (org.apache.accumulo.core.client.ConditionalWriter.Status)10 Key (org.apache.accumulo.core.data.Key)9 Range (org.apache.accumulo.core.data.Range)8 Text (org.apache.hadoop.io.Text)8 AccumuloException (org.apache.accumulo.core.client.AccumuloException)7 Authorizations (org.apache.accumulo.core.security.Authorizations)7 ArrayList (java.util.ArrayList)6 AccumuloSecurityException (org.apache.accumulo.core.client.AccumuloSecurityException)6 IteratorSetting (org.apache.accumulo.core.client.IteratorSetting)5 TableNotFoundException (org.apache.accumulo.core.client.TableNotFoundException)5