| 1109 | */ |
| 1110 | private class MockAppend implements Answer<Deferred<Boolean>> { |
| 1111 | @Override |
| 1112 | public Deferred<Boolean> answer(final InvocationOnMock invocation) |
| 1113 | throws Throwable { |
| 1114 | final Object[] args = invocation.getArguments(); |
| 1115 | final AppendRequest append = (AppendRequest)args[0]; |
| 1116 | |
| 1117 | if (exceptions != null) { |
| 1118 | final Pair<RuntimeException, Boolean> ex = exceptions.get(append.key()); |
| 1119 | if (ex != null) { |
| 1120 | if (ex.getValue()) { |
| 1121 | return Deferred.fromError(ex.getKey()); |
| 1122 | } else { |
| 1123 | throw ex.getKey(); |
| 1124 | } |
| 1125 | } |
| 1126 | } |
| 1127 | |
| 1128 | final ByteMap<ByteMap<ByteMap<TreeMap<Long, byte[]>>>> map = |
| 1129 | storage.get(append.table()); |
| 1130 | if (map == null) { |
| 1131 | return Deferred.fromError(new RuntimeException( |
| 1132 | "No such table " + Bytes.pretty(append.table()))); |
| 1133 | } |
| 1134 | |
| 1135 | final ByteMap<ByteMap<TreeMap<Long, byte[]>>> cf = map.get(append.family()); |
| 1136 | if (cf == null) { |
| 1137 | return Deferred.fromError(new RuntimeException( |
| 1138 | "No such CF " + Bytes.pretty(append.table()))); |
| 1139 | } |
| 1140 | |
| 1141 | ByteMap<TreeMap<Long, byte[]>> row = cf.get(append.key()); |
| 1142 | if (row == null) { |
| 1143 | row = new ByteMap<TreeMap<Long, byte[]>>(); |
| 1144 | cf.put(append.key(), row); |
| 1145 | } |
| 1146 | |
| 1147 | for (int i = 0; i < append.qualifiers().length; i++) { |
| 1148 | TreeMap<Long, byte[]> column = row.get(append.qualifiers()[i]); |
| 1149 | if (column == null) { |
| 1150 | column = new TreeMap<Long, byte[]>(Collections.reverseOrder()); |
| 1151 | row.put(append.qualifiers()[i], column); |
| 1152 | } |
| 1153 | |
| 1154 | final byte[] values; |
| 1155 | long column_timestamp = 0; |
| 1156 | /* |
| 1157 | * If there is no Map for Timestamp -> Value, then we create one, add the value with current timestamp |
| 1158 | * else we fetch the top most KeyValue from the column map and append the value in the request with the value |
| 1159 | * already present. The timestamp is also updated. The larger of either current time or the first timestamp from |
| 1160 | * the map is incremented by 1 and used for the updated KeyValue. |
| 1161 | */ |
| 1162 | |
| 1163 | if (column.isEmpty()) { |
| 1164 | values = null; |
| 1165 | column_timestamp = current_timestamp++; |
| 1166 | } else { |
| 1167 | values = column.firstEntry().getValue(); |
| 1168 | column_timestamp = current_timestamp > column.firstKey() ? current_timestamp++ : column.firstKey() + 1; |