drop memory caches only when is dirty
[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       if (myMap.isDirty()) {
38         myMap.dropMemoryCaches();
39       }
40     }
41   }
42
43   public void close() throws IOException {
44     synchronized (myDataLock) {
45       myMap.close();
46     }
47   }
48
49   public boolean wipe() {
50     synchronized (myDataLock) {
51       try {
52         myMap.close();
53       }
54       catch (IOException ignored) {
55       }
56       PersistentHashMap.deleteFilesStartingWith(myBaseFile);
57       try {
58         myMap = createMap(myBaseFile);
59       }
60       catch (Exception ignored) {
61         return false;
62       }
63       return true;
64     }
65   }
66
67   public void update(Key key, T state) throws Exception {
68     if (state != null) {
69       synchronized (myDataLock) {
70         myMap.put(key, state);
71       }
72     }
73     else {
74       remove(key);
75     }
76   }
77
78   public void appendData(final Key key, final T data) throws Exception {
79     synchronized (myDataLock) {
80       myMap.appendData(key, new PersistentHashMap.ValueDataAppender() {
81         public void append(DataOutput out) throws IOException {
82           myStateExternalizer.save(out, data);
83         }
84       });
85     }
86   }
87
88   public void remove(Key key) throws Exception {
89     synchronized (myDataLock) {
90       myMap.remove(key);
91     }
92   }
93
94   public T getState(Key key) throws Exception {
95     synchronized (myDataLock) {
96       return myMap.get(key);
97     }
98   }
99
100   public Collection<Key> getKeys() throws Exception {
101     synchronized (myDataLock) {
102       return myMap.getAllKeysWithExistingMapping();
103     }
104   }
105
106   public Iterator<Key> getKeysIterator() throws Exception {
107     synchronized (myDataLock) {
108       return myMap.getAllKeysWithExistingMapping().iterator();
109     }
110   }
111
112
113   private PersistentHashMap<Key, T> createMap(final File file) throws Exception {
114     FileUtil.createIfDoesntExist(file);
115     return new PersistentHashMap<Key,T>(file, myKeyDescriptor, myStateExternalizer);
116   }
117
118 }