comparison src/org/tmatesoft/hg/internal/RevlogStream.java @ 366:189dc6dc1c3e

Use exceptions to expose errors reading mercurial data
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 16 Dec 2011 04:43:18 +0100
parents 5f9073eabf06
children 2fadf8695f8a
comparison
equal deleted inserted replaced
365:3572fcb06473 366:189dc6dc1c3e
22 import java.io.File; 22 import java.io.File;
23 import java.io.IOException; 23 import java.io.IOException;
24 import java.util.zip.Inflater; 24 import java.util.zip.Inflater;
25 25
26 import org.tmatesoft.hg.core.HgBadStateException; 26 import org.tmatesoft.hg.core.HgBadStateException;
27 import org.tmatesoft.hg.core.HgException;
27 import org.tmatesoft.hg.core.HgInvalidControlFileException; 28 import org.tmatesoft.hg.core.HgInvalidControlFileException;
28 import org.tmatesoft.hg.core.HgInvalidRevisionException; 29 import org.tmatesoft.hg.core.HgInvalidRevisionException;
29 import org.tmatesoft.hg.core.Nodeid; 30 import org.tmatesoft.hg.core.Nodeid;
30 import org.tmatesoft.hg.repo.HgInternals; 31 import org.tmatesoft.hg.repo.HgInternals;
31 import org.tmatesoft.hg.repo.HgRepository; 32 import org.tmatesoft.hg.repo.HgRepository;
179 180
180 private final int REVLOGV1_RECORD_SIZE = 64; 181 private final int REVLOGV1_RECORD_SIZE = 64;
181 182
182 // should be possible to use TIP, ALL, or -1, -2, -n notation of Hg 183 // should be possible to use TIP, ALL, or -1, -2, -n notation of Hg
183 // ? boolean needsNodeid 184 // ? boolean needsNodeid
184 public void iterate(int start, int end, boolean needData, Inspector inspector) throws HgInvalidRevisionException { 185 public void iterate(int start, int end, boolean needData, Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException /*REVISIT - too general exception*/ {
185 initOutline(); 186 initOutline();
186 final int indexSize = revisionCount(); 187 final int indexSize = revisionCount();
187 if (indexSize == 0) { 188 if (indexSize == 0) {
188 return; 189 return;
189 } 190 }
199 ReaderN1 r = new ReaderN1(needData, inspector); 200 ReaderN1 r = new ReaderN1(needData, inspector);
200 try { 201 try {
201 r.start(end - start + 1); 202 r.start(end - start + 1);
202 r.range(start, end); 203 r.range(start, end);
203 } catch (IOException ex) { 204 } catch (IOException ex) {
204 throw new HgBadStateException(ex); // FIXME need better handling 205 throw new HgInvalidControlFileException(String.format("Failed reading [%d..%d]", start, end), ex, indexFile);
206 } catch (HgInvalidControlFileException ex) {
207 throw ex;
208 } catch (HgException ex) {
209 throw new HgInvalidControlFileException(String.format("Failed reading [%d..%d]", start, end), ex, indexFile);
205 } finally { 210 } finally {
206 r.finish(); 211 r.finish();
207 } 212 }
208 } 213 }
209 214
212 * revisions are of interest. 217 * revisions are of interest.
213 * @param sortedRevisions revisions to walk, in ascending order. 218 * @param sortedRevisions revisions to walk, in ascending order.
214 * @param needData whether inspector needs access to header only 219 * @param needData whether inspector needs access to header only
215 * @param inspector callback to process entries 220 * @param inspector callback to process entries
216 */ 221 */
217 public void iterate(int[] sortedRevisions, boolean needData, Inspector inspector) throws HgInvalidRevisionException { 222 public void iterate(int[] sortedRevisions, boolean needData, Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException /*REVISIT - too general exception*/ {
218 final int indexSize = revisionCount(); 223 final int indexSize = revisionCount();
219 if (indexSize == 0 || sortedRevisions.length == 0) { 224 if (indexSize == 0 || sortedRevisions.length == 0) {
220 return; 225 return;
221 } 226 }
222 if (sortedRevisions[0] > indexSize) { 227 if (sortedRevisions[0] > indexSize) {
243 if (!r.range(sortedRevisions[x], sortedRevisions[i-1])) { 248 if (!r.range(sortedRevisions[x], sortedRevisions[i-1])) {
244 return; 249 return;
245 } 250 }
246 } 251 }
247 } catch (IOException ex) { 252 } catch (IOException ex) {
248 throw new HgBadStateException(ex); // FIXME need better handling 253 final int c = sortedRevisions.length;
254 throw new HgInvalidControlFileException(String.format("Failed reading %d revisions in [%d; %d]",c, sortedRevisions[0], sortedRevisions[c-1]), ex, indexFile);
255 } catch (HgInvalidControlFileException ex) {
256 throw ex;
257 } catch (HgException ex) {
258 final int c = sortedRevisions.length;
259 throw new HgInvalidControlFileException(String.format("Failed reading %d revisions in [%d; %d]",c, sortedRevisions[0], sortedRevisions[c-1]), ex, indexFile);
249 } finally { 260 } finally {
250 r.finish(); 261 r.finish();
251 } 262 }
252 } 263 }
253 264
335 long l = da.readLong(); 346 long l = da.readLong();
336 offset = l >>> 16; 347 offset = l >>> 16;
337 } 348 }
338 } 349 }
339 } catch (IOException ex) { 350 } catch (IOException ex) {
340 ex.printStackTrace(); // log error 351 ex.printStackTrace(); // FIXME, log error is not enough
341 // too bad, no outline then, but don't fail with NPE 352 // too bad, no outline then, but don't fail with NPE
342 baseRevisions = new int[0]; 353 baseRevisions = new int[0];
343 } finally { 354 } finally {
344 da.done(); 355 da.done();
345 } 356 }
346 } 357 }
347 358
348 /** 359 /**
349 * operation with single file open/close and multiple diverse reads. 360 * operation with single file open/close and multiple diverse reads.
350 * XXX initOutline might need similar extraction to keen N1 format knowledge 361 * XXX initOutline might need similar extraction to keep N1 format knowledge
351 */ 362 */
352 class ReaderN1 { 363 class ReaderN1 {
353 private final Inspector inspector; 364 private final Inspector inspector;
354 private final boolean needData; 365 private final boolean needData;
355 private DataAccess daIndex = null, daData = null; 366 private DataAccess daIndex = null, daData = null;
391 daData.done(); 402 daData.done();
392 } 403 }
393 // System.out.printf("applyTime:%d ms, inspectorTime: %d ms\n", applyTime, inspectorTime); // TIMING 404 // System.out.printf("applyTime:%d ms, inspectorTime: %d ms\n", applyTime, inspectorTime); // TIMING
394 } 405 }
395 406
396 public boolean range(int start, int end) throws IOException { 407 public boolean range(int start, int end) throws IOException, HgException {
397 byte[] nodeidBuf = new byte[20]; 408 byte[] nodeidBuf = new byte[20];
398 int i; 409 int i;
399 // it (i.e. replace with i >= start) 410 // it (i.e. replace with i >= start)
400 if (needData && (i = getBaseRevision(start)) < start) { 411 if (needData && (i = getBaseRevision(start)) < start) {
401 // if lastRevisionRead in [baseRevision(start), start) can reuse lastUserData 412 // if lastRevisionRead in [baseRevision(start), start) can reuse lastUserData
515 526
516 public interface Inspector { 527 public interface Inspector {
517 // XXX boolean retVal to indicate whether to continue? 528 // XXX boolean retVal to indicate whether to continue?
518 // TODO specify nodeid and data length, and reuse policy (i.e. if revlog stream doesn't reuse nodeid[] for each call) 529 // TODO specify nodeid and data length, and reuse policy (i.e. if revlog stream doesn't reuse nodeid[] for each call)
519 // implementers shall not invoke DataAccess.done(), it's accomplished by #iterate at appropraite moment 530 // implementers shall not invoke DataAccess.done(), it's accomplished by #iterate at appropraite moment
520 void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[/*20*/] nodeid, DataAccess data); 531 void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[/*20*/] nodeid, DataAccess data) throws HgException;
521 } 532 }
522 } 533 }