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 / AbstractStateStorage.java
1 package org.jetbrains.jps.incremental.storage;
2
3 import com.intellij.openapi.util.io.FileUtil;
4 import com.intellij.util.io.DataExternalizer;
5 import com.intellij.util.io.KeyDescriptor;
6 import com.intellij.util.io.PersistentHashMap;
7 import org.jetbrains.annotations.NonNls;
8
9 import java.io.DataOutput;
10 import java.io.File;
11 import java.io.IOException;
12 import java.util.Collection;
13 import java.util.Iterator;
14
15 public abstract class AbstractStateStorage<Key, T> {
16   private PersistentHashMap<Key, T> myMap;
17   private final File myBaseFile;
18   private final KeyDescriptor<Key> myKeyDescriptor;
19   private final DataExternalizer<T> myStateExternalizer;
20   protected final Object myDataLock = new Object();
21
22   public AbstractStateStorage(@NonNls File storePath, KeyDescriptor<Key> keyDescriptor, DataExternalizer<T> stateExternalizer) throws Exception {
23     myBaseFile = storePath;
24     myKeyDescriptor = keyDescriptor;
25     myStateExternalizer = stateExternalizer;
26     myMap = createMap(storePath);
27   }
28
29   public void force() {
30     synchronized (myDataLock) {
31       myMap.force();
32     }
33   }
34
35   public void dropMemoryCache() {
36     synchronized (myDataLock) {
37       myMap.dropMemoryCaches();
38     }
39   }
40
41   public void close() throws IOException {
42     synchronized (myDataLock) {
43       myMap.close();
44     }
45   }
46
47   public boolean wipe() {
48     synchronized (myDataLock) {
49       try {
50         myMap.close();
51       }
52       catch (IOException ignored) {
53       }
54       PersistentHashMap.deleteFilesStartingWith(myBaseFile);
55       try {
56         myMap = createMap(myBaseFile);
57       }
58       catch (Exception ignored) {
59         return false;
60       }
61       return true;
62     }
63   }
64
65   public void update(Key key, T state) throws Exception {
66     if (state != null) {
67       synchronized (myDataLock) {
68         myMap.put(key, state);
69       }
70     }
71     else {
72       remove(key);
73     }
74   }
75
76   public void appendData(final Key key, final T data) throws Exception {
77     synchronized (myDataLock) {
78       myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
79         public void append(DataOutput out) throws IOException {
80           myStateExternalizer.save(out, data);
81         }
82       });
83     }
84   }
85
86   public void remove(Key key) throws Exception {
87     synchronized (myDataLock) {
88       myMap.remove(key);
89     }
90   }
91
92   public T getState(Key key) throws Exception {
93     synchronized (myDataLock) {
94       return myMap.get(key);
95     }
96   }
97
98   public Collection<Key> getKeys() throws Exception {
99     synchronized (myDataLock) {
100       return myMap.getAllKeysWithExistingMapping();
101     }
102   }
103
104   public Iterator<Key> getKeysIterator() throws Exception {
105     synchronized (myDataLock) {
106       return myMap.getAllKeysWithExistingMapping().iterator();
107     }
108   }
109
110
111   private PersistentHashMap<Key, T> createMap(final File file) throws Exception {
112     FileUtil.createIfDoesntExist(file);
113     return new PersistentHashMap<Key,T>(file, myKeyDescriptor, myStateExternalizer);
114   }
115
116 }