package jplagWebService.serverAccess; import java.util.Date; import java.util.Vector; import java.io.*; import jplagWebService.serverImpl.JPlagCentral; public class MemoryManager extends Thread { private static final long ONEDAY = 86400000; private static final long MAX_SUB_SIZE = 104857600; // 100MB private static final long LOW_SUB_SIZE = 102400; // 100kB private static final long MIN_TIME_ON_SERVER = 1; // in days private static final long MAX_TIME_ON_SERVER = 7; // in days /* * constants for linear interpolation between MINIMAL_TIME_ON_SERVER * at MAX_SUB_SIZE and MAXIMAL_TIME_ON_SERVER at LOW_SUB_SIZE */ private static final float a = -(MAX_TIME_ON_SERVER-MIN_TIME_ON_SERVER) / (MAX_SUB_SIZE-LOW_SUB_SIZE); private static final float b = MIN_TIME_ON_SERVER - a * MAX_SUB_SIZE; private static MemoryManager instance = null; private static long LAST_LOADING_TIME = 0; /** * used to stop memory manager. */ private boolean manager_enabled = false; /** * All submissions at this time. */ private Vector<AccessStructure> submissions = new Vector<AccessStructure>(); /** * Memory manager will react every SLEEP_TIME millisecond */ private static final long SLEEP_TIME = 600000;// 10 min private MemoryManager() { }// cannot be instantiated out of this. /** * * @return unique instance of the memory manager. */ public static MemoryManager giveInstance() { if (instance == null) instance = new MemoryManager(); return instance; } /** * @return Whether the submission is to be erased or not */ private static boolean isErasable(AccessStructure struct) { // get size of struct String result_loc = struct.getResultPath(); File res_file = new File(result_loc); long size = Math.max(res_file.length(), 1); /** * Check whether the file is bigger than the maximal one authorized */ if(size>MAX_SUB_SIZE) return true; float time_diff = (System.currentTimeMillis()-struct.getDate())/ONEDAY; if (time_diff < MIN_TIME_ON_SERVER) return false; else if (time_diff >= MAX_TIME_ON_SERVER) return true; else if (time_diff >= a * size + b) return true; else return false; } /** * Mechanism to delete a submission from the Terminated Queue. * * @param struct * submission to be deleted */ private static void manageDeletion(AccessStructure struct) { JPlagCentral.cancelSubmission(struct); System.out.println("[" + new Date() + "] MemoryManager: Submission \"" + struct.getTitle() + "\" from user \"" + struct.getUsername() + "\" with submissionID " + struct.getSubmissionID() + " saved on " + new Date(struct.getDate()) + " has been deleted"); } /** * Used to actualize the vector containing all submissions */ private void loadSubmissions() { submissions.clear(); // Collect all usernames on the server String[] users = JPlagCentral.usersList(); // Collect all submissions for each user for (int i = 0; i < users.length; i++) { AccessStructure[] subm = JPlagCentral.listAccessStructures(users[i]); if (subm != null && subm.length != 0) { for (int j = 0; j < subm.length; j++) { submissions.add(subm[j]); } } } } /** * MemoryManager main loop */ public void run() { System.out.println("MemoryManager running..."); try { while (manager_enabled) { if ((System.currentTimeMillis() - LAST_LOADING_TIME) / ONEDAY >= MIN_TIME_ON_SERVER) { loadSubmissions(); LAST_LOADING_TIME = System.currentTimeMillis(); } for (int i = submissions.size()-1; i>=0 && manager_enabled; i--) { AccessStructure struct = (AccessStructure) submissions.get(i); if (isErasable(struct)) { manageDeletion(struct); submissions.remove(i); } } try { Thread.sleep(SLEEP_TIME); } catch (InterruptedException e) { if(manager_enabled) e.printStackTrace(); } } } catch(Exception e) { e.printStackTrace(); } System.out.println("MemoryManager stopped!"); } public boolean isManager_enabled() { return manager_enabled; } /** * @param manager_enabled New MemoryManager state. Must be set to true * before starting the memory manager. */ public synchronized void setManager_enabled(boolean manager_enabled) { this.manager_enabled = manager_enabled; } }