private WALEntry createEntry(byte[] table, int row, KeyValue.Type type, List<Cell> cells) { byte[] fam = Bytes.equals(table, TABLE_NAME1) ? FAM_NAME1 : FAM_NAME2; byte[] rowBytes = Bytes.toBytes(row); // Just make sure we don't get the same ts for two consecutive rows with // same key try { Thread.sleep(1); } catch (InterruptedException e) { LOG.info("Was interrupted while sleep, meh", e); } final long now = System.currentTimeMillis(); KeyValue kv = null; if (type.getCode() == KeyValue.Type.Put.getCode()) { kv = new KeyValue(rowBytes, fam, fam, now, KeyValue.Type.Put, Bytes.toBytes(row)); } else if (type.getCode() == KeyValue.Type.DeleteColumn.getCode()) { kv = new KeyValue(rowBytes, fam, fam, now, KeyValue.Type.DeleteColumn); } else if (type.getCode() == KeyValue.Type.DeleteFamily.getCode()) { kv = new KeyValue(rowBytes, fam, null, now, KeyValue.Type.DeleteFamily); } WALEntry.Builder builder = WALEntry.newBuilder(); builder.setAssociatedCellCount(1); WALKey.Builder keyBuilder = WALKey.newBuilder(); UUID.Builder uuidBuilder = UUID.newBuilder(); uuidBuilder.setLeastSigBits(HConstants.DEFAULT_CLUSTER_ID.getLeastSignificantBits()); uuidBuilder.setMostSigBits(HConstants.DEFAULT_CLUSTER_ID.getMostSignificantBits()); keyBuilder.setClusterId(uuidBuilder.build()); keyBuilder.setTableName(HBaseZeroCopyByteString.wrap(table)); keyBuilder.setWriteTime(now); keyBuilder.setEncodedRegionName(HBaseZeroCopyByteString.wrap(HConstants.EMPTY_BYTE_ARRAY)); keyBuilder.setLogSequenceNumber(-1); builder.setKey(keyBuilder.build()); cells.add(kv); return builder.build(); }
/** * Transactional version of {@link HTable#delete(Delete)} * * @param transactionState Identifier of the transaction * @see HTable#delete(Delete) * @throws IOException */ public void delete(TransactionState transactionState, Delete delete) throws IOException { final long startTimestamp = transactionState.getStartTimestamp(); boolean issueGet = false; final Put deleteP = new Put(delete.getRow(), startTimestamp); final Get deleteG = new Get(delete.getRow()); Map<byte[], List<KeyValue>> fmap = delete.getFamilyMap(); if (fmap.isEmpty()) { issueGet = true; } for (List<KeyValue> kvl : fmap.values()) { for (KeyValue kv : kvl) { switch (KeyValue.Type.codeToType(kv.getType())) { case DeleteColumn: deleteP.add(kv.getFamily(), kv.getQualifier(), startTimestamp, null); break; case DeleteFamily: deleteG.addFamily(kv.getFamily()); issueGet = true; break; case Delete: if (kv.getTimestamp() == HConstants.LATEST_TIMESTAMP) { deleteP.add(kv.getFamily(), kv.getQualifier(), startTimestamp, null); break; } else { throw new UnsupportedOperationException( "Cannot delete specific versions on Snapshot Isolation."); } } } } if (issueGet) { Result result = this.get(deleteG); for (Entry<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> entryF : result.getMap().entrySet()) { byte[] family = entryF.getKey(); for (Entry<byte[], NavigableMap<Long, byte[]>> entryQ : entryF.getValue().entrySet()) { byte[] qualifier = entryQ.getKey(); deleteP.add(family, qualifier, null); } } } transactionState.addRow( new RowKeyFamily(delete.getRow(), getTableName(), deleteP.getFamilyMap())); put(deleteP); }
@Override public void prePut( final ObserverContext<RegionCoprocessorEnvironment> e, final Put put, final WALEdit edit, final Durability durability) throws IOException { byte[] attribute = put.getAttribute("visibility"); byte[] cf = null; List<Cell> updatedCells = new ArrayList<Cell>(); if (attribute != null) { for (List<? extends Cell> edits : put.getFamilyCellMap().values()) { for (Cell cell : edits) { KeyValue kv = KeyValueUtil.ensureKeyValue(cell); if (cf == null) { cf = kv.getFamily(); } Tag tag = new Tag(TAG_TYPE, attribute); List<Tag> tagList = new ArrayList<Tag>(); tagList.add(tag); KeyValue newKV = new KeyValue( kv.getRow(), 0, kv.getRowLength(), kv.getFamily(), 0, kv.getFamilyLength(), kv.getQualifier(), 0, kv.getQualifierLength(), kv.getTimestamp(), KeyValue.Type.codeToType(kv.getType()), kv.getValue(), 0, kv.getValueLength(), tagList); ((List<Cell>) updatedCells).add(newKV); } } put.getFamilyCellMap().remove(cf); // Update the family map put.getFamilyCellMap().put(cf, updatedCells); } }
/** * Check if the specified KeyValue buffer has been deleted by a previously seen delete. * * @param kv * @param ds * @return True is the specified KeyValue is deleted, false if not */ public boolean isDeleted(final KeyValue kv, final NavigableSet<KeyValue> ds) { if (deletes == null || deletes.isEmpty()) return false; for (KeyValue d : ds) { long kvts = kv.getTimestamp(); long dts = d.getTimestamp(); if (d.isDeleteFamily()) { if (kvts <= dts) return true; continue; } // Check column int ret = Bytes.compareTo( kv.getBuffer(), kv.getQualifierOffset(), kv.getQualifierLength(), d.getBuffer(), d.getQualifierOffset(), d.getQualifierLength()); if (ret <= -1) { // This delete is for an earlier column. continue; } else if (ret >= 1) { // Beyond this kv. break; } // Check Timestamp if (kvts > dts) return false; // Check Type switch (KeyValue.Type.codeToType(d.getType())) { case Delete: return kvts == dts; case DeleteColumn: return true; default: continue; } } return false; }