More project saving changes for #528

- reduce project retention in memory from 1 hr to 15 min.
- free all unmodified projects if we get an error on save (we could be
running low on memory)
- make sure exceptions propagate up to where they can be usefully
handled
This commit is contained in:
Tom Morris 2013-08-05 14:13:56 -04:00
parent 190a031a8a
commit 7b5b549113
3 changed files with 33 additions and 14 deletions

View File

@ -119,7 +119,6 @@ public abstract class ProjectManager {
_projectsMetadata.put(project.id, projectMetadata); _projectsMetadata.put(project.id, projectMetadata);
} }
} }
//----------Load from data store to memory----------------
/** /**
* Load project metadata from data storage * Load project metadata from data storage
@ -135,7 +134,6 @@ public abstract class ProjectManager {
*/ */
protected abstract Project loadProject(long id); protected abstract Project loadProject(long id);
//------------Import and Export from Refine archive-----------------
/** /**
* Import project from a Refine archive * Import project from a Refine archive
* @param projectID * @param projectID
@ -154,7 +152,6 @@ public abstract class ProjectManager {
public abstract void exportProject(long projectId, TarOutputStream tos) throws IOException; public abstract void exportProject(long projectId, TarOutputStream tos) throws IOException;
//------------Save to record store------------
/** /**
* Saves a project and its metadata to the data store * Saves a project and its metadata to the data store
* @param id * @param id
@ -194,8 +191,9 @@ public abstract class ProjectManager {
/** /**
* Save project to the data store * Save project to the data store
* @param project * @param project
* @throws IOException
*/ */
protected abstract void saveProject(Project project); protected abstract void saveProject(Project project) throws IOException;
/** /**
* Save workspace and all projects to data store * Save workspace and all projects to data store
@ -204,6 +202,7 @@ public abstract class ProjectManager {
public void save(boolean allModified) { public void save(boolean allModified) {
if (allModified || _busy == 0) { if (allModified || _busy == 0) {
saveProjects(allModified); saveProjects(allModified);
// TODO: Only save workspace if it's dirty
saveWorkspace(); saveWorkspace();
} }
} }
@ -227,7 +226,7 @@ public abstract class ProjectManager {
} }
} }
static protected final int s_projectFlushDelay = 1000 * 60 * 60; // 1 hour static protected final int s_projectFlushDelay = 1000 * 60 * 15; // 15 minutes
static protected final int s_quickSaveTimeout = 1000 * 30; // 30 secs static protected final int s_quickSaveTimeout = 1000 * 30; // 30 secs
/** /**
@ -296,12 +295,29 @@ public abstract class ProjectManager {
saveProject(records.get(i).project); saveProject(records.get(i).project);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
// In case we're running low on memory, free as much as we can
disposeUnmodifiedProjects();
}
}
}
}
/**
* Flush all unmodified projects from memory.
*/
protected void disposeUnmodifiedProjects() {
synchronized (this) {
for (long id : _projectsMetadata.keySet()) {
ProjectMetadata metadata = getProjectMetadata(id);
Project project = _projects.get(id);
if (project != null && !project.getProcessManager().hasPending()
&& metadata.getModified().getTime() < project.getLastSave().getTime()) {
_projects.remove(id).dispose();
} }
} }
} }
} }
//--------------Get from memory--------------
/** /**
* Gets the InterProjectModel from memory * Gets the InterProjectModel from memory
*/ */
@ -405,7 +421,6 @@ public abstract class ProjectManager {
*/ */
public abstract HistoryEntryManager getHistoryEntryManager(); public abstract HistoryEntryManager getHistoryEntryManager();
//-------------remove project-----------
/** /**
* Remove the project from the data store * Remove the project from the data store
@ -434,7 +449,6 @@ public abstract class ProjectManager {
} }
} }
//--------------Miscellaneous-----------
/** /**
* Sets the flag for long running operations. This will prevent * Sets the flag for long running operations. This will prevent

View File

@ -217,7 +217,7 @@ public class FileProjectManager extends ProjectManager {
} }
@Override @Override
protected void saveProject(Project project){ protected void saveProject(Project project) throws IOException{
ProjectUtilities.save(project); ProjectUtilities.save(project);
} }

View File

@ -35,6 +35,7 @@ package com.google.refine.io;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
@ -50,7 +51,7 @@ import com.google.refine.util.Pool;
public class ProjectUtilities { public class ProjectUtilities {
final static Logger logger = LoggerFactory.getLogger("project_utilities"); final static Logger logger = LoggerFactory.getLogger("project_utilities");
synchronized public static void save(Project project) { synchronized public static void save(Project project) throws IOException {
synchronized (project) { synchronized (project) {
long id = project.id; long id = project.id;
File dir = ((FileProjectManager)ProjectManager.singleton).getProjectDir(id); File dir = ((FileProjectManager)ProjectManager.singleton).getProjectDir(id);
@ -58,11 +59,15 @@ public class ProjectUtilities {
File tempFile = new File(dir, "data.temp.zip"); File tempFile = new File(dir, "data.temp.zip");
try { try {
saveToFile(project, tempFile); saveToFile(project, tempFile);
} catch (Exception e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
logger.warn("Failed to save project {}", id); logger.warn("Failed to save project {}", id);
return; try {
tempFile.delete();
} catch (Exception e2) {
// just ignore - file probably was never created.
}
throw e;
} }
File file = new File(dir, "data.zip"); File file = new File(dir, "data.zip");
@ -83,7 +88,7 @@ public class ProjectUtilities {
} }
} }
protected static void saveToFile(Project project, File file) throws Exception { protected static void saveToFile(Project project, File file) throws IOException {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file)); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(file));
try { try {
Pool pool = new Pool(); Pool pool = new Pool();