/* * Copyright 2003,2004,2005 Colin Crist * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package hermes.fix.quickfix; import hermes.fix.FIXMessage; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.collections.map.LRUMap; import quickfix.Message; import quickfix.mina.message.FIXMessageDecoder; /** * @author colincrist@hermesjms.com * @version $Id: QuickFIXMessageCache.java,v 1.1 2006/07/26 09:47:56 colincrist * Exp $ */ public class QuickFIXMessageCache { private LRUMap messages; private Set<FIXMessage> toReset = new HashSet<FIXMessage>(); private Lock lock = new ReentrantLock(); private Map<Thread, FIXMessageDecoder> decoders = new HashMap<Thread, FIXMessageDecoder>(); public QuickFIXMessageCache() { this(1024); } public FIXMessageDecoder getDecoder() throws UnsupportedEncodingException { synchronized (decoders) { FIXMessageDecoder decoder = decoders.get(Thread.currentThread()); if (decoder == null) { decoder = new FIXMessageDecoder(); decoders.put(Thread.currentThread(), decoder); } return decoder; } } public QuickFIXMessageCache(int size) { messages = createLRUMap(size); } private LRUMap createLRUMap(int size) { return new LRUMap(size) { /** * */ private static final long serialVersionUID = -3353399913762901038L; @Override protected boolean removeLRU(LinkEntry entry) { // // When the message is removed from the cache clear its fields. final FIXMessage message = (FIXMessage) entry.getKey(); // We cannot call reset here, the next time a put occurs, we'll // reset it. synchronized (toReset) { toReset.add(message); } return super.removeLRU(entry); } }; } public void setSize(int size) { lock.lock(); try { final LRUMap newMessages = createLRUMap(size); messages.putAll(newMessages); messages = newMessages; } finally { lock.unlock(); } } public int getSize() { lock.lock(); try { if (messages == null) { return 0; } else { return messages.maxSize(); } } finally { lock.unlock(); } } public void close() { lock.lock(); try { messages.clear(); decoders.clear(); } finally { lock.unlock(); } synchronized (toReset) { toReset.clear(); } } public void lock() { lock.lock(); } public void unlock() { lock.unlock(); } public boolean contains(FIXMessage key) { lock.lock(); try { return messages.containsKey(key); } finally { lock.unlock(); } } public void put(FIXMessage key, Message value) { lock.lock(); try { messages.put(key, value); } finally { lock.unlock(); } synchronized (toReset) { if (toReset.contains(key)) { toReset.remove(key); } for (FIXMessage m : toReset) { m.reset(); } toReset.clear(); } } public Message get(FIXMessage key) { lock.lock(); try { return (Message) messages.get(key); } finally { lock.unlock(); } } }