/**
   * Fail any deferred requests that are attached to this oplock, and clear the deferred list
   *
   * @return int Number of deferred requests that were failed
   */
  public int failDeferredRequests() {

    // Check if there are any deferred requests

    if (m_deferredRequests == null) return 0;

    int failCnt = 0;

    synchronized (m_deferredRequests) {
      for (DeferredRequest deferReq : m_deferredRequests) {

        // Get the deferred session/packet details

        SMBSrvSession sess = deferReq.getDeferredSession();
        SMBSrvPacket pkt = deferReq.getDeferredPacket();

        try {

          // Return an error for the deferred file open request

          if (sess.sendAsyncErrorResponseSMB(pkt, SMBStatus.NTAccessDenied, SMBStatus.NTErr)
              == true) {

            // Update the failed request count

            failCnt++;

            // DEBUG

            if (Debug.EnableDbg && sess.hasDebug(SMBSrvSession.DBG_OPLOCK))
              Debug.println("Oplock break timeout, oplock=" + this);
          } else if (Debug.EnableDbg && sess.hasDebug(SMBSrvSession.DBG_OPLOCK))
            Debug.println("Failed to send open reject, oplock break timed out, oplock=" + this);
        } catch (IOException ex) {

        } finally {

          // Make sure the packet is released back to the memory pool

          if (pkt != null) sess.getPacketPool().releasePacket(pkt);
        }
      }

      // Clear the deferred request list

      m_deferredRequests.clear();
    }

    // Return the count of failed requests

    return failCnt;
  }
  /**
   * Requeue deferred requests to the thread pool for processing, oplock has been released
   *
   * @return int Number of deferred requests requeued
   */
  public int requeueDeferredRequests() {

    // Check if there are any deferred requests

    if (m_deferredRequests == null) return 0;

    int requeueCnt = 0;

    synchronized (m_deferredRequests) {
      for (DeferredRequest deferReq : m_deferredRequests) {

        // Get the deferred session/packet details

        SMBSrvSession sess = deferReq.getDeferredSession();
        SMBSrvPacket pkt = deferReq.getDeferredPacket();

        // DEBUG

        if (Debug.EnableDbg && sess.hasDebug(SMBSrvSession.DBG_OPLOCK))
          Debug.println(
              "Release oplock, queued deferred request to thread pool sess="
                  + sess.getUniqueId()
                  + ", pkt="
                  + pkt);

        try {

          // Queue the deferred request to the thread pool for processing

          sess.getThreadPool().queueRequest(new CIFSThreadRequest(sess, pkt));
        } catch (Throwable ex) {

          // Failed to queue the request to the thread pool, release the deferred packet back to the
          // memory pool

          sess.getPacketPool().releasePacket(pkt);
        }
      }

      // Clear the deferred request list

      m_deferredRequests.clear();
    }

    // Return the count of requeued requests

    return requeueCnt;
  }
  /**
   * Add a deferred session/packet, whilst an oplock break is in progress
   *
   * @param deferredSess SMBSrvSession
   * @param deferredPkt SMBSrvPacket
   * @exception DeferFailedException If the session/packet cannot be deferred
   */
  public void addDeferredSession(SMBSrvSession deferredSess, SMBSrvPacket deferredPkt)
      throws DeferFailedException {

    // Allocate the deferred request list, if required

    if (m_deferredRequests == null) {
      synchronized (this) {
        if (m_deferredRequests == null)
          m_deferredRequests = new ArrayList<DeferredRequest>(MaxDeferredRequests);
      }
    }

    // Add the request to the list if there are spare slots

    synchronized (m_deferredRequests) {
      if (m_deferredRequests.size() < MaxDeferredRequests) {

        // Add the deferred request to the list

        m_deferredRequests.add(new DeferredRequest(deferredSess, deferredPkt));

        // Update the deferred processing count for the CIFS packet

        deferredPkt.incrementDeferredCount();

        // Set the time that the oplock break was sent to the client, if this is the first deferred
        // request

        if (m_deferredRequests.size() == 1) m_oplockBreakTime = System.currentTimeMillis();

        // DEBUG

        if (Debug.EnableDbg && deferredSess.hasDebug(SMBSrvSession.DBG_OPLOCK))
          Debug.println(
              "Added deferred request, list=" + m_deferredRequests.size() + ", oplock=" + this);
      } else throw new DeferFailedException("No more deferred slots available on oplock");
    }
  }
  /** Run the CIFS request */
  public void runRequest() {

    // Check if the session is still alive

    if (m_sess.isShutdown() == false) {

      SMBSrvPacket smbPkt = null;

      try {

        // Get the packet handler and read in the CIFS request

        WinsockNetBIOSPacketHandler pktHandler =
            (WinsockNetBIOSPacketHandler) m_sess.getPacketHandler();
        smbPkt = pktHandler.readPacket();

        // Clear the read in progress flag for the session

        m_sess.setReadInProgress(false);

        // DEBUG

        //				Debug.println("[SMB] Read packet, sess=" + m_sess.getUniqueId() + " ,pkt=" + smbPkt);

        // If the request packet is not valid then close the session

        if (smbPkt == null) {

          // Close the session

          m_sess.hangupSession("Client closed socket");
        } else {

          // Re-enable read events for this socket channel

          //					m_reqHandler.requeueSocketEvent( m_socketEvent,
          // pktHandler.getSocket().getSocket());
        }

        // Process the CIFS request

        m_sess.processPacket(smbPkt);
        smbPkt = null;

        // Process any asynchronous packets (oplock breaks and change notifications)

        int asyncCnt = m_sess.sendQueuedAsyncResponses();

        // DEBUG

        if (asyncCnt > 0 && Debug.EnableInfo && m_sess.hasDebug(SMBSrvSession.DBG_SOCKET))
          Debug.println(
              "Sent queued async packets (JNI/NIO) count="
                  + asyncCnt
                  + ", sess="
                  + m_sess.getUniqueId()
                  + ", addr="
                  + m_sess.getRemoteAddress().getHostAddress());
      } catch (Throwable ex) {
        Debug.println(ex);
      } finally {

        // Make sure the request packet is returned to the pool

        if (smbPkt != null) m_sess.getPacketPool().releasePacket(smbPkt);
      }
    }
  }