/** * Copyright 2011-2012 Akiban Technologies, Inc. * * 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 com.persistit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; /** * <p> * Identity key for a session. Normally there is one session per thread, but * applications that need to maintain session context across multiple network * requests serviced on different threads can access and carefully modify their * session contexts using SessionID. See {@link Persistit#getSessionId()} and * {@link Persistit#setSessionId(SessionId)}. * </p> * <p> * A SessionId instance holds a reference to the <code>Thread</code> currently * associated with it; initially this this the thread that created the * SessionId. The <code>setSessionId</code> method reassigns the thread field. * The {@link #isAlive()} method indicates whether the associated thread is * alive. The {@link Persistit#cleanup()} method cleans up all transaction * resources for <code>SessionId</code> instances whose threads are no longer * alive. * </p> * <p> * A session is used to maintain state, including the {@link Transaction} * context and map of cached {@link Exchange} maintained by * {@link Persistit#getExchange(String, String, boolean)}. Therefore care must * be taken to limit the maximum number of <code>SessionId</code> instances * created during the lifetime of a <code>Persistit</code> instance and to * manage them appropriately. * </p> * * @author peter * */ public class SessionId { private final static AtomicInteger counter = new AtomicInteger(1); private final int _id = counter.getAndIncrement(); private final AtomicReference<Thread> _owner = new AtomicReference<Thread>(); public SessionId() { assign(); } @Override public boolean equals(final Object id) { if (id == null || !(id instanceof SessionId)) { return false; } return this._id == ((SessionId) id)._id; } @Override public int hashCode() { return _id; } /** * @return Status of the associated {@link Thread}. */ public boolean isAlive() { return _owner.get().isAlive(); } @Override public String toString() { return "[" + _id + (!isAlive() ? "*]" : "]"); } void assign() { _owner.set(Thread.currentThread()); } boolean interrupt() { final Thread t = _owner.get(); if (t != null && t != Thread.currentThread()) { t.interrupt(); return true; } else { return false; } } public String ownerName() { final Thread t = _owner.get(); if (t == null) { return "null"; } else { return t.getName(); } } }