Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/RevlogStream.java @ 606:5daa42067e7c
Avoid mmap files when only few bytes are to be read
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 07 May 2013 14:16:35 +0200 |
parents | cc7b0c4dc993 |
children | 66f1cc23b906 |
comparison
equal
deleted
inserted
replaced
605:c56edf42be64 | 606:5daa42067e7c |
---|---|
75 public RevlogStream(DataAccessProvider dap, File indexFile) { | 75 public RevlogStream(DataAccessProvider dap, File indexFile) { |
76 this.dataAccess = dap; | 76 this.dataAccess = dap; |
77 this.indexFile = indexFile; | 77 this.indexFile = indexFile; |
78 } | 78 } |
79 | 79 |
80 /*package*/ DataAccess getIndexStream() { | 80 /** |
81 // FIXME [1.1] must supply a hint that I'll need really few bytes of data (perhaps, at some offset) | 81 * @param shortRead pass <code>true</code> to indicate intention to read few revisions only (as opposed to reading most of/complete revlog) |
82 // to avoid mmap files when only few bytes are to be read (i.e. #dataLength()) | 82 * @return never <code>null</code>, empty {@link DataAccess} if no stream is available |
83 return dataAccess.createReader(indexFile); | 83 */ |
84 /*package*/ DataAccess getIndexStream(boolean shortRead) { | |
85 // shortRead hint helps to avoid mmap files when only | |
86 // few bytes are to be read (i.e. #dataLength()) | |
87 return dataAccess.createReader(indexFile, shortRead); | |
84 } | 88 } |
85 | 89 |
86 /*package*/ DataAccess getDataStream() { | 90 /*package*/ DataAccess getDataStream() { |
87 return dataAccess.createReader(getDataFile()); | 91 return dataAccess.createReader(getDataFile(), false); |
88 } | 92 } |
89 | 93 |
90 /*package*/ DataSerializer getIndexStreamWriter() { | 94 /*package*/ DataSerializer getIndexStreamWriter() { |
91 return dataAccess.createWriter(indexFile, true); | 95 return dataAccess.createWriter(indexFile, true); |
92 } | 96 } |
145 */ | 149 */ |
146 public int dataLength(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { | 150 public int dataLength(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { |
147 // XXX in fact, use of iterate() instead of this implementation may be quite reasonable. | 151 // XXX in fact, use of iterate() instead of this implementation may be quite reasonable. |
148 // | 152 // |
149 revisionIndex = checkRevisionIndex(revisionIndex); | 153 revisionIndex = checkRevisionIndex(revisionIndex); |
150 DataAccess daIndex = getIndexStream(); | 154 DataAccess daIndex = getIndexStream(true); |
151 try { | 155 try { |
152 int recordOffset = getIndexOffsetInt(revisionIndex); | 156 int recordOffset = getIndexOffsetInt(revisionIndex); |
153 daIndex.seek(recordOffset + 12); // 6+2+4 | 157 daIndex.seek(recordOffset + 12); // 6+2+4 |
154 int actualLen = daIndex.readInt(); | 158 int actualLen = daIndex.readInt(); |
155 return actualLen; | 159 return actualLen; |
166 * @throws HgInvalidControlFileException if attempt to read index file failed | 170 * @throws HgInvalidControlFileException if attempt to read index file failed |
167 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog | 171 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog |
168 */ | 172 */ |
169 public byte[] nodeid(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { | 173 public byte[] nodeid(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { |
170 revisionIndex = checkRevisionIndex(revisionIndex); | 174 revisionIndex = checkRevisionIndex(revisionIndex); |
171 DataAccess daIndex = getIndexStream(); | 175 DataAccess daIndex = getIndexStream(true); |
172 try { | 176 try { |
173 int recordOffset = getIndexOffsetInt(revisionIndex); | 177 int recordOffset = getIndexOffsetInt(revisionIndex); |
174 daIndex.seek(recordOffset + 32); | 178 daIndex.seek(recordOffset + 32); |
175 byte[] rv = new byte[20]; | 179 byte[] rv = new byte[20]; |
176 daIndex.readBytes(rv, 0, 20); | 180 daIndex.readBytes(rv, 0, 20); |
188 * @throws HgInvalidControlFileException if attempt to read index file failed | 192 * @throws HgInvalidControlFileException if attempt to read index file failed |
189 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog | 193 * @throws HgInvalidRevisionException if revisionIndex argument doesn't represent a valid record in the revlog |
190 */ | 194 */ |
191 public int linkRevision(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { | 195 public int linkRevision(int revisionIndex) throws HgInvalidControlFileException, HgInvalidRevisionException { |
192 revisionIndex = checkRevisionIndex(revisionIndex); | 196 revisionIndex = checkRevisionIndex(revisionIndex); |
193 DataAccess daIndex = getIndexStream(); | 197 DataAccess daIndex = getIndexStream(true); |
194 try { | 198 try { |
195 int recordOffset = getIndexOffsetInt(revisionIndex); | 199 int recordOffset = getIndexOffsetInt(revisionIndex); |
196 daIndex.seek(recordOffset + 20); | 200 daIndex.seek(recordOffset + 20); |
197 int linkRev = daIndex.readInt(); | 201 int linkRev = daIndex.readInt(); |
198 return linkRev; | 202 return linkRev; |
224 * @throws HgInvalidControlFileException if attempt to read index file failed | 228 * @throws HgInvalidControlFileException if attempt to read index file failed |
225 */ | 229 */ |
226 public int findRevisionIndex(Nodeid nodeid) throws HgInvalidControlFileException { | 230 public int findRevisionIndex(Nodeid nodeid) throws HgInvalidControlFileException { |
227 // XXX this one may be implemented with iterate() once there's mechanism to stop iterations | 231 // XXX this one may be implemented with iterate() once there's mechanism to stop iterations |
228 final int indexSize = revisionCount(); | 232 final int indexSize = revisionCount(); |
229 DataAccess daIndex = getIndexStream(); | 233 DataAccess daIndex = getIndexStream(false); |
230 try { | 234 try { |
231 byte[] nodeidBuf = new byte[20]; | 235 byte[] nodeidBuf = new byte[20]; |
232 for (int i = 0; i < indexSize; i++) { | 236 for (int i = 0; i < indexSize; i++) { |
233 daIndex.skip(8); | 237 daIndex.skip(8); |
234 int compressedLen = daIndex.readInt(); | 238 int compressedLen = daIndex.readInt(); |
253 */ | 257 */ |
254 public long newEntryOffset() { | 258 public long newEntryOffset() { |
255 if (revisionCount() == 0) { | 259 if (revisionCount() == 0) { |
256 return 0; | 260 return 0; |
257 } | 261 } |
258 DataAccess daIndex = getIndexStream(); | 262 DataAccess daIndex = getIndexStream(true); |
259 int lastRev = revisionCount() - 1; | 263 int lastRev = revisionCount() - 1; |
260 try { | 264 try { |
261 int recordOffset = getIndexOffsetInt(lastRev); | 265 int recordOffset = getIndexOffsetInt(lastRev); |
262 daIndex.seek(recordOffset); | 266 daIndex.seek(recordOffset); |
263 long value = daIndex.readLong(); | 267 long value = daIndex.readLong(); |
419 | 423 |
420 private void initOutline() throws HgInvalidControlFileException { | 424 private void initOutline() throws HgInvalidControlFileException { |
421 if (outlineCached()) { | 425 if (outlineCached()) { |
422 return; | 426 return; |
423 } | 427 } |
424 DataAccess da = getIndexStream(); | 428 DataAccess da = getIndexStream(false); |
425 try { | 429 try { |
426 if (da.isEmpty()) { | 430 if (da.isEmpty()) { |
427 // do not fail with exception if stream is empty, it's likely intentional | 431 // do not fail with exception if stream is empty, it's likely intentional |
428 baseRevisions = new int[0]; | 432 baseRevisions = new int[0]; |
429 // empty revlog, likely to be populated, indicate we start with a single file | 433 // empty revlog, likely to be populated, indicate we start with a single file |
549 inspector = insp; | 553 inspector = insp; |
550 mergePatches = usePatchMerge; | 554 mergePatches = usePatchMerge; |
551 } | 555 } |
552 | 556 |
553 public void start(int totalWork, CachedRevision cachedRevision) { | 557 public void start(int totalWork, CachedRevision cachedRevision) { |
554 daIndex = getIndexStream(); | 558 daIndex = getIndexStream(totalWork <= 10); |
555 if (needData && !inline) { | 559 if (needData && !inline) { |
556 daData = getDataStream(); | 560 daData = getDataStream(); |
557 } | 561 } |
558 lifecycleListener = Adaptable.Factory.getAdapter(inspector, Lifecycle.class, null); | 562 lifecycleListener = Adaptable.Factory.getAdapter(inspector, Lifecycle.class, null); |
559 if (lifecycleListener != null) { | 563 if (lifecycleListener != null) { |