Parses a column from storage, orders and drops newer duplicate data points. The parsing will return both a Cell collection for debugging and add the cells to concatenated qualifier and value arrays in the compacted data point format so that the results can be merged with other non-append columns or
(final TSDB tsdb, final KeyValue kv)
| 116 | * or we were unable to parse the value. |
| 117 | */ |
| 118 | public final Collection<Cell> parseKeyValue(final TSDB tsdb, final KeyValue kv) { |
| 119 | if (kv.qualifier().length != 3 || kv.qualifier()[0] != APPEND_COLUMN_PREFIX) { |
| 120 | // it's really not an issue if the offset is not 0, maybe in the future |
| 121 | // we'll support appends at different offsets. |
| 122 | throw new IllegalArgumentException("Can not parse cell, it is not " + |
| 123 | " an appended cell. It has a different qualifier " + |
| 124 | Bytes.pretty(kv.qualifier()) + ", row key " + Bytes.pretty(kv.key())); |
| 125 | } |
| 126 | final boolean repair = tsdb.getConfig().repair_appends(); |
| 127 | final long base_time; |
| 128 | try { |
| 129 | base_time = Internal.baseTime(tsdb, kv.key()); |
| 130 | } catch (ArrayIndexOutOfBoundsException oob) { |
| 131 | throw new IllegalDataException("Corrupted value: invalid row key: " + kv, |
| 132 | oob); |
| 133 | } |
| 134 | |
| 135 | int val_idx = 0; |
| 136 | int val_length = 0; |
| 137 | int qual_length = 0; |
| 138 | int last_delta = -1; // Time delta, extracted from the qualifier. |
| 139 | |
| 140 | final Map<Integer, Internal.Cell> deltas = new TreeMap<Integer, Cell>(); |
| 141 | boolean has_duplicates = false; |
| 142 | boolean out_of_order = false; |
| 143 | boolean needs_repair = false; |
| 144 | |
| 145 | try { |
| 146 | while (val_idx < kv.value().length) { |
| 147 | byte[] q = Internal.extractQualifier(kv.value(), val_idx); |
| 148 | System.arraycopy(kv.value(), val_idx, q, 0, q.length); |
| 149 | val_idx=val_idx + q.length; |
| 150 | |
| 151 | int vlen = Internal.getValueLengthFromQualifier(q, 0); |
| 152 | byte[] v = new byte[vlen]; |
| 153 | System.arraycopy(kv.value(), val_idx, v, 0, vlen); |
| 154 | val_idx += vlen; |
| 155 | int delta = Internal.getOffsetFromQualifier(q); |
| 156 | |
| 157 | final Cell duplicate = deltas.get(delta); |
| 158 | if (duplicate != null) { |
| 159 | // This is a duplicate cell, skip it |
| 160 | has_duplicates = true; |
| 161 | qual_length -= duplicate.qualifier.length; |
| 162 | val_length -= duplicate.value.length; |
| 163 | } |
| 164 | |
| 165 | qual_length += q.length; |
| 166 | val_length += vlen; |
| 167 | final Cell cell = new Cell(q, v); |
| 168 | deltas.put(delta, cell); |
| 169 | |
| 170 | if (!out_of_order) { |
| 171 | // Data points needs to be sorted if we find at least one out of |
| 172 | // order data |
| 173 | if (delta <= last_delta) { |
| 174 | out_of_order = true; |
| 175 | } |