blob: 53fea91a889e4cd02cbabfddd7505f5d03ba69c0 [file] [log] [blame]
package org.eclipse.dltk.tcl.internal.core;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.Queue;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dltk.ast.parser.IASTCache;
import org.eclipse.dltk.ast.parser.IModuleDeclaration;
import org.eclipse.dltk.compiler.problem.IProblemReporter;
import org.eclipse.dltk.compiler.problem.ProblemCollector;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.caching.IContentCache;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.dltk.internal.core.ModelManager;
import org.eclipse.dltk.tcl.ast.TclModule;
import org.eclipse.dltk.tcl.ast.TclModuleDeclaration;
import org.eclipse.dltk.tcl.internal.core.serialization.TclASTLoader;
import org.eclipse.dltk.tcl.internal.core.serialization.TclASTSaver;
import org.eclipse.dltk.tcl.internal.parser.NewTclSourceParser;
@SuppressWarnings("restriction")
public class TclASTCache implements IASTCache {
public static final String TCL_AST_ATTRIBUTE = "_ast";
public static final String TCL_PKG_INFO = "_pinf";
public static final String TCL_STRUCTURE_INDEX = IContentCache.STRUCTURE_INDEX;
public static final String TCL_MIXIN_INDEX = IContentCache.MIXIN_INDEX;
private static class StoreEntry {
ProblemCollector problems;
IFileHandle handle;
TclModule module;
}
private static class TclCacheSaver extends Job {
final Queue<StoreEntry> queue = new LinkedList<StoreEntry>();
public TclCacheSaver() {
super("Tcl Cache Saver");
setSystem(true);
setPriority(SHORT);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
for (;;) {
final StoreEntry entry;
synchronized (queue) {
entry = queue.poll();
}
if (entry == null) {
break;
}
IContentCache cache = ModelManager.getModelManager()
.getCoreCache();
OutputStream stream = cache.getCacheEntryAttributeOutputStream(
entry.handle, TCL_AST_ATTRIBUTE);
storeTclEntryInCache(entry.problems, entry.module, stream);
try {
stream.close();
} catch (IOException e) {
}
}
return Status.OK_STATUS;
}
@Override
public boolean shouldRun() {
synchronized (queue) {
return !queue.isEmpty();
}
}
void addToQueue(StoreEntry entry) {
final int prevSize;
synchronized (queue) {
prevSize = queue.size();
if (prevSize <= 256) {
queue.add(entry);
}
}
if ((prevSize & 0x0F) == 0) {
schedule();
}
}
}
private final TclCacheSaver cacheSaverJob = new TclCacheSaver();
public ASTCacheEntry restoreModule(ISourceModule module) {
IFileHandle handle = EnvironmentPathUtils.getFile(module);
if (handle == null) {
return null;
}
IContentCache cache = ModelManager.getModelManager().getCoreCache();
ProblemCollector collector = new ProblemCollector();
TclModule tclModule = null;
tclModule = restoreTclModuleFromCache(handle, cache, collector);
if (tclModule != null) {
ASTCacheEntry entry = new ASTCacheEntry();
NewTclSourceParser parser = new NewTclSourceParser();
entry.problems = collector;
entry.module = parser.parse(null, tclModule, null);
if (entry.problems.isEmpty()) {
entry.problems = null;
}
return entry;
}
return null;
}
public static TclModule restoreTclModuleFromCache(IFileHandle handle,
IContentCache cache, IProblemReporter collector) {
InputStream stream = cache.getCacheEntryAttribute(handle,
TCL_AST_ATTRIBUTE);
if (stream != null) {
try {
TclASTLoader loader = new TclASTLoader(stream);
TclModule tclModule = loader.getModule(collector);
if (tclModule != null) {
return tclModule;
}
} catch (Exception e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
} finally {
try {
stream.close();
} catch (IOException e) {
}
}
}
return null;
}
public void storeModule(ISourceModule module,
IModuleDeclaration moduleDeclaration, ProblemCollector problems) {
IFileHandle handle = EnvironmentPathUtils.getFile(module, false);
if (handle == null) {
return;
}
if (moduleDeclaration instanceof TclModuleDeclaration) {
TclModuleDeclaration decl = (TclModuleDeclaration) moduleDeclaration;
TclModule tclModule = decl.getTclModule();
if (tclModule != null) {
StoreEntry entry = new StoreEntry();
entry.handle = handle;
entry.module = tclModule;
if (problems != null) {
entry.problems = new ProblemCollector();
problems.copyTo(entry.problems);
}
cacheSaverJob.addToQueue(entry);
}
}
}
public static void storeTclEntryInCache(ProblemCollector problems,
TclModule tclModule, OutputStream stream) {
TclASTSaver saver;
try {
saver = new TclASTSaver();
saver.save(tclModule, problems, stream);
} catch (IOException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
}