/*
* Copyright 2003-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jetbrains.mps.generator.impl.cache;
import jetbrains.mps.generator.GenerationCacheContainer.ModelCacheContainer;
import jetbrains.mps.util.FileUtil;
import jetbrains.mps.util.io.ModelInputStream;
import jetbrains.mps.util.io.ModelOutputStream;
import org.jetbrains.mps.openapi.model.SModelReference;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Evgeny Gryaznov, Sep 21, 2010
*/
public class IntermediateModelsCache {
private static final String SIGNATURE = "signature";
private static final String STEPS = "steps";
private final ModelCacheContainer myCacheContainer;
private final String mySignature;
private boolean isOk = true;
private List<Integer> mySteps;
public IntermediateModelsCache(ModelCacheContainer cacheContainer, String signature) {
myCacheContainer = cacheContainer;
mySignature = signature;
mySteps = new ArrayList<Integer>();
}
public String getSignature() {
return mySignature;
}
private String getStorageName(int major, int minor) {
return "step" + major + "_" + minor;
}
public static IntermediateModelsCache load(ModelCacheContainer cacheContainer) {
try {
ModelInputStream is = new ModelInputStream(cacheContainer.openStream(STEPS));
List<Integer> steps;
try {
int count = is.readInt();
if (count > 10000) {
throw new IOException("illegal data");
}
steps = new ArrayList<Integer>(count);
for (int i = 0; i < count; i++) {
steps.add(is.readInt());
}
} finally {
is.close();
}
InputStreamReader reader = new InputStreamReader(cacheContainer.openStream(SIGNATURE), FileUtil.DEFAULT_CHARSET);
try {
StringBuilder signature = new StringBuilder();
char[] buff = new char[512];
int size;
while ((size = reader.read(buff)) > 0) {
signature.append(buff, 0, size);
}
IntermediateModelsCache result = new IntermediateModelsCache(cacheContainer, signature.toString());
result.setSteps(steps);
return result;
} finally {
reader.close();
}
} catch (IOException e) {
/* cannot load */
}
return null;
}
private void setSteps(List<Integer> steps) {
mySteps = steps;
}
public int getMinorCount(int majorStep) {
return mySteps.get(majorStep);
}
public void store(int majorStep, int minor, TransientModelWithMetainfo model) {
try {
while (majorStep >= mySteps.size()) {
mySteps.add(0);
}
int minorStep = mySteps.get(majorStep);
mySteps.set(majorStep, minorStep + 1);
assert minor == minorStep;
ModelOutputStream os = new ModelOutputStream(myCacheContainer.createStream(getStorageName(majorStep, minorStep)));
try {
model.save(os);
} finally {
os.close();
}
} catch (IOException e) {
isOk = false;
}
}
public TransientModelWithMetainfo load(int majorStep, int minorStep, SModelReference modelReference) {
try {
InputStream stream = myCacheContainer.openStream(getStorageName(majorStep, minorStep));
ModelInputStream is = new ModelInputStream(stream);
try {
return TransientModelWithMetainfo.load(is, modelReference);
} finally {
is.close();
}
} catch (IOException e) {
isOk = false;
}
return null;
}
public void store() {
try {
ModelOutputStream os = new ModelOutputStream(myCacheContainer.createStream(STEPS));
try {
os.writeInt(mySteps.size());
for (Integer i : mySteps) {
os.writeInt(i);
}
} finally {
os.close();
}
OutputStreamWriter writer = new OutputStreamWriter(myCacheContainer.createStream(SIGNATURE));
try {
writer.write(mySignature);
} finally {
writer.close();
}
if (isOk) {
myCacheContainer.commit();
} else {
myCacheContainer.revert();
}
} catch (IOException e) {
myCacheContainer.revert();
}
}
public void remove() {
myCacheContainer.revert();
}
}