/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.zookeeper_voltpatches.server;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.apache.zookeeper_voltpatches.server.SessionTracker;
import org.apache.zookeeper_voltpatches.server.SessionTrackerImpl;
import org.apache.zookeeper_voltpatches.server.ZooTrace;
import org.apache.zookeeper_voltpatches.KeeperException;
import org.apache.zookeeper_voltpatches.KeeperException.SessionExpiredException;
import org.voltcore.logging.VoltLogger;
/**
* This is a full featured SessionTracker. It tracks session in grouped by tick
* interval. It always rounds up the tick interval to provide a sort of grace
* period. Sessions are thus expired in batches made up of sessions that expire
* in a given interval.
*/
public class SessionTrackerImpl implements SessionTracker {
private static final VoltLogger LOG = new VoltLogger(SessionTrackerImpl.class.getSimpleName());
ConcurrentHashMap<Long, Long> sessionsById = new ConcurrentHashMap<Long, Long>();
SessionExpirer m_expirer;
public SessionTrackerImpl(SessionExpirer expirer,
ConcurrentHashMap<Long, Long> sessionsAndOwners)
{
m_expirer = expirer;
sessionsById = sessionsAndOwners;
}
@Override
public void dumpSessions(PrintWriter pwriter) {
pwriter.print("Session Sets (");
pwriter.println("):");
ArrayList<Long> keys = new ArrayList<Long>(sessionsById.keySet());
Collections.sort(keys);
for (long sid : keys) {
pwriter.print("Session ");
pwriter.print("0x");
pwriter.print(sid);
pwriter.print(" owner ");
pwriter.println(sessionsById.get(sid));
}
}
@Override
synchronized public String toString() {
StringWriter sw = new StringWriter();
PrintWriter pwriter = new PrintWriter(sw);
dumpSessions(pwriter);
pwriter.flush();
pwriter.close();
return sw.toString();
}
@Override
public void removeSession(long sessionId) {
if (!sessionsById.containsKey(sessionId)) {
return;
}
long owner = sessionsById.remove(sessionId);
if (LOG.isTraceEnabled()) {
ZooTrace.logTraceMessage(LOG, ZooTrace.SESSION_TRACE_MASK,
"SessionTrackerImpl --- Removing session 0x"
+ Long.toHexString(sessionId) + " owner " + owner);
}
}
@Override
public void addSession(long id, long owner) {
if (sessionsById.get(id) == null) {
sessionsById.put(id, owner);
if (LOG.isTraceEnabled()) {
ZooTrace.logTraceMessage(LOG, ZooTrace.SESSION_TRACE_MASK,
"SessionTrackerImpl --- Adding session 0x"
+ Long.toHexString(id) + " owner " + owner);
}
} else {
if (LOG.isTraceEnabled()) {
ZooTrace.logTraceMessage(LOG, ZooTrace.SESSION_TRACE_MASK,
"SessionTrackerImpl --- Existing session 0x"
+ Long.toHexString(id) + " owner " + sessionsById.get(id));
}
}
}
@Override
public void expireSessionsWithOwner(long owner) {
Iterator<Map.Entry<Long,Long>> iter = sessionsById.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<Long, Long> entry = iter.next();
if (entry.getValue() == owner) {
iter.remove();
m_expirer.expire(entry.getKey());
}
}
}
}