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