public void finishBackupExclusiveOperation() throws IOException { LOG.debug("Finish backup exclusive operation"); try (Table table = connection.getTable(tableName)) { Put put = createPutForStopBackupSession(); if (!table.checkAndMutate(ACTIVE_SESSION_ROW, SESSIONS_FAMILY).qualifier(ACTIVE_SESSION_COL) .ifEquals(ACTIVE_SESSION_YES).thenPut(put)) { throw new IOException("There is no active backup exclusive operation"); } } }
/** * Exclusive operations are: create, delete, merge * @throws IOException if a table operation fails or an active backup exclusive operation is * already underway */ public void startBackupExclusiveOperation() throws IOException { LOG.debug("Start new backup exclusive operation"); try (Table table = connection.getTable(tableName)) { Put put = createPutForStartBackupSession(); // First try to put if row does not exist if (!table.checkAndMutate(ACTIVE_SESSION_ROW, SESSIONS_FAMILY).qualifier(ACTIVE_SESSION_COL) .ifNotExists().thenPut(put)) { // Row exists, try to put if value == ACTIVE_SESSION_NO if (!table.checkAndMutate(ACTIVE_SESSION_ROW, SESSIONS_FAMILY).qualifier(ACTIVE_SESSION_COL) .ifEquals(ACTIVE_SESSION_NO).thenPut(put)) { throw new ExclusiveOperationException(); } } } }
@Override public Object run() throws Exception { Put p = new Put(TEST_ROW); p.addColumn(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1)); try(Connection conn = ConnectionFactory.createConnection(conf); Table t = conn.getTable(TEST_TABLE)) { t.checkAndMutate(TEST_ROW, TEST_FAMILY).qualifier(TEST_QUALIFIER) .ifEquals(Bytes.toBytes("test_value")).thenPut(p); } return null; } };
@Override public Object run() throws Exception { Delete d = new Delete(TEST_ROW); d.addFamily(TEST_FAMILY); try(Connection conn = ConnectionFactory.createConnection(conf); Table t = conn.getTable(TEST_TABLE)) { t.checkAndMutate(TEST_ROW, TEST_FAMILY).qualifier(TEST_QUALIFIER) .ifEquals(Bytes.toBytes("test_value")).thenDelete(d); } return null; } };
@Test(expected = InvalidMutationDurabilityException.class) public void testCheckWithMutateToTableNeedReplicate() throws Exception { tableNeedReplicate.checkAndMutate(Bytes.toBytes("row"), CF).qualifier(CQ).ifNotExists() .thenPut(newPutWithSkipWAL()); } }
@Test public void testCheckWithMutateToTableNotReplicate() throws Exception { tableNotReplicate.checkAndMutate(Bytes.toBytes("row"), CF).qualifier(CQ).ifNotExists() .thenPut(newPutWithSkipWAL()); }
@Override public Object run() throws Exception { try { if (table == null) { table = connection.getTable(tableName); } if (m instanceof Increment) { table.increment((Increment) m); } else if (m instanceof Append) { table.append((Append) m); } else if (m instanceof Put) { table.checkAndMutate(row, cf).qualifier(q).ifEquals(v).thenPut((Put) m); } else if (m instanceof Delete) { table.checkAndMutate(row, cf).qualifier(q).ifEquals(v).thenDelete((Delete) m); } else { throw new IllegalArgumentException("unsupported mutation " + m.getClass().getSimpleName()); } totalOpTimeMs.addAndGet(System.currentTimeMillis() - start); } catch (IOException e) { recordFailure(m, keyBase, start, e); } return null; } }
@Test public void testCheckAndDelete() throws IOException { final byte [] value1 = Bytes.toBytes("aaaa"); Table table = TEST_UTIL.createTable(TableName.valueOf(name.getMethodName()), FAMILY); Put put = new Put(ROW); put.addColumn(FAMILY, QUALIFIER, value1); table.put(put); Delete delete = new Delete(ROW); delete.addColumns(FAMILY, QUALIFIER); boolean ok = table.checkAndMutate(ROW, FAMILY).qualifier(QUALIFIER) .ifEquals(value1).thenDelete(delete); assertTrue(ok); }
@Test public void testCheckAndPutCount() throws Exception { byte[] valOne = Bytes.toBytes("Value"); byte[] valTwo = Bytes.toBytes("ValueTwo"); byte[] valThree = Bytes.toBytes("ValueThree"); Put p = new Put(row); p.addColumn(cf, qualifier, valOne); table.put(p); Put pTwo = new Put(row); pTwo.addColumn(cf, qualifier, valTwo); table.checkAndMutate(row, cf).qualifier(qualifier).ifEquals(valOne).thenPut(pTwo); Put pThree = new Put(row); pThree.addColumn(cf, qualifier, valThree); table.checkAndMutate(row, cf).qualifier(qualifier).ifEquals(valOne).thenPut(pThree); metricsRegionServer.getRegionServerWrapper().forceRecompute(); assertCounter("checkMutateFailedCount", 1); assertCounter("checkMutatePassedCount", 1); }
@Override public Void run() throws Exception { try (Connection connection = ConnectionFactory.createConnection(conf)) { try (Table t = connection.getTable(TEST_TABLE.getTableName())) { Delete d = new Delete(row); d.addColumn(TEST_FAMILY1, q1, 120); t.checkAndMutate(row, TEST_FAMILY1).qualifier(q1).ifEquals(value).thenDelete(d); } } return null; } });
@Override public Void run() throws Exception { try (Connection connection = ConnectionFactory.createConnection(conf)) { try (Table t = connection.getTable(TEST_TABLE.getTableName())) { Delete d = new Delete(TEST_ROW1); d.addColumns(TEST_FAMILY1, TEST_Q1, 120); t.checkAndMutate(TEST_ROW1, TEST_FAMILY1).qualifier(TEST_Q1) .ifEquals(ZERO).thenDelete(d); } } return null; } });
@Test public void testCheckAndPutHooks() throws IOException { final TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + "." + name.getMethodName()); try (Table table = util.createTable(tableName, new byte[][] { A, B, C })) { Put p = new Put(Bytes.toBytes(0)); p.addColumn(A, A, A); table.put(p); p = new Put(Bytes.toBytes(0)); p.addColumn(A, A, A); verifyMethodResult(SimpleRegionObserver.class, new String[] { "hadPreCheckAndPut", "hadPreCheckAndPutAfterRowLock", "hadPostCheckAndPut" }, tableName, new Boolean[] { false, false, false }); table.checkAndMutate(Bytes.toBytes(0), A).qualifier(A).ifEquals(A).thenPut(p); verifyMethodResult(SimpleRegionObserver.class, new String[] { "hadPreCheckAndPut", "hadPreCheckAndPutAfterRowLock", "hadPostCheckAndPut" }, tableName, new Boolean[] { true, true, true }); } finally { util.deleteTable(tableName); } }
@Override boolean testRow(final int i) throws IOException { final byte [] bytes = format(i); // checkAndXXX tests operate on only a single value // Put a known value so when we go to check it, it is there. Put put = new Put(bytes); put.addColumn(FAMILY_ZERO, getQualifier(), bytes); this.table.put(put); this.table.checkAndMutate(bytes, FAMILY_ZERO).qualifier(getQualifier()) .ifEquals(bytes).thenPut(put); return true; } }
@Override public boolean checkAndMutate(ByteBuffer table, ByteBuffer row, ByteBuffer family, ByteBuffer qualifier, TCompareOp compareOp, ByteBuffer value, TRowMutations rowMutations) throws TIOError, TException { checkReadOnlyMode(); try (final Table htable = getTable(table)) { return htable.checkAndMutate(byteBufferToByteArray(row), byteBufferToByteArray(family)) .qualifier(byteBufferToByteArray(qualifier)) .ifMatches(compareOpFromThrift(compareOp), byteBufferToByteArray(value)) .thenMutate(rowMutationsFromThrift(rowMutations)); } catch (IOException e) { throw getTIOError(e); } }
@Test public void testCheckAndDeleteHooks() throws IOException { final TableName tableName = TableName.valueOf(TEST_TABLE.getNameAsString() + "." + name.getMethodName()); Table table = util.createTable(tableName, new byte[][] { A, B, C }); try { Put p = new Put(Bytes.toBytes(0)); p.addColumn(A, A, A); table.put(p); Delete d = new Delete(Bytes.toBytes(0)); table.delete(d); verifyMethodResult( SimpleRegionObserver.class, new String[] { "hadPreCheckAndDelete", "hadPreCheckAndDeleteAfterRowLock", "hadPostCheckAndDelete" }, tableName, new Boolean[] { false, false, false }); table.checkAndMutate(Bytes.toBytes(0), A).qualifier(A).ifEquals(A).thenDelete(d); verifyMethodResult( SimpleRegionObserver.class, new String[] { "hadPreCheckAndDelete", "hadPreCheckAndDeleteAfterRowLock", "hadPostCheckAndDelete" }, tableName, new Boolean[] { true, true, true }); } finally { util.deleteTable(tableName); table.close(); } }
@Override boolean testRow(final int i) throws IOException { final byte [] bytes = format(i); // checkAndXXX tests operate on only a single value // Put a known value so when we go to check it, it is there. Put put = new Put(bytes); put.addColumn(FAMILY_ZERO, getQualifier(), bytes); this.table.put(put); Delete delete = new Delete(put.getRow()); delete.addColumn(FAMILY_ZERO, getQualifier()); this.table.checkAndMutate(bytes, FAMILY_ZERO).qualifier(getQualifier()) .ifEquals(bytes).thenDelete(delete); return true; } }
@Override public Void run() throws Exception { try (Connection connection = ConnectionFactory.createConnection(conf)) { try (Table t = connection.getTable(TEST_TABLE.getTableName())) { Delete d = new Delete(row); d.addColumns(TEST_FAMILY1, TEST_Q1); t.checkAndMutate(row, TEST_FAMILY1).qualifier(TEST_Q1).ifEquals(value).thenDelete(d); fail(user.getShortName() + " should not be allowed to do checkAndDelete"); } catch (Exception e) { } } return null; } });
@Override boolean testRow(final int i) throws IOException { final byte [] bytes = format(i); // checkAndXXX tests operate on only a single value // Put a known value so when we go to check it, it is there. Put put = new Put(bytes); put.addColumn(FAMILY_ZERO, getQualifier(), bytes); this.table.put(put); RowMutations mutations = new RowMutations(bytes); mutations.add(put); this.table.checkAndMutate(bytes, FAMILY_ZERO).qualifier(getQualifier()) .ifEquals(bytes).thenMutate(mutations); return true; } }
@Override public boolean checkAndPut(ByteBuffer table, ByteBuffer row, ByteBuffer family, ByteBuffer qualifier, ByteBuffer value, TPut put) throws TIOError, TException { checkReadOnlyMode(); Table htable = getTable(table); try { Table.CheckAndMutateBuilder builder = htable.checkAndMutate(byteBufferToByteArray(row), byteBufferToByteArray(family)).qualifier(byteBufferToByteArray(qualifier)); if (value == null) { return builder.ifNotExists().thenPut(putFromThrift(put)); } else { return builder.ifEquals(byteBufferToByteArray(value)).thenPut(putFromThrift(put)); } } catch (IOException e) { throw getTIOError(e); } finally { closeTable(htable); } }
@Override public boolean checkAndDelete(ByteBuffer table, ByteBuffer row, ByteBuffer family, ByteBuffer qualifier, ByteBuffer value, TDelete deleteSingle) throws TIOError, TException { checkReadOnlyMode(); Table htable = getTable(table); try { Table.CheckAndMutateBuilder mutateBuilder = htable.checkAndMutate(byteBufferToByteArray(row), byteBufferToByteArray(family)) .qualifier(byteBufferToByteArray(qualifier)); if (value == null) { return mutateBuilder.ifNotExists().thenDelete(deleteFromThrift(deleteSingle)); } else { return mutateBuilder.ifEquals(byteBufferToByteArray(value)) .thenDelete(deleteFromThrift(deleteSingle)); } } catch (IOException e) { throw getTIOError(e); } finally { closeTable(htable); } }