1 // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 package org.rocksdb.util; 3 4 import org.rocksdb.RocksDBException; 5 import org.rocksdb.WriteBatch; 6 7 import java.util.ArrayList; 8 import java.util.Arrays; 9 import java.util.List; 10 import java.util.Objects; 11 12 /** 13 * A simple WriteBatch Handler which adds a record 14 * of each event that it receives to a list 15 */ 16 public class CapturingWriteBatchHandler extends WriteBatch.Handler { 17 18 private final List<Event> events = new ArrayList<>(); 19 20 /** 21 * Returns a copy of the current events list 22 * 23 * @return a list of the events which have happened upto now 24 */ getEvents()25 public List<Event> getEvents() { 26 return new ArrayList<>(events); 27 } 28 29 @Override put(final int columnFamilyId, final byte[] key, final byte[] value)30 public void put(final int columnFamilyId, final byte[] key, 31 final byte[] value) { 32 events.add(new Event(Action.PUT, columnFamilyId, key, value)); 33 } 34 35 @Override put(final byte[] key, final byte[] value)36 public void put(final byte[] key, final byte[] value) { 37 events.add(new Event(Action.PUT, key, value)); 38 } 39 40 @Override merge(final int columnFamilyId, final byte[] key, final byte[] value)41 public void merge(final int columnFamilyId, final byte[] key, 42 final byte[] value) { 43 events.add(new Event(Action.MERGE, columnFamilyId, key, value)); 44 } 45 46 @Override merge(final byte[] key, final byte[] value)47 public void merge(final byte[] key, final byte[] value) { 48 events.add(new Event(Action.MERGE, key, value)); 49 } 50 51 @Override delete(final int columnFamilyId, final byte[] key)52 public void delete(final int columnFamilyId, final byte[] key) { 53 events.add(new Event(Action.DELETE, columnFamilyId, key, (byte[])null)); 54 } 55 56 @Override delete(final byte[] key)57 public void delete(final byte[] key) { 58 events.add(new Event(Action.DELETE, key, (byte[])null)); 59 } 60 61 @Override singleDelete(final int columnFamilyId, final byte[] key)62 public void singleDelete(final int columnFamilyId, final byte[] key) { 63 events.add(new Event(Action.SINGLE_DELETE, 64 columnFamilyId, key, (byte[])null)); 65 } 66 67 @Override singleDelete(final byte[] key)68 public void singleDelete(final byte[] key) { 69 events.add(new Event(Action.SINGLE_DELETE, key, (byte[])null)); 70 } 71 72 @Override deleteRange(final int columnFamilyId, final byte[] beginKey, final byte[] endKey)73 public void deleteRange(final int columnFamilyId, final byte[] beginKey, 74 final byte[] endKey) { 75 events.add(new Event(Action.DELETE_RANGE, columnFamilyId, beginKey, 76 endKey)); 77 } 78 79 @Override deleteRange(final byte[] beginKey, final byte[] endKey)80 public void deleteRange(final byte[] beginKey, final byte[] endKey) { 81 events.add(new Event(Action.DELETE_RANGE, beginKey, endKey)); 82 } 83 84 @Override logData(final byte[] blob)85 public void logData(final byte[] blob) { 86 events.add(new Event(Action.LOG, (byte[])null, blob)); 87 } 88 89 @Override putBlobIndex(final int columnFamilyId, final byte[] key, final byte[] value)90 public void putBlobIndex(final int columnFamilyId, final byte[] key, 91 final byte[] value) { 92 events.add(new Event(Action.PUT_BLOB_INDEX, key, value)); 93 } 94 95 @Override markBeginPrepare()96 public void markBeginPrepare() throws RocksDBException { 97 events.add(new Event(Action.MARK_BEGIN_PREPARE, (byte[])null, 98 (byte[])null)); 99 } 100 101 @Override markEndPrepare(final byte[] xid)102 public void markEndPrepare(final byte[] xid) throws RocksDBException { 103 events.add(new Event(Action.MARK_END_PREPARE, (byte[])null, 104 (byte[])null)); 105 } 106 107 @Override markNoop(final boolean emptyBatch)108 public void markNoop(final boolean emptyBatch) throws RocksDBException { 109 events.add(new Event(Action.MARK_NOOP, (byte[])null, (byte[])null)); 110 } 111 112 @Override markRollback(final byte[] xid)113 public void markRollback(final byte[] xid) throws RocksDBException { 114 events.add(new Event(Action.MARK_ROLLBACK, (byte[])null, (byte[])null)); 115 } 116 117 @Override markCommit(final byte[] xid)118 public void markCommit(final byte[] xid) throws RocksDBException { 119 events.add(new Event(Action.MARK_COMMIT, (byte[])null, (byte[])null)); 120 } 121 122 public static class Event { 123 public final Action action; 124 public final int columnFamilyId; 125 public final byte[] key; 126 public final byte[] value; 127 Event(final Action action, final byte[] key, final byte[] value)128 public Event(final Action action, final byte[] key, final byte[] value) { 129 this(action, 0, key, value); 130 } 131 Event(final Action action, final int columnFamilyId, final byte[] key, final byte[] value)132 public Event(final Action action, final int columnFamilyId, final byte[] key, 133 final byte[] value) { 134 this.action = action; 135 this.columnFamilyId = columnFamilyId; 136 this.key = key; 137 this.value = value; 138 } 139 140 @Override equals(final Object o)141 public boolean equals(final Object o) { 142 if (this == o) { 143 return true; 144 } 145 if (o == null || getClass() != o.getClass()) { 146 return false; 147 } 148 final Event event = (Event) o; 149 return columnFamilyId == event.columnFamilyId && 150 action == event.action && 151 ((key == null && event.key == null) 152 || Arrays.equals(key, event.key)) && 153 ((value == null && event.value == null) 154 || Arrays.equals(value, event.value)); 155 } 156 157 @Override hashCode()158 public int hashCode() { 159 160 return Objects.hash(action, columnFamilyId, key, value); 161 } 162 } 163 164 /** 165 * Enumeration of Write Batch 166 * event actions 167 */ 168 public enum Action { 169 PUT, MERGE, DELETE, SINGLE_DELETE, DELETE_RANGE, LOG, PUT_BLOB_INDEX, 170 MARK_BEGIN_PREPARE, MARK_END_PREPARE, MARK_NOOP, MARK_COMMIT, 171 MARK_ROLLBACK } 172 } 173