/* * "Copyright (c) 2010-11 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Author: Jorge Ortiz (jortiz@cs.berkeley.edu) * IS4 release version 1.0 */ package local.metadata; import java.util.logging.Logger; import java.util.logging.Level; import java.util.Hashtable; import java.util.TimerTask; import java.util.Timer; import java.util.ArrayList; import java.util.Collections; import java.util.Collection; import java.util.Date; import java.io.*; public class BindStateMngr extends TimerTask implements Serializable { private static Logger logger = Logger.getLogger(BindStateMngr.class.getPackage().getName()); private static BindStateMngr bindStateMngr = null; private static Hashtable<Binding, Long> deadlines = new Hashtable<Binding, Long>(); private static Hashtable<Long, Binding> reverseDeadlines = new Hashtable<Long, Binding>(); private static Timer timer = new Timer("BindStateMngrTimer"); private static final long T = 86400; //5L; // //seconds protected static String IS4HOME=null; protected static String deadlinesObjPath = "/.state/deadlines.obj"; protected static String reverseDeadlinesObjPath ="/.state/reverseDeadlines.obj"; private static boolean init = false; private BindStateMngr() { timer.schedule(this, 0L, T*1000); logger.info("Started cleanup task timer"); if(!init) { try { initGlobalVars(); File f1 = new File(deadlinesObjPath); File f2 = new File(reverseDeadlinesObjPath); if (f1.exists()){ FileInputStream fileIn = new FileInputStream(f1); ObjectInputStream in = new ObjectInputStream(fileIn); deadlines = (Hashtable<Binding, Long>)in.readObject(); } if (f2.exists()){ FileInputStream fileIn = new FileInputStream(f2); ObjectInputStream in = new ObjectInputStream(fileIn); reverseDeadlines = (Hashtable<Long, Binding>)in.readObject(); } init = true; } catch (Exception e) { logger.log(Level.WARNING, "Error loading previous state", e); } } } public static BindStateMngr getInstance() { logger.info("fetching BindStateMngr instance"); if(bindStateMngr == null) bindStateMngr = new BindStateMngr(); return bindStateMngr; } protected static void initGlobalVars(){ String home = System.getenv().get("IS4HOME"); if(IS4HOME == null && home !=null && !home.equals("")){ IS4HOME = home; deadlinesObjPath = IS4HOME + deadlinesObjPath; reverseDeadlinesObjPath = IS4HOME + reverseDeadlinesObjPath; } else if(IS4HOME == null && home ==null || home.equals("")){ logger.severe("Environment variable not set"); System.exit(1); } } public void manageBinding(Binding binding) { logger.info((new StringBuilder()).append("Adding Binding: ").append(binding.getPid()).toString()); if(binding != null){ Long newDeadline = new Long((new Date()).getTime() / 1000L + T); deadlines.put(binding, newDeadline); reverseDeadlines.put(newDeadline, binding); logger.info((new StringBuilder()).append("Added ").append(binding.getPid()).append(" Deadline: ").append(newDeadline.longValue()).toString()); saveState(); } } public void updateBindingTimestamp(Binding binding) { logger.info("Updating the binding timestamp"); Long dl = null; if((dl = deadlines.get(binding)) != null) { Date date = new Date(); Long newDeadline = new Long(date.getTime() / 1000L); deadlines.remove(binding); reverseDeadlines.remove(dl); deadlines.put(binding, newDeadline); reverseDeadlines.put(newDeadline, binding); saveState(); } } public void expireBinding(Binding binding) { Long dl = null; if((dl = (Long)deadlines.get(binding)) != null) { deadlines.remove(binding); reverseDeadlines.remove(dl); logger.info((new StringBuilder()).append("removing binding: ").append(binding.getPid()).append(" --> \n\t").append(binding.getMeta()).toString()); saveState(); } } public boolean isActive(Binding binding) { logger.info("Checking if binding is active"); return deadlines.get(binding) != null; } public void run() { logger.info("Starting periodic cleanup task"); Collection<Long> deadlineTimes = deadlines.values(); ArrayList<Long> deadlineTimesList = new ArrayList<Long>(deadlineTimes); if(deadlineTimesList.size() > 0) { logger.info("Found"); Collections.sort(deadlineTimesList); Collections.reverse(deadlineTimesList); long now = (new Date()).getTime() / 1000L; int i = 0; logger.info((new StringBuilder()).append("Now: ").append(now).append(" Deadline: ").append(((Long)deadlineTimesList.get(i)).longValue()).toString()); while(i < deadlineTimesList.size() && now >= deadlineTimesList.get(i).longValue()) { Binding binding = reverseDeadlines.get(deadlineTimesList.get(i)); MetadataMngr.getInstance().unbind(binding.getPid()); i += 1; } } } public synchronized void saveState(){ try { FileOutputStream fileOut = new FileOutputStream(deadlinesObjPath); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(deadlines); fileOut = new FileOutputStream(reverseDeadlinesObjPath); out = new ObjectOutputStream(fileOut); out.writeObject(reverseDeadlines); logger.info("Wrote objectes"); } catch(Exception e) { logger.log(Level.WARNING, "Likely and IOException while writing objects", e); } } }