extensions/net.sf.basedb.xfiles/trunk/src/net/sf/basedb/xfiles/ConnectionCache.java

Code
Comments
Other
Rev Date Author Line
2571 13 Aug 14 nicklas 1 /**
2571 13 Aug 14 nicklas 2   $Id$
2571 13 Aug 14 nicklas 3
2571 13 Aug 14 nicklas 4   Copyright (C) 2014 Nicklas Nordborg
2571 13 Aug 14 nicklas 5
2571 13 Aug 14 nicklas 6   This file is part of BASE - BioArray Software Environment.
2571 13 Aug 14 nicklas 7   Available at http://base.thep.lu.se/
2571 13 Aug 14 nicklas 8
2571 13 Aug 14 nicklas 9   BASE is free software; you can redistribute it and/or
2571 13 Aug 14 nicklas 10   modify it under the terms of the GNU General Public License
2571 13 Aug 14 nicklas 11   as published by the Free Software Foundation; either version 3
2571 13 Aug 14 nicklas 12   of the License, or (at your option) any later version.
2571 13 Aug 14 nicklas 13
2571 13 Aug 14 nicklas 14   BASE is distributed in the hope that it will be useful,
2571 13 Aug 14 nicklas 15   but WITHOUT ANY WARRANTY; without even the implied warranty of
2571 13 Aug 14 nicklas 16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2571 13 Aug 14 nicklas 17   GNU General Public License for more details.
2571 13 Aug 14 nicklas 18
2571 13 Aug 14 nicklas 19   You should have received a copy of the GNU General Public License
2571 13 Aug 14 nicklas 20   along with BASE. If not, see <http://www.gnu.org/licenses/>.
2571 13 Aug 14 nicklas 21 */
2571 13 Aug 14 nicklas 22 package net.sf.basedb.xfiles;
2571 13 Aug 14 nicklas 23
2571 13 Aug 14 nicklas 24 import java.io.Closeable;
2571 13 Aug 14 nicklas 25 import java.util.Comparator;
2571 13 Aug 14 nicklas 26 import java.util.Map;
2571 13 Aug 14 nicklas 27 import java.util.TreeMap;
2571 13 Aug 14 nicklas 28
2571 13 Aug 14 nicklas 29 import net.sf.basedb.core.DbControl;
2571 13 Aug 14 nicklas 30 import net.sf.basedb.core.TransactionalAction;
2571 13 Aug 14 nicklas 31
2571 13 Aug 14 nicklas 32 /**
2571 13 Aug 14 nicklas 33   Cache implementation for holding connections to remote server. Caching is done per
2571 13 Aug 14 nicklas 34   thread so there should not be any multi-threading issues. Before a cache can be
2571 13 Aug 14 nicklas 35   used it must be initialized with a DbControl, since we need to detect when the
2571 13 Aug 14 nicklas 36   transaction has ended and remove the cache.
2571 13 Aug 14 nicklas 37   
2571 13 Aug 14 nicklas 38   @since 1.1
2571 13 Aug 14 nicklas 39 */
2571 13 Aug 14 nicklas 40 public class ConnectionCache<C extends Closeable>
2571 13 Aug 14 nicklas 41   implements TransactionalAction
2571 13 Aug 14 nicklas 42 {
2571 13 Aug 14 nicklas 43
2572 13 Aug 14 nicklas 44   private final ThreadLocal<Map<ConnectionInfo, C>> cache;
2571 13 Aug 14 nicklas 45   private final ThreadLocal<Boolean> initialized;
2571 13 Aug 14 nicklas 46   
2571 13 Aug 14 nicklas 47   /**
2571 13 Aug 14 nicklas 48     Create a new cache. The comparator implementation should be such that 
2571 13 Aug 14 nicklas 49     if two sets of connection parameters result in a connection to the same server 
2571 13 Aug 14 nicklas 50     with the same credentials, the parameters shold be considered equal.
2571 13 Aug 14 nicklas 51     
2571 13 Aug 14 nicklas 52     @param comparator A comparator that is used to check if connection parameters
2571 13 Aug 14 nicklas 53       are equal
2571 13 Aug 14 nicklas 54   */
2572 13 Aug 14 nicklas 55   public ConnectionCache(Comparator<ConnectionInfo> comparator)
2571 13 Aug 14 nicklas 56   {
2571 13 Aug 14 nicklas 57     this.cache = new TheCache<C>(comparator);
2571 13 Aug 14 nicklas 58     this.initialized = new ThreadLocal<Boolean>();
2571 13 Aug 14 nicklas 59   }  
2571 13 Aug 14 nicklas 60   
2571 13 Aug 14 nicklas 61   /**
2571 13 Aug 14 nicklas 62     Initialize the cache for the current thread. The cache is tied to
2571 13 Aug 14 nicklas 63     the given transaction and will live at least as long as until the
2571 13 Aug 14 nicklas 64     transaction either is committed or rolled back. If there are still
2571 13 Aug 14 nicklas 65     open files, the cache may live until the last file is closed.
2571 13 Aug 14 nicklas 66   */
2571 13 Aug 14 nicklas 67   public void init(DbControl dc)
2571 13 Aug 14 nicklas 68   {
2571 13 Aug 14 nicklas 69     if (cache.get().size() == 0)
2571 13 Aug 14 nicklas 70     {
2571 13 Aug 14 nicklas 71       dc.addTransactionalAction(this);
2571 13 Aug 14 nicklas 72       initialized.set(true);
2571 13 Aug 14 nicklas 73     }
2571 13 Aug 14 nicklas 74   }
2571 13 Aug 14 nicklas 75   
2571 13 Aug 14 nicklas 76   /**
2571 13 Aug 14 nicklas 77     Get a client for connecting to the remote server with the given connection parameters.
2571 13 Aug 14 nicklas 78     @return An existing connection or null if no connection has been cached
2571 13 Aug 14 nicklas 79   */
2572 13 Aug 14 nicklas 80   public C getClient(ConnectionInfo cp)
2571 13 Aug 14 nicklas 81   {
2571 13 Aug 14 nicklas 82     if (cp == null || initialized.get() == null) 
2571 13 Aug 14 nicklas 83     {
2571 13 Aug 14 nicklas 84       return null;
2571 13 Aug 14 nicklas 85     }
2571 13 Aug 14 nicklas 86     return cache.get().get(cp);
2571 13 Aug 14 nicklas 87   }
2571 13 Aug 14 nicklas 88   
2571 13 Aug 14 nicklas 89   /**
2571 13 Aug 14 nicklas 90     Store the given client connection in the cache.
2571 13 Aug 14 nicklas 91     @return TRUE if the connection was added to the cache, FALSE if not
2571 13 Aug 14 nicklas 92   */
2572 13 Aug 14 nicklas 93   public boolean setClient(ConnectionInfo cp, C client)
2571 13 Aug 14 nicklas 94   {
2571 13 Aug 14 nicklas 95     if (cp == null || initialized.get() == null) return false;
2571 13 Aug 14 nicklas 96     cache.get().put(cp, client);
2571 13 Aug 14 nicklas 97     return true;
2571 13 Aug 14 nicklas 98   }
2571 13 Aug 14 nicklas 99
2571 13 Aug 14 nicklas 100   @Override
2571 13 Aug 14 nicklas 101   public void onBeforeCommit()
2571 13 Aug 14 nicklas 102   {}
2571 13 Aug 14 nicklas 103
2571 13 Aug 14 nicklas 104   @Override
2571 13 Aug 14 nicklas 105   public void onAfterCommit() 
2571 13 Aug 14 nicklas 106   {
2571 13 Aug 14 nicklas 107     close();
2571 13 Aug 14 nicklas 108   }
2571 13 Aug 14 nicklas 109
2571 13 Aug 14 nicklas 110   @Override
2571 13 Aug 14 nicklas 111   public void onRollback() 
2571 13 Aug 14 nicklas 112   {
2571 13 Aug 14 nicklas 113     close();
2571 13 Aug 14 nicklas 114   }
2571 13 Aug 14 nicklas 115   
2571 13 Aug 14 nicklas 116   /**
2571 13 Aug 14 nicklas 117     Close all connections and destroy the cache for the current thread.
2571 13 Aug 14 nicklas 118   */
2571 13 Aug 14 nicklas 119   private void close()
2571 13 Aug 14 nicklas 120   {
2571 13 Aug 14 nicklas 121     MultiCloseable.closeAll(cache.get().values());
2571 13 Aug 14 nicklas 122     cache.remove();
2571 13 Aug 14 nicklas 123     initialized.remove();
2571 13 Aug 14 nicklas 124   }
2571 13 Aug 14 nicklas 125   
2571 13 Aug 14 nicklas 126   static class TheCache<C>
2572 13 Aug 14 nicklas 127     extends ThreadLocal<Map<ConnectionInfo, C>>
2571 13 Aug 14 nicklas 128   {
2572 13 Aug 14 nicklas 129     private final Comparator<ConnectionInfo> comparator;
2571 13 Aug 14 nicklas 130     
2572 13 Aug 14 nicklas 131     TheCache(Comparator<ConnectionInfo> comparator)
2571 13 Aug 14 nicklas 132     {
2571 13 Aug 14 nicklas 133       this.comparator = comparator;
2571 13 Aug 14 nicklas 134     }
2571 13 Aug 14 nicklas 135     
2571 13 Aug 14 nicklas 136     @Override
2572 13 Aug 14 nicklas 137     protected Map<ConnectionInfo, C> initialValue() 
2571 13 Aug 14 nicklas 138     {
2572 13 Aug 14 nicklas 139       return new TreeMap<ConnectionInfo, C>(this.comparator);
2571 13 Aug 14 nicklas 140     }
2571 13 Aug 14 nicklas 141   }
2571 13 Aug 14 nicklas 142 }