Mercurial > jhg
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 } | 
