68
68
source = newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0x1, 0x2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0xA, /* extra */
70
70
final int usedLength = source.length - 5;
71
71
// new version (-1 = MVV type ID)
72
72
assertEquals(MVV.exactRequiredLength(source, 0, usedLength, 3, 3), usedLength + MVV.overheadLength(1) + 3 - 1);
116
116
final int storedLength = storeVersion(target, 0, vh, source, source.length);
118
118
assertEquals(source.length + MVV.overheadLength(2), storedLength);
119
assertArrayEqualsLen(newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, vh, 0, 3, 0xA, 0xB,
120
0xC), target, storedLength);
119
assertArrayEqualsLen(
120
newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, vh, 0, 3, 0xA, 0xB, 0xC), target,
130
131
final int storedLength = storeVersion(target, targetLength, vh, source, source.length);
132
133
assertEquals(targetLength + source.length + MVV.overheadLength(2), storedLength);
133
assertArrayEqualsLen(newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0xA, 0xB, 0xC, 0, 0, 0, 0, 0, 0, 0, vh,
134
0, 3, 0xD, 0xE, 0xF), target, storedLength);
134
assertArrayEqualsLen(
135
newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0xA, 0xB, 0xC, 0, 0, 0, 0, 0, 0, 0, vh, 0, 3, 0xD,
136
0xE, 0xF), target, storedLength);
145
147
final int storedLength = storeVersion(target, targetLength, vh2, source, source.length);
147
149
assertEquals(targetContentsLength + source.length + MVV.overheadLength(2), storedLength);
148
assertArrayEqualsLen(newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 4, 0xA, 0xB, 0xC, 0xD, 0, 0, 0, 0, 0, 0,
149
0, vh2, 0, 2, 0xE, 0xF), target, storedLength);
150
assertArrayEqualsLen(
151
newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 4, 0xA, 0xB, 0xC, 0xD, 0, 0, 0, 0, 0, 0, 0, vh2, 0, 2,
152
0xE, 0xF), target, storedLength);
158
161
final byte[] source = { 0xD, 0xE, 0xF };
159
162
final int storedLength = storeVersion(target, targetLength, vh2, source, source.length);
160
163
assertTrue("version existed", (storedLength & STORE_EXISTED_MASK) != 0);
161
assertArrayEqualsLen(newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 2, 0x4, 0x5, 0, 0, 0, 0, 0, 0, 0, vh2, 0,
162
3, 0xD, 0xE, 0xF, 0, 0, 0, 0, 0, 0, 0, vh3, 0, 4, 0x6, 0x7, 0x8, 0x9), target, storedLength);
164
assertArrayEqualsLen(
165
newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 2, 0x4, 0x5, 0, 0, 0, 0, 0, 0, 0, vh2, 0, 3, 0xD, 0xE,
166
0xF, 0, 0, 0, 0, 0, 0, 0, vh3, 0, 4, 0x6, 0x7, 0x8, 0x9), target, storedLength);
175
179
storedLength &= STORE_LENGTH_MASK;
176
180
assertEquals(targetLength - 1, storedLength);
177
assertArrayEqualsLen(newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 2, 0x4, 0x5, 0, 0, 0, 0, 0, 0, 0, vh3, 0,
178
4, 0x6, 0x7, 0x8, 0x9, 0, 0, 0, 0, 0, 0, 0, vh2, 0, 2, 0xD, 0xE), target, storedLength);
181
assertArrayEqualsLen(
182
newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 2, 0x4, 0x5, 0, 0, 0, 0, 0, 0, 0, vh3, 0, 4, 0x6, 0x7,
183
0x8, 0x9, 0, 0, 0, 0, 0, 0, 0, vh2, 0, 2, 0xD, 0xE), target, storedLength);
191
196
storedLength &= STORE_LENGTH_MASK;
193
198
assertEquals(targetLength + 1, storedLength);
194
assertArrayEqualsLen(newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 2, 0x4, 0x5, 0, 0, 0, 0, 0, 0, 0, vh3, 0,
195
4, 0x6, 0x7, 0x8, 0x9, 0, 0, 0, 0, 0, 0, 0, vh2, 0, 4, 0xC, 0xD, 0xE, 0xF), target, storedLength);
199
assertArrayEqualsLen(
200
newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, vh1, 0, 2, 0x4, 0x5, 0, 0, 0, 0, 0, 0, 0, vh3, 0, 4, 0x6, 0x7,
201
0x8, 0x9, 0, 0, 0, 0, 0, 0, 0, vh2, 0, 4, 0xC, 0xD, 0xE, 0xF), target, storedLength);
207
213
targetLength = storeVersion(target, targetLength, vh1, source1, source1.length);
208
214
targetLength = storeVersion(target, targetLength, vh2, source2, source2.length);
210
assertArrayEqualsLen(newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xAA, 0xBB, 0xCC, 0, 1,
211
0xA, 0, 0xFF, 0xFF, 0xFF, 0, 0xAA, 0xBB, 0xCC, 0, 1, 0xB), target, targetLength);
216
assertArrayEqualsLen(
217
newArray(TYPE_MVV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xAA, 0xBB, 0xCC, 0, 1, 0xA, 0, 0xFF,
218
0xFF, 0xFF, 0, 0xAA, 0xBB, 0xCC, 0, 1, 0xB), target, targetLength);
398
405
public void visitAndFetchByOffsetPrimordial() throws PersistitException {
399
406
final byte[] source = { 0xA, 0xB, 0xC };
400
TestVisitor visitor = new TestVisitor();
407
final TestVisitor visitor = new TestVisitor();
401
408
MVV.visitAllVersions(visitor, source, 0, source.length);
402
409
assertTrue(visitor.initCalled);
403
410
assertEquals(newVisitorMap(0, 3, 0), visitor.versions);
413
420
0, 2, 0xD, 0xE, 0, 0, 0, 0, 0, 0, 0, 11, 0, 5, 0x1, 0x2, 0x3, 0x4, 0x5, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0,
414
421
0, 0, 0, 0, 0, 0, 0, 9, 0, 1, 0xA, 0, 1, 2, 3, 4, 5, 6, 7, 0, 3, 0xB, 0xC, 0xD, 0, 0, 0, 0, 0, 0, 0, 3,
416
TestVisitor visitor = new TestVisitor();
423
final TestVisitor visitor = new TestVisitor();
417
424
MVV.visitAllVersions(visitor, source, 0, source.length);
418
425
assertTrue(visitor.initCalled);
419
assertEquals(newVisitorMap(1, 3, 11, 2, 2, 24, 11, 5, 36, 127, 0, 51, 9, 1, 61, 283686952306183L, 3, 72, 3, 0,
420
85), visitor.versions);
427
newVisitorMap(1, 3, 11, 2, 2, 24, 11, 5, 36, 127, 0, 51, 9, 1, 61, 283686952306183L, 3, 72, 3, 0, 85),
422
for (Map.Entry<Long, LengthAndOffset> entry : visitor.versions.entrySet()) {
423
int length = (int) entry.getValue().length;
424
int offset = (int) entry.getValue().offset;
425
byte[] target = new byte[length];
430
for (final Map.Entry<Long, LengthAndOffset> entry : visitor.versions.entrySet()) {
431
final int length = (int) entry.getValue().length;
432
final int offset = (int) entry.getValue().offset;
433
final byte[] target = new byte[length];
426
434
MVV.fetchVersionByOffset(source, source.length, offset, target);
427
435
assertArrayEqualsLen(source, offset, target, length);
466
474
final byte fetchtarget[] = new byte[50];
467
475
for (int i = 0; i < VERSION_COUNT; ++i) {
468
int fetchedLen = MVV.fetchVersion(target, targetLength, versions[i], fetchtarget);
476
final int fetchedLen = MVV.fetchVersion(target, targetLength, versions[i], fetchtarget);
469
477
assertEquals(sources[i].length, fetchedLen);
470
478
assertArrayEqualsLen(sources[i], fetchtarget, sources[i].length);
484
492
// Test helper methods
487
private static int writeArray(byte[] array, int... contents) {
495
private static int writeArray(final byte[] array, final int... contents) {
488
496
assert contents.length <= array.length : "Too many values for array";
489
497
for (int i = 0; i < contents.length; ++i) {
490
int value = contents[i];
498
final int value = contents[i];
491
499
assert value >= 0 && value <= 255 : "Value " + value + " out of byte range at index " + i;
492
500
array[i] = (byte) value;
494
502
return contents.length;
497
private static byte[] newArray(int... contents) {
498
byte[] array = new byte[contents.length];
505
private static byte[] newArray(final int... contents) {
506
final byte[] array = new byte[contents.length];
499
507
writeArray(array, contents);
503
private static void assertArrayEqualsLen(byte[] expected, byte[] actual, int length) {
511
private static void assertArrayEqualsLen(final byte[] expected, final byte[] actual, final int length) {
504
512
assertArrayEqualsLen(expected, 0, actual, length);
507
private static void assertArrayEqualsLen(byte[] expected, int offset, byte[] actual, int length) {
515
private static void assertArrayEqualsLen(final byte[] expected, final int offset, final byte[] actual,
508
517
if (expected.length < length) {
509
518
throw new AssertionError(String.format("Expected array is too short: %d vs %d", actual.length, length));
560
public void sawVersion(long version, int offset, int valueLength) {
569
public void sawVersion(final long version, final int offset, final int valueLength) {
561
570
versions.put(version, new LengthAndOffset(valueLength, offset));
565
private static Map<Long, LengthAndOffset> newVisitorMap(long... vals) {
574
private static Map<Long, LengthAndOffset> newVisitorMap(final long... vals) {
566
575
assertTrue("must be (version,length,offset) triplets", (vals.length % 3) == 0);
567
Map<Long, LengthAndOffset> outMap = new TreeMap<Long, LengthAndOffset>();
576
final Map<Long, LengthAndOffset> outMap = new TreeMap<Long, LengthAndOffset>();
568
577
for (int i = 0; i < vals.length; i += 3) {
569
578
outMap.put(vals[i], new LengthAndOffset(vals[i + 1], vals[i + 2]));
577
586
* storeVersion and is likely to get an ArrayIndexOutOfBounds or other
578
587
* undefined behavior if it fails to do so.
580
static int storeVersion(byte[] target, int targetLength, long versionHandle, byte[] source, int sourceLength) {
589
static int storeVersion(final byte[] target, final int targetLength, final long versionHandle, final byte[] source,
590
final int sourceLength) {
581
591
return MVV.storeVersion(target, 0, targetLength, target.length, versionHandle, source, 0, sourceLength);