speedup: call force() only at the end of the build, between chunk builds drop only...
[idea/community.git] / jps / jps-builders / src / org / jetbrains / jps / incremental / storage / BuildDataManager.java
1 package org.jetbrains.jps.incremental.storage;
2
3 import com.intellij.openapi.diagnostic.Logger;
4 import com.intellij.openapi.util.io.FileUtil;
5 import org.jetbrains.annotations.Nullable;
6 import org.jetbrains.ether.dependencyView.Mappings;
7 import org.jetbrains.jps.incremental.Paths;
8
9 import java.io.File;
10 import java.io.IOException;
11 import java.util.HashMap;
12 import java.util.Map;
13
14 /**
15  * @author Eugene Zhuravlev
16  *         Date: 10/7/11
17  */
18 public class BuildDataManager {
19   private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
20   private static final String SRC_TO_OUTPUTS_STORAGE = "src-out";
21   private static final String SRC_TO_FORM_STORAGE = "src-form";
22   private static final String MAPPINGS_STORAGE = "mappings";
23   private final String myProjectName;
24
25   private final Object mySourceToOutputLock = new Object();
26   private final Map<String, SourceToOutputMapping> myProductionSourceToOutputs = new HashMap<String, SourceToOutputMapping>();
27   private final Map<String, SourceToOutputMapping> myTestSourceToOutputs = new HashMap<String, SourceToOutputMapping>();
28
29   private final SourceToFormMapping mySrcToFormMap;
30   private final Mappings myMappings;
31
32   public BuildDataManager(String projectName, final boolean useMemoryTempCaches) throws Exception {
33     myProjectName = projectName;
34     mySrcToFormMap = new SourceToFormMapping(new File(getSourceToFormsRoot(), "data"));
35     myMappings = new Mappings(getMappingsRoot(), useMemoryTempCaches);
36   }
37
38   public SourceToOutputMapping getSourceToOutputMap(String moduleName, boolean testSources) throws Exception {
39     final Map<String, SourceToOutputMapping> storageMap = testSources? myTestSourceToOutputs : myProductionSourceToOutputs;
40     SourceToOutputMapping mapping;
41     synchronized (mySourceToOutputLock) {
42       mapping = storageMap.get(moduleName);
43       if (mapping == null) {
44         mapping = new SourceToOutputMapping(new File(getSourceToOutputRoot(moduleName, testSources), "data"));
45         storageMap.put(moduleName, mapping);
46       }
47     }
48     return mapping;
49   }
50
51   public SourceToFormMapping getSourceToFormMap() {
52     return mySrcToFormMap;
53   }
54
55   public Mappings getMappings() {
56     return myMappings;
57   }
58
59   public void clean() throws IOException {
60     try {
61       synchronized (mySourceToOutputLock) {
62         try {
63           closeOutputToSourceStorages();
64         }
65         finally {
66           FileUtil.delete(getSourceToOutputsRoot());
67         }
68       }
69     }
70     finally {
71       try {
72         wipeStorage(getSourceToFormsRoot(), mySrcToFormMap);
73       }
74       finally {
75         final Mappings mappings = myMappings;
76         if (mappings != null) {
77           synchronized (mappings) {
78             mappings.clean();
79           }
80         }
81         else {
82           FileUtil.delete(getMappingsRoot());
83         }
84       }
85     }
86   }
87
88   public void flush(boolean memoryCachesOnly) {
89     synchronized (mySourceToOutputLock) {
90       for (Map.Entry<String, SourceToOutputMapping> entry : myProductionSourceToOutputs.entrySet()) {
91         final SourceToOutputMapping mapping = entry.getValue();
92         if (memoryCachesOnly) {
93           mapping.dropMemoryCache();
94         }
95         else {
96           mapping.force();
97         }
98       }
99       for (Map.Entry<String, SourceToOutputMapping> entry : myTestSourceToOutputs.entrySet()) {
100         final SourceToOutputMapping mapping = entry.getValue();
101         if (memoryCachesOnly) {
102           mapping.dropMemoryCache();
103         }
104         else {
105           mapping.force();
106         }
107       }
108     }
109     if (memoryCachesOnly) {
110       mySrcToFormMap.dropMemoryCache();
111     }
112     else {
113       mySrcToFormMap.force();
114     }
115     final Mappings mappings = myMappings;
116     if (mappings != null) {
117       synchronized (mappings) {
118         mappings.flush(memoryCachesOnly);
119       }
120     }
121   }
122
123   public void close() throws IOException {
124     try {
125       synchronized (mySourceToOutputLock) {
126         closeOutputToSourceStorages();
127       }
128     }
129     finally {
130       try {
131         closeStorage(mySrcToFormMap);
132       }
133       finally {
134         final Mappings mappings = myMappings;
135         if (mappings != null) {
136           synchronized (mappings) {
137             try {
138               mappings.close();
139             }
140             catch (RuntimeException e) {
141               final Throwable cause = e.getCause();
142               if (cause instanceof IOException) {
143                 throw ((IOException)cause);
144               }
145               throw e;
146             }
147           }
148         }
149       }
150     }
151   }
152
153   private void closeOutputToSourceStorages() throws IOException {
154     IOException ex = null;
155     try {
156       for (Map.Entry<String, SourceToOutputMapping> entry : myProductionSourceToOutputs.entrySet()) {
157         try {
158           closeStorage(entry.getValue());
159         }
160         catch (IOException e) {
161           if (ex != null) {
162             ex = e;
163           }
164         }
165       }
166       for (Map.Entry<String, SourceToOutputMapping> entry : myTestSourceToOutputs.entrySet()) {
167         try {
168           closeStorage(entry.getValue());
169         }
170         catch (IOException e) {
171           if (ex != null) {
172             ex = e;
173           }
174         }
175       }
176     }
177     finally {
178       myProductionSourceToOutputs.clear();
179       myTestSourceToOutputs.clear();
180     }
181     if (ex != null) {
182       throw ex;
183     }
184   }
185
186   public File getSourceToFormsRoot() {
187     return new File(Paths.getDataStorageRoot(myProjectName), SRC_TO_FORM_STORAGE);
188   }
189
190   public File getSourceToOutputRoot(String moduleName, boolean forTests) {
191     return new File(getSourceToOutputsRoot(), (forTests? "tests" : "production") + "/" + moduleName);
192   }
193
194   private File getSourceToOutputsRoot() {
195     return new File(Paths.getDataStorageRoot(myProjectName), SRC_TO_OUTPUTS_STORAGE);
196   }
197
198   public File getMappingsRoot() {
199     return new File(Paths.getDataStorageRoot(myProjectName), MAPPINGS_STORAGE);
200   }
201
202   private static void wipeStorage(File root, @Nullable AbstractStateStorage<?, ?> storage) {
203     if (storage != null) {
204       synchronized (storage) {
205         storage.wipe();
206       }
207     }
208     else {
209       FileUtil.delete(root);
210     }
211   }
212
213   private static void closeStorage(@Nullable AbstractStateStorage<?, ?> storage) throws IOException {
214     if (storage != null) {
215       synchronized (storage) {
216         storage.close();
217       }
218     }
219   }
220 }