@Override
  public void run() {
    try {
      while (!finished) {
        Request request = queuedRequests.take();
        if (LOG.isTraceEnabled()) {
          ZooTrace.logRequest(LOG, ZooTrace.CLIENT_REQUEST_TRACE_MASK, 'F', request, "");
        }
        if (request == Request.requestOfDeath) {
          break;
        }
        // We want to queue the request to be processed before we submit
        // the request to the leader so that we are ready to receive
        // the response
        nextProcessor.processRequest(request);

        // We now ship the request to the leader. As with all
        // other quorum operations, sync also follows this code
        // path, but different from others, we need to keep track
        // of the sync operations this Observer has pending, so we
        // add it to pendingSyncs.
        switch (request.type) {
          case OpCode.sync:
            zks.pendingSyncs.add(request);
            zks.getObserver().request(request);
            break;
          case OpCode.create:
          case OpCode.create2:
          case OpCode.delete:
          case OpCode.setData:
          case OpCode.reconfig:
          case OpCode.setACL:
          case OpCode.multi:
          case OpCode.check:
            zks.getObserver().request(request);
            break;
          case OpCode.createSession:
          case OpCode.closeSession:
            // Don't forward local sessions to the leader.
            if (!request.isLocalSession()) {
              zks.getObserver().request(request);
            }
            break;
        }
      }
    } catch (Exception e) {
      LOG.error("Unexpected exception causing exit", e);
    }
    LOG.info("ObserverRequestProcessor exited loop!");
  }
 /** Simply queue the request, which will be processed in FIFO order. */
 public void processRequest(Request request) {
   if (!finished) {
     Request upgradeRequest = null;
     try {
       upgradeRequest = zks.checkUpgradeSession(request);
     } catch (KeeperException ke) {
       if (request.getHdr() != null) {
         request.getHdr().setType(OpCode.error);
         request.setTxn(new ErrorTxn(ke.code().intValue()));
       }
       request.setException(ke);
       LOG.info("Error creating upgrade request", ke);
     } catch (IOException ie) {
       LOG.error("Unexpected error in upgrade", ie);
     }
     if (upgradeRequest != null) {
       queuedRequests.add(upgradeRequest);
     }
     queuedRequests.add(request);
   }
 }
 /**
  * Constructor - takes an ObserverZooKeeperServer to associate with and the next processor to pass
  * requests to after we're finished.
  *
  * @param zks
  * @param nextProcessor
  */
 public ObserverRequestProcessor(ObserverZooKeeperServer zks, RequestProcessor nextProcessor) {
   super("ObserverRequestProcessor:" + zks.getServerId());
   this.zks = zks;
   this.nextProcessor = nextProcessor;
 }