gt:         long id = cnxn.getSessionId();
context: /**
   * 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.server;
  
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.PrintWriter;
  import java.nio.ByteBuffer;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.HashMap;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Random;
  
  import org.apache.jute.BinaryInputArchive;
  import org.apache.jute.BinaryOutputArchive;
  import org.apache.jute.Record;
  import org.apache.zookeeper.Environment;
  import org.apache.zookeeper.KeeperException;
  import org.apache.zookeeper.KeeperException.Code;
  import org.apache.zookeeper.KeeperException.SessionExpiredException;
  import org.apache.zookeeper.ZooDefs.OpCode;
  import org.apache.zookeeper.data.ACL;
  import org.apache.zookeeper.data.Id;
  import org.apache.zookeeper.data.StatPersisted;
  import org.apache.zookeeper.jmx.MBeanRegistry;
  import org.apache.zookeeper.proto.AuthPacket;
  import org.apache.zookeeper.proto.ConnectRequest;
  import org.apache.zookeeper.proto.ConnectResponse;
  import org.apache.zookeeper.proto.GetSASLRequest;
  import org.apache.zookeeper.proto.ReplyHeader;
  import org.apache.zookeeper.proto.RequestHeader;
  import org.apache.zookeeper.proto.SetSASLResponse;
  import org.apache.zookeeper.server.DataTree.ProcessTxnResult;
  import org.apache.zookeeper.server.RequestProcessor.RequestProcessorException;
  import org.apache.zookeeper.server.ServerCnxn.CloseRequestException;
  import org.apache.zookeeper.server.SessionTracker.Session;
  import org.apache.zookeeper.server.SessionTracker.SessionExpirer;
  import org.apache.zookeeper.server.auth.AuthenticationProvider;
  import org.apache.zookeeper.server.auth.ProviderRegistry;
  import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
  import org.apache.zookeeper.server.quorum.ReadOnlyZooKeeperServer;
  import org.apache.zookeeper.txn.CreateSessionTxn;
  import org.apache.zookeeper.txn.TxnHeader;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  
  /**
   * This class implements a simple standalone ZooKeeperServer. It sets up the
   * following chain of RequestProcessors to process requests:
   * PrepRequestProcessor -> SyncRequestProcessor -> FinalRequestProcessor
   */
  public class ZooKeeperServer implements SessionExpirer, ServerStats.Provider {
      protected static final Logger LOG;
      
      static {
          LOG = LoggerFactory.getLogger(ZooKeeperServer.class);
          
          Environment.logEnv("Server environment:", LOG);
      }
  
      protected ZooKeeperServerBean jmxServerBean;
      protected DataTreeBean jmxDataTreeBean;
  
   
      /**
       * The server delegates loading of the tree to an instance of the interface
       */
      public interface DataTreeBuilder {
          public DataTree build();
      }
  
      static public class BasicDataTreeBuilder implements DataTreeBuilder {
          public DataTree build() {
              return new DataTree();
          }
      }
  
      public static final int DEFAULT_TICK_TIME = 3000;
      protected int tickTime = DEFAULT_TICK_TIME;
      /** value of -1 indicates unset, use default */
      protected int minSessionTimeout = -1;
      /** value of -1 indicates unset, use default */
      protected int maxSessionTimeout = -1;
      protected SessionTracker sessionTracker;
      private FileTxnSnapLog txnLogFactory = null;
      private ZKDatabase zkDb;
      protected long hzxid = 0;
      public final static Exception ok = new Exception("No prob");
      protected RequestProcessor firstProcessor;
      protected volatile boolean running;
  
      /**
       * This is the secret that we use to generate passwords, for the moment it
       * is more of a sanity check.
       */
      static final private long superSecret = 0XB3415C00L;
  
      int requestsInProcess;
      final List<ChangeRecord> outstandingChanges = new ArrayList<ChangeRecord>();
      // this data structure must be accessed under the outstandingChanges lock
      final HashMap<String, ChangeRecord> outstandingChangesForPath =
          new HashMap<String, ChangeRecord>();
      
      private ServerCnxnFactory serverCnxnFactory;
  
      private final ServerStats serverStats;
  
      void removeCnxn(ServerCnxn cnxn) {
          zkDb.removeCnxn(cnxn);
      }
   
      /**
       * Creates a ZooKeeperServer instance. Nothing is setup, use the setX
       * methods to prepare the instance (eg datadir, datalogdir, ticktime, 
       * builder, etc...)
       * 
       * @throws IOException
       */
      public ZooKeeperServer() {
          serverStats = new ServerStats(this);
      }
      
      /**
       * Creates a ZooKeeperServer instance. It sets everything up, but doesn't
       * actually start listening for clients until run() is invoked.
       * 
       * @param dataDir the directory to put the data
       */
      public ZooKeeperServer(FileTxnSnapLog txnLogFactory, int tickTime,
              int minSessionTimeout, int maxSessionTimeout,
              DataTreeBuilder treeBuilder, ZKDatabase zkDb) {
          serverStats = new ServerStats(this);
          this.txnLogFactory = txnLogFactory;
          this.zkDb = zkDb;
          this.tickTime = tickTime;
          this.minSessionTimeout = minSessionTimeout;
          this.maxSessionTimeout = maxSessionTimeout;
          
          LOG.info("Created server with tickTime " + tickTime
                  + " minSessionTimeout " + getMinSessionTimeout()
                  + " maxSessionTimeout " + getMaxSessionTimeout()
                  + " datadir " + txnLogFactory.getDataDir()
                  + " snapdir " + txnLogFactory.getSnapDir());
      }
  
      /**
       * creates a zookeeperserver instance. 
       * @param txnLogFactory the file transaction snapshot logging class
       * @param tickTime the ticktime for the server
       * @param treeBuilder the datatree builder
       * @throws IOException
       */
      public ZooKeeperServer(FileTxnSnapLog txnLogFactory, int tickTime,
              DataTreeBuilder treeBuilder) throws IOException {
          this(txnLogFactory, tickTime, -1, -1, treeBuilder,
                  new ZKDatabase(txnLogFactory));
      }
      
      public ServerStats serverStats() {
          return serverStats;
      }
  
      public void dumpConf(PrintWriter pwriter) {
          pwriter.print("clientPort=");
          pwriter.println(getClientPort());
          pwriter.print("dataDir=");
          pwriter.println(zkDb.snapLog.getSnapDir().getAbsolutePath());
          pwriter.print("dataLogDir=");
          pwriter.println(zkDb.snapLog.getDataDir().getAbsolutePath());
          pwriter.print("tickTime=");
          pwriter.println(getTickTime());
          pwriter.print("maxClientCnxns=");
          pwriter.println(serverCnxnFactory.getMaxClientCnxnsPerHost());
          pwriter.print("minSessionTimeout=");
          pwriter.println(getMinSessionTimeout());
          pwriter.print("maxSessionTimeout=");
          pwriter.println(getMaxSessionTimeout());
  
          pwriter.print("serverId=");
          pwriter.println(getServerId());
      }
  
      /**
       * This constructor is for backward compatibility with the existing unit
       * test code.
       * It defaults to FileLogProvider persistence provider.
       */
      public ZooKeeperServer(File snapDir, File logDir, int tickTime)
              throws IOException {
          this( new FileTxnSnapLog(snapDir, logDir),
                  tickTime, new BasicDataTreeBuilder());
      }
  
      /**
       * Default constructor, relies on the config for its agrument values
       *
       * @throws IOException
       */
      public ZooKeeperServer(FileTxnSnapLog txnLogFactory,
              DataTreeBuilder treeBuilder)
          throws IOException
      {
          this(txnLogFactory, DEFAULT_TICK_TIME, -1, -1, treeBuilder,
                  new ZKDatabase(txnLogFactory));
      }
  
      /**
       * get the zookeeper database for this server
       * @return the zookeeper database for this server
       */
      public ZKDatabase getZKDatabase() {
          return this.zkDb;
      }
      
      /**
       * set the zkdatabase for this zookeeper server
       * @param zkDb
       */
      public void setZKDatabase(ZKDatabase zkDb) {
         this.zkDb = zkDb;
      }
      
      /**
       *  Restore sessions and data
       */
      public void loadData() throws IOException, InterruptedException {
          /*
           * When a new leader starts executing Leader#lead, it 
           * invokes this method. The database, however, has been
           * initialized before running leader election so that
           * the server could pick its zxid for its initial vote.
           * It does it by invoking QuorumPeer#getLastLoggedZxid.
           * Consequently, we don't need to initialize it once more
           * and avoid the penalty of loading it a second time. Not 
           * reloading it is particularly important for applications
           * that host a large database.
           * 
           * The following if block checks whether the database has
           * been initialized or not. Note that this method is
           * invoked by at least one other method: 
           * ZooKeeperServer#startdata.
           *  
           * See ZOOKEEPER-1642 for more detail.
           */
          if(zkDb.isInitialized()){
              setZxid(zkDb.getDataTreeLastProcessedZxid());
          }
          else {
              setZxid(zkDb.loadDataBase());
          }
          
          // Clean up dead sessions
          LinkedList<Long> deadSessions = new LinkedList<Long>();
          for (Long session : zkDb.getSessions()) {
              if (zkDb.getSessionWithTimeOuts().get(session) == null) {
                  deadSessions.add(session);
              }
          }
          zkDb.setDataTreeInit(true);
          for (long session : deadSessions) {
              // XXX: Is lastProcessedZxid really the best thing to use?
              killSession(session, zkDb.getDataTreeLastProcessedZxid());
          }
      }
  
      public void takeSnapshot(){
  
          try {
              txnLogFactory.save(zkDb.getDataTree(), zkDb.getSessionWithTimeOuts());
          } catch (IOException e) {
              LOG.error("Severe unrecoverable error, exiting", e);
              // This is a severe error that we cannot recover from,
              // so we need to exit
              System.exit(10);
          }
      }
  
    
      /**
       * This should be called from a synchronized block on this!
       */
      synchronized public long getZxid() {
          return hzxid;
      }
  
      synchronized long getNextZxid() {
          return ++hzxid;
      }
  
      synchronized public void setZxid(long zxid) {
          hzxid = zxid;
      }
  
      long getTime() {
          return System.currentTimeMillis();
      }
  
      private void close(long sessionId) {
          submitRequest(null, sessionId, OpCode.closeSession, 0, null, null);
      }
      
      public void closeSession(long sessionId) {
          LOG.info("Closing session 0x" + Long.toHexString(sessionId));
          
          // we do not want to wait for a session close. send it as soon as we
          // detect it!
          close(sessionId);
      }
  
      protected void killSession(long sessionId, long zxid) {
          zkDb.killSession(sessionId, zxid);
          if (LOG.isTraceEnabled()) {
              ZooTrace.logTraceMessage(LOG, ZooTrace.SESSION_TRACE_MASK,
                                           "ZooKeeperServer --- killSession: 0x"
                      + Long.toHexString(sessionId));
          }
          if (sessionTracker != null) {
              sessionTracker.removeSession(sessionId);
          }
      }
  
      public void expire(Session session) {
          long sessionId = session.getSessionId();
          LOG.info("Expiring session 0x" + Long.toHexString(sessionId)
                  + ", timeout of " + session.getTimeout() + "ms exceeded");
          close(sessionId);
      }
  
      public static class MissingSessionException extends IOException {
          private static final long serialVersionUID = 7467414635467261007L;
  
          public MissingSessionException(String msg) {
              super(msg);
          }
      }
      
      void touch(ServerCnxn cnxn) throws MissingSessionException {
          if (cnxn == null) {
              return;
          }
  