new compiler api: persistent state splitted to source and output state
[idea/community.git] / java / compiler / impl / src / com / intellij / compiler / impl / newApi / NewCompilerCache.java
1 /*
2  * Copyright 2000-2010 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.compiler.impl.newApi;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.util.Processor;
20 import com.intellij.util.io.DataExternalizer;
21 import com.intellij.util.io.KeyDescriptor;
22 import com.intellij.util.io.PersistentHashMap;
23
24 import java.io.DataInput;
25 import java.io.DataOutput;
26 import java.io.File;
27 import java.io.IOException;
28
29 /**
30  * @author nik
31  */
32 public class NewCompilerCache<Key, SourceState, OutputState> {
33   private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.newApi.NewCompilerCache");
34   private PersistentHashMap<KeyAndTargetData<Key>, PersistentStateData<SourceState, OutputState>> myPersistentMap;
35   private File myCacheFile;
36   private final NewCompiler<Key, SourceState, OutputState> myCompiler;
37
38   public NewCompilerCache(NewCompiler<Key, SourceState, OutputState> compiler, final File compilerCacheDir) throws IOException {
39     myCompiler = compiler;
40     myCacheFile = new File(compilerCacheDir, "timestamps");
41     createMap();
42   }
43
44   private void createMap() throws IOException {
45     myPersistentMap = new PersistentHashMap<KeyAndTargetData<Key>, PersistentStateData<SourceState,OutputState>>(myCacheFile, new SourceItemDataDescriptor(myCompiler.getItemKeyDescriptor()),
46                                                                   new PersistentStateDataExternalizer(myCompiler));
47   }
48
49   private KeyAndTargetData<Key> getKeyAndTargetData(Key key, int target) {
50     return new KeyAndTargetData<Key>(target, key);
51   }
52
53   public void wipe() throws IOException {
54     try {
55       myPersistentMap.close();
56     }
57     catch (IOException ignored) {
58     }
59     PersistentHashMap.deleteFilesStartingWith(myCacheFile);
60     createMap();
61   }
62
63   public void close() {
64     try {
65       myPersistentMap.close();
66     }
67     catch (IOException e) {
68       LOG.info(e);
69     }
70   }
71
72   public void remove(int targetId, Key key) throws IOException {
73     myPersistentMap.remove(getKeyAndTargetData(key, targetId));
74   }
75
76   public PersistentStateData<SourceState, OutputState> getState(int targetId, Key key) throws IOException {
77     return myPersistentMap.get(getKeyAndTargetData(key, targetId));
78   }
79
80   public void processSources(final int targetId, final Processor<Key> processor) throws IOException {
81     myPersistentMap.processKeys(new Processor<KeyAndTargetData<Key>>() {
82       @Override
83       public boolean process(KeyAndTargetData<Key> data) {
84         return targetId == data.myTarget ? processor.process(data.myKey) : true;
85       }
86     });
87   }
88
89   public void putState(int targetId, Key key, SourceState sourceState, OutputState outputState) throws IOException {
90     myPersistentMap.put(getKeyAndTargetData(key, targetId), new PersistentStateData<SourceState,OutputState>(sourceState, outputState));
91   }
92
93
94   private static class KeyAndTargetData<Key> {
95     public final int myTarget;
96     public final Key myKey;
97
98     private KeyAndTargetData(int target, Key key) {
99       myTarget = target;
100       myKey = key;
101     }
102   }
103
104   public static class PersistentStateData<SourceState, OutputState> {
105     public final SourceState mySourceState;
106     public final OutputState myOutputState;
107
108     private PersistentStateData(SourceState sourceState, OutputState outputState) {
109       mySourceState = sourceState;
110       myOutputState = outputState;
111     }
112   }
113   
114   private class SourceItemDataDescriptor implements KeyDescriptor<KeyAndTargetData<Key>> {
115     private final KeyDescriptor<Key> myKeyDescriptor;
116
117     public SourceItemDataDescriptor(KeyDescriptor<Key> keyDescriptor) {
118       myKeyDescriptor = keyDescriptor;
119     }
120
121     @Override
122     public boolean isEqual(KeyAndTargetData<Key> val1, KeyAndTargetData<Key> val2) {
123       return val1.myTarget == val2.myTarget;
124     }
125
126     @Override
127     public int getHashCode(KeyAndTargetData<Key> value) {
128       return value.myTarget + 239 * myKeyDescriptor.getHashCode(value.myKey);
129     }
130
131     @Override
132     public void save(DataOutput out, KeyAndTargetData<Key> value) throws IOException {
133       out.writeInt(value.myTarget);
134       myKeyDescriptor.save(out, value.myKey);
135     }
136
137
138     @Override
139     public KeyAndTargetData<Key> read(DataInput in) throws IOException {
140       int target = in.readInt();
141       final Key item = myKeyDescriptor.read(in);
142       return getKeyAndTargetData(item, target);
143     }
144   }
145
146   private class PersistentStateDataExternalizer implements DataExternalizer<PersistentStateData<SourceState, OutputState>> {
147     private DataExternalizer<SourceState> mySourceStateExternalizer;
148     private DataExternalizer<OutputState> myOutputStateExternalizer;
149
150     public PersistentStateDataExternalizer(NewCompiler<Key,SourceState,OutputState> compiler) {
151       mySourceStateExternalizer = compiler.getSourceStateExternalizer();
152       myOutputStateExternalizer = compiler.getOutputStateExternalizer();
153     }
154
155     @Override
156     public void save(DataOutput out, PersistentStateData<SourceState, OutputState> value) throws IOException {
157       mySourceStateExternalizer.save(out, value.mySourceState);
158       myOutputStateExternalizer.save(out, value.myOutputState);
159     }
160
161     @Override
162     public PersistentStateData<SourceState, OutputState> read(DataInput in) throws IOException {
163       SourceState sourceState = mySourceStateExternalizer.read(in);
164       OutputState outputState = myOutputStateExternalizer.read(in);
165       return new PersistentStateData<SourceState,OutputState>(sourceState, outputState);
166     }
167   }
168 }