2 * Copyright (C) 2006 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License, version 2.1, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org
.spearce
.egit
.core
.project
;
20 import java
.io
.IOException
;
21 import java
.util
.ArrayList
;
22 import java
.util
.Collection
;
23 import java
.util
.HashSet
;
24 import java
.util
.Iterator
;
25 import java
.util
.LinkedHashMap
;
29 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
30 import org
.eclipse
.core
.runtime
.IStatus
;
31 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
32 import org
.eclipse
.core
.runtime
.Status
;
33 import org
.eclipse
.core
.runtime
.jobs
.ISchedulingRule
;
34 import org
.eclipse
.core
.runtime
.jobs
.Job
;
35 import org
.eclipse
.core
.runtime
.jobs
.MultiRule
;
36 import org
.eclipse
.osgi
.util
.NLS
;
37 import org
.spearce
.egit
.core
.Activator
;
38 import org
.spearce
.egit
.core
.CoreText
;
39 import org
.spearce
.jgit
.lib
.FileTreeEntry
;
40 import org
.spearce
.jgit
.lib
.ObjectWriter
;
41 import org
.spearce
.jgit
.lib
.Tree
;
42 import org
.spearce
.jgit
.lib
.TreeEntry
;
44 public class CheckpointJob
extends Job
{
45 private static final Object EXISTS
= new Object();
47 private static final int MB
= 1024 * 1024;
49 private final Set blobQueue
;
51 private final Collection blobRules
;
53 private final Map treeQueue
;
55 private final ObjectWriter ow
;
57 private final RepositoryMapping rm
;
61 private int objectCnt
;
63 public CheckpointJob(final RepositoryMapping m
) {
64 super(NLS
.bind(CoreText
.CheckpointJob_name
, m
.getContainer()
66 setPriority(Job
.LONG
);
68 blobQueue
= new HashSet();
69 blobRules
= new ArrayList();
70 treeQueue
= new LinkedHashMap();
71 ow
= new ObjectWriter(m
.getRepository());
75 public void scheduleIfNecessary() {
76 if (!blobQueue
.isEmpty() || !treeQueue
.isEmpty()) {
77 final ISchedulingRule
[] r
= new ISchedulingRule
[blobRules
.size()];
79 setRule(MultiRule
.combine(r
));
85 public void enqueue(final ISchedulingRule rule
, final File s
,
86 final FileTreeEntry e
) {
87 if (rule
!= null && e
.isModified() && s
.canRead()) {
88 if (blobQueue
.add(new QueuedBlob(s
, e
))) {
90 byteCnt
+= s
.length();
96 public void enqueue(final Tree t
) {
98 if (treeQueue
.put(t
, EXISTS
) == null) {
104 protected IStatus
run(IProgressMonitor monitor
) {
105 if (monitor
== null) {
106 monitor
= new NullProgressMonitor();
110 monitor
.beginTask(CoreText
.CheckpointJob_writing
, (int) (byteCnt
/ MB
)
114 boolean wroteSomething
;
116 monitor
.subTask(CoreText
.CheckpointJob_writingBlobs
);
117 i
= blobQueue
.iterator();
118 while (i
.hasNext()) {
119 if (monitor
.isCanceled()) {
121 return Status
.CANCEL_STATUS
;
124 final QueuedBlob q
= (QueuedBlob
) i
.next();
125 synchronized (q
.ent
) {
126 if (q
.ent
.isModified() && q
.src
.canRead()) {
127 q
.ent
.setId(ow
.writeBlob(q
.src
));
130 monitor
.worked((int) (q
.src
.length() / MB
) + 1);
133 monitor
.subTask(CoreText
.CheckpointJob_writingTrees
);
134 wroteSomething
= true;
135 while (!treeQueue
.isEmpty() && wroteSomething
) {
136 i
= treeQueue
.keySet().iterator();
137 wroteSomething
= false;
138 PICK_TREE
: while (i
.hasNext()) {
139 if (monitor
.isCanceled()) {
141 return Status
.CANCEL_STATUS
;
144 final Tree t
= (Tree
) i
.next();
146 if (t
.isModified()) {
147 final TreeEntry
[] m
= t
.members();
148 for (int p
= 0; p
< m
.length
; p
++) {
149 if (m
[p
].isModified()) {
153 t
.setId(ow
.writeTree(t
));
156 wroteSomething
= true;
163 if (!rm
.getCacheTree().isModified()) {
164 monitor
.subTask(CoreText
.CheckpointJob_writingRef
);
165 trace("writing ref");
168 trace("tree is still dirty; ref can't be written");
171 } catch (IOException ioe
) {
172 return Activator
.error(CoreText
.CheckpointJob_failed
, ioe
)
179 return Status
.OK_STATUS
;
182 private void trace(final String m
) {
183 Activator
.trace("(CheckpointJob " + rm
.getContainer().getFullPath()
187 private static class QueuedBlob
{
190 final FileTreeEntry ent
;
192 QueuedBlob(final File s
, final FileTreeEntry e
) {
197 public int hashCode() {
198 return ent
.hashCode();
201 public boolean equals(final Object o
) {
202 return ent
.equals(((QueuedBlob
) o
).ent
);