Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/RevlogStream.java @ 420:6c22bdc0bdfd
Respect long offsets in revlogs
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 22 Mar 2012 22:56:01 +0100 |
parents | c76c57f6b961 |
children | 9c9c442b5f2e |
comparison
equal
deleted
inserted
replaced
419:7f136a3fa671 | 420:6c22bdc0bdfd |
---|---|
64 this.dataAccess = dap; | 64 this.dataAccess = dap; |
65 this.indexFile = indexFile; | 65 this.indexFile = indexFile; |
66 } | 66 } |
67 | 67 |
68 /*package*/ DataAccess getIndexStream() { | 68 /*package*/ DataAccess getIndexStream() { |
69 // XXX may supply a hint that I'll need really few bytes of data (perhaps, at some offset) | 69 // TODO post 1.0 may supply a hint that I'll need really few bytes of data (perhaps, at some offset) |
70 // to avoid mmap files when only few bytes are to be read (i.e. #dataLength()) | 70 // to avoid mmap files when only few bytes are to be read (i.e. #dataLength()) |
71 return dataAccess.create(indexFile); | 71 return dataAccess.create(indexFile); |
72 } | 72 } |
73 | 73 |
74 /*package*/ DataAccess getDataStream() { | 74 /*package*/ DataAccess getDataStream() { |
324 int versionField = da.readInt(); | 324 int versionField = da.readInt(); |
325 da.readInt(); // just to skip next 4 bytes of offset + flags | 325 da.readInt(); // just to skip next 4 bytes of offset + flags |
326 final int INLINEDATA = 1 << 16; | 326 final int INLINEDATA = 1 << 16; |
327 inline = (versionField & INLINEDATA) != 0; | 327 inline = (versionField & INLINEDATA) != 0; |
328 IntVector resBases, resOffsets = null; | 328 IntVector resBases, resOffsets = null; |
329 int entryCountGuess = da.length() / REVLOGV1_RECORD_SIZE; | 329 int entryCountGuess = Internals.ltoi(da.longLength() / REVLOGV1_RECORD_SIZE); |
330 if (inline) { | 330 if (inline) { |
331 entryCountGuess >>>= 2; // pure guess, assume useful data takes 3/4 of total space | 331 entryCountGuess >>>= 2; // pure guess, assume useful data takes 3/4 of total space |
332 resOffsets = new IntVector(entryCountGuess, 5000); | 332 resOffsets = new IntVector(entryCountGuess, 5000); |
333 } | 333 } |
334 resBases = new IntVector(entryCountGuess, 5000); | 334 resBases = new IntVector(entryCountGuess, 5000); |
345 // int parent1Revision = di.readInt(); | 345 // int parent1Revision = di.readInt(); |
346 // int parent2Revision = di.readInt(); | 346 // int parent2Revision = di.readInt(); |
347 // byte[] nodeid = new byte[32]; | 347 // byte[] nodeid = new byte[32]; |
348 resBases.add(baseRevision); | 348 resBases.add(baseRevision); |
349 if (inline) { | 349 if (inline) { |
350 int o = (int) offset; | 350 int o = Internals.ltoi(offset); |
351 if (o != offset) { | 351 if (o != offset) { |
352 // just in case, can't happen, ever, unless HG (or some other bad tool) produces index file | 352 // just in case, can't happen, ever, unless HG (or some other bad tool) produces index file |
353 // with inlined data of size greater than 2 Gb. | 353 // with inlined data of size greater than 2 Gb. |
354 throw new HgBadStateException("Data too big, offset didn't fit to sizeof(int)"); | 354 throw new HgBadStateException("Data too big, offset didn't fit to sizeof(int)"); |
355 } | 355 } |
463 daIndex.seek(getIndexOffsetInt(i)); | 463 daIndex.seek(getIndexOffsetInt(i)); |
464 } | 464 } |
465 long l = daIndex.readLong(); // 0 | 465 long l = daIndex.readLong(); // 0 |
466 long offset = i == 0 ? 0 : (l >>> 16); | 466 long offset = i == 0 ? 0 : (l >>> 16); |
467 @SuppressWarnings("unused") | 467 @SuppressWarnings("unused") |
468 int flags = (int) (l & 0X0FFFF); | 468 int flags = (int) (l & 0x0FFFF); |
469 int compressedLen = daIndex.readInt(); // +8 | 469 int compressedLen = daIndex.readInt(); // +8 |
470 int actualLen = daIndex.readInt(); // +12 | 470 int actualLen = daIndex.readInt(); // +12 |
471 int baseRevision = daIndex.readInt(); // +16 | 471 int baseRevision = daIndex.readInt(); // +16 |
472 int linkRevision = daIndex.readInt(); // +20 | 472 int linkRevision = daIndex.readInt(); // +20 |
473 int parent1Revision = daIndex.readInt(); | 473 int parent1Revision = daIndex.readInt(); |
475 // Hg has 32 bytes here, uses 20 for nodeid, and keeps 12 last bytes empty | 475 // Hg has 32 bytes here, uses 20 for nodeid, and keeps 12 last bytes empty |
476 daIndex.readBytes(nodeidBuf, 0, 20); // +32 | 476 daIndex.readBytes(nodeidBuf, 0, 20); // +32 |
477 daIndex.skip(12); | 477 daIndex.skip(12); |
478 DataAccess userDataAccess = null; | 478 DataAccess userDataAccess = null; |
479 if (needData) { | 479 if (needData) { |
480 int streamOffset; | 480 long streamOffset; |
481 DataAccess streamDataAccess; | 481 DataAccess streamDataAccess; |
482 if (inline) { | 482 if (inline) { |
483 streamDataAccess = daIndex; | 483 streamDataAccess = daIndex; |
484 streamOffset = getIndexOffsetInt(i) + REVLOGV1_RECORD_SIZE; // don't need to do seek as it's actual position in the index stream | 484 streamOffset = getIndexOffsetInt(i) + REVLOGV1_RECORD_SIZE; // don't need to do seek as it's actual position in the index stream |
485 } else { | 485 } else { |
486 streamOffset = (int) offset; | 486 streamOffset = offset; |
487 streamDataAccess = daData; | 487 streamDataAccess = daData; |
488 daData.seek(streamOffset); | 488 daData.longSeek(streamOffset); |
489 } | 489 } |
490 final boolean patchToPrevious = baseRevision != i; // the only way I found to tell if it's a patch | 490 final boolean patchToPrevious = baseRevision != i; // the only way I found to tell if it's a patch |
491 if (streamDataAccess.isEmpty() || compressedLen == 0) { | 491 if (streamDataAccess.isEmpty() || compressedLen == 0) { |
492 userDataAccess = new DataAccess(); // empty | 492 userDataAccess = new DataAccess(); // empty |
493 } else { | 493 } else { |