Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 312:f9f3e9b67ccc
Facilitate cancellation and progress reporting in changelog and manifest iterations
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Tue, 27 Sep 2011 05:29:12 +0200 |
| parents | 85b8efde5586 |
| children | c1e3c18fd2f2 |
comparison
equal
deleted
inserted
replaced
| 311:b9592e21176a | 312:f9f3e9b67ccc |
|---|---|
| 26 import org.tmatesoft.hg.core.HgBadStateException; | 26 import org.tmatesoft.hg.core.HgBadStateException; |
| 27 import org.tmatesoft.hg.core.Nodeid; | 27 import org.tmatesoft.hg.core.Nodeid; |
| 28 import org.tmatesoft.hg.internal.DataAccess; | 28 import org.tmatesoft.hg.internal.DataAccess; |
| 29 import org.tmatesoft.hg.internal.DigestHelper; | 29 import org.tmatesoft.hg.internal.DigestHelper; |
| 30 import org.tmatesoft.hg.internal.Experimental; | 30 import org.tmatesoft.hg.internal.Experimental; |
| 31 import org.tmatesoft.hg.internal.IterateControlMediator; | |
| 31 import org.tmatesoft.hg.internal.Lifecycle; | 32 import org.tmatesoft.hg.internal.Lifecycle; |
| 32 import org.tmatesoft.hg.internal.Pool2; | 33 import org.tmatesoft.hg.internal.Pool2; |
| 33 import org.tmatesoft.hg.internal.RevlogStream; | 34 import org.tmatesoft.hg.internal.RevlogStream; |
| 35 import org.tmatesoft.hg.util.CancelSupport; | |
| 34 import org.tmatesoft.hg.util.Path; | 36 import org.tmatesoft.hg.util.Path; |
| 37 import org.tmatesoft.hg.util.ProgressSupport; | |
| 35 | 38 |
| 36 | 39 |
| 37 /** | 40 /** |
| 38 * | 41 * |
| 39 * @author Artem Tikhomirov | 42 * @author Artem Tikhomirov |
| 275 } | 278 } |
| 276 return result; | 279 return result; |
| 277 } | 280 } |
| 278 } | 281 } |
| 279 | 282 |
| 280 private static class ManifestParser implements RevlogStream.Inspector { | 283 private static class ManifestParser implements RevlogStream.Inspector, Lifecycle { |
| 281 private boolean gtg = true; // good to go | |
| 282 private final Inspector inspector; | 284 private final Inspector inspector; |
| 283 private final Inspector2 inspector2; | 285 private final Inspector2 inspector2; |
| 284 private Pool2<Nodeid> nodeidPool, thisRevPool; | 286 private Pool2<Nodeid> nodeidPool, thisRevPool; |
| 285 private final Pool2<PathProxy> fnamePool; | 287 private final Pool2<PathProxy> fnamePool; |
| 286 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool | 288 private byte[] nodeidLookupBuffer = new byte[20]; // get reassigned each time new Nodeid is added to pool |
| 289 private final ProgressSupport progressHelper; | |
| 290 private IterateControlMediator iterateControl; | |
| 287 | 291 |
| 288 public ManifestParser(Inspector delegate) { | 292 public ManifestParser(Inspector delegate) { |
| 289 assert delegate != null; | 293 assert delegate != null; |
| 290 inspector = delegate; | 294 inspector = delegate; |
| 291 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null; | 295 inspector2 = delegate instanceof Inspector2 ? (Inspector2) delegate : null; |
| 292 nodeidPool = new Pool2<Nodeid>(); | 296 nodeidPool = new Pool2<Nodeid>(); |
| 293 fnamePool = new Pool2<PathProxy>(); | 297 fnamePool = new Pool2<PathProxy>(); |
| 294 thisRevPool = new Pool2<Nodeid>(); | 298 thisRevPool = new Pool2<Nodeid>(); |
| 299 progressHelper = ProgressSupport.Factory.get(delegate); | |
| 295 } | 300 } |
| 296 | 301 |
| 297 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { | 302 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { |
| 298 if (!gtg) { | |
| 299 return; | |
| 300 } | |
| 301 try { | 303 try { |
| 302 gtg = gtg && inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision); | 304 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { |
| 305 iterateControl.stop(); | |
| 306 return; | |
| 307 } | |
| 303 Path fname = null; | 308 Path fname = null; |
| 304 Flags flags = null; | 309 Flags flags = null; |
| 305 Nodeid nid = null; | 310 Nodeid nid = null; |
| 306 int i; | 311 int i; |
| 307 byte[] data = da.byteArray(); | 312 byte[] data = da.byteArray(); |
| 308 for (i = 0; gtg && i < actualLen; i++) { | 313 for (i = 0; i < actualLen; i++) { |
| 309 int x = i; | 314 int x = i; |
| 310 for( ; data[i] != '\n' && i < actualLen; i++) { | 315 for( ; data[i] != '\n' && i < actualLen; i++) { |
| 311 if (fname == null && data[i] == 0) { | 316 if (fname == null && data[i] == 0) { |
| 312 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x)); | 317 PathProxy px = fnamePool.unify(new PathProxy(data, x, i - x)); |
| 313 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit | 318 // if (cached = fnamePool.unify(px))== px then cacheMiss, else cacheHit |
| 335 // for cpython 0..10k, there are 4361062 flag checks, and there's only 1 unique flag | 340 // for cpython 0..10k, there are 4361062 flag checks, and there's only 1 unique flag |
| 336 flags = Flags.parse(data, x + nodeidLen, i-x-nodeidLen); | 341 flags = Flags.parse(data, x + nodeidLen, i-x-nodeidLen); |
| 337 } else { | 342 } else { |
| 338 flags = null; | 343 flags = null; |
| 339 } | 344 } |
| 345 boolean good2go; | |
| 340 if (inspector2 == null) { | 346 if (inspector2 == null) { |
| 341 String flagString = flags == null ? null : flags.nativeString(); | 347 String flagString = flags == null ? null : flags.nativeString(); |
| 342 gtg = inspector.next(nid, fname.toString(), flagString); | 348 good2go = inspector.next(nid, fname.toString(), flagString); |
| 343 } else { | 349 } else { |
| 344 gtg = inspector2.next(nid, fname, flags); | 350 good2go = inspector2.next(nid, fname, flags); |
| 351 } | |
| 352 if (!good2go) { | |
| 353 iterateControl.stop(); | |
| 354 return; | |
| 345 } | 355 } |
| 346 } | 356 } |
| 347 nid = null; | 357 nid = null; |
| 348 fname = null; | 358 fname = null; |
| 349 flags = null; | 359 flags = null; |
| 350 } | 360 } |
| 351 gtg = gtg && inspector.end(revisionNumber); | 361 if (!inspector.end(revisionNumber)) { |
| 362 iterateControl.stop(); | |
| 363 return; | |
| 364 } | |
| 352 // | 365 // |
| 353 // keep only actual file revisions, found at this version | 366 // keep only actual file revisions, found at this version |
| 354 // (next manifest is likely to refer to most of them, although in specific cases | 367 // (next manifest is likely to refer to most of them, although in specific cases |
| 355 // like commit in another branch a lot may be useless) | 368 // like commit in another branch a lot may be useless) |
| 356 nodeidPool.clear(); | 369 nodeidPool.clear(); |
| 357 Pool2<Nodeid> t = nodeidPool; | 370 Pool2<Nodeid> t = nodeidPool; |
| 358 nodeidPool = thisRevPool; | 371 nodeidPool = thisRevPool; |
| 359 thisRevPool = t; | 372 thisRevPool = t; |
| 373 progressHelper.worked(1); | |
| 360 } catch (IOException ex) { | 374 } catch (IOException ex) { |
| 361 throw new HgBadStateException(ex); | 375 throw new HgBadStateException(ex); |
| 362 } | 376 } |
| 377 } | |
| 378 | |
| 379 public void start(int count, Callback callback, Object token) { | |
| 380 CancelSupport cs = CancelSupport.Factory.get(inspector, null); | |
| 381 iterateControl = new IterateControlMediator(cs, callback); | |
| 382 progressHelper.start(count); | |
| 383 } | |
| 384 | |
| 385 public void finish(Object token) { | |
| 386 progressHelper.done(); | |
| 363 } | 387 } |
| 364 } | 388 } |
| 365 | 389 |
| 366 private static class RevisionMapper implements RevlogStream.Inspector, Lifecycle { | 390 private static class RevisionMapper implements RevlogStream.Inspector, Lifecycle { |
| 367 | 391 |
