/**
  * Get the driver state from the session.
  *
  * @param sess
  * @return the driver state.
  */
 private DriverState getDriverState(SrvSession sess) {
   synchronized (sess) {
     // Get the driver state
     Object state = sess.getDriverState();
     if (state == null) {
       state = new DriverState();
       sess.setDriverState(state);
       if (logger.isDebugEnabled()) {
         logger.debug("new driver state created");
       }
     }
     DriverState driverState = (DriverState) state;
     return driverState;
   }
 }
  /**
   * Check if the domain name matches the access control domain name and return the allowed access.
   *
   * @param sess SrvSession
   * @param share SharedDevice
   * @param mgr AccessControlManager
   * @return int
   */
  public int allowsAccess(SrvSession sess, SharedDevice share, AccessControlManager mgr) {

    //	Check if the session has client information

    if (sess.hasClientInformation() == false || sess instanceof SMBSrvSession == false)
      return Default;

    //	Check if the domain name matches the access control name

    ClientInfo cInfo = sess.getClientInformation();

    if (cInfo.getDomain() != null && cInfo.getDomain().equalsIgnoreCase(getName()))
      return getAccess();
    return Default;
  }
  /**
   * Release space to the free space for the filesystem.
   *
   * @param sess SrvSession
   * @param tree TreeConnection
   * @param fid int
   * @param path String
   * @param alloc long
   * @exception IOException
   */
  public void releaseSpace(SrvSession sess, TreeConnection tree, int fid, String path, long alloc)
      throws IOException {

    // Check if content usage is enabled

    if (m_usageService.getEnabled() == false) return;

    // Check if there is a live usage record for the user

    UserQuotaDetails userQuota = getQuotaDetails(sess, true);

    if (userQuota != null) {

      synchronized (userQuota) {

        // Release the space from the live usage value

        userQuota.subtractFromCurrentUsage(alloc);
      }

      // DEBUG

      if (logger.isDebugEnabled())
        logger.debug("Released " + alloc + " bytes, userQuota=" + userQuota);
    } else if (logger.isDebugEnabled())
      logger.debug("Failed to release " + alloc + " bytes for sess " + sess.getUniqueId());
  }
  /**
   * Allocate space on the filesystem.
   *
   * @param sess SrvSession
   * @param tree TreeConnection
   * @param file NetworkFile
   * @param alloc long requested allocation size
   * @return long granted allocation size
   * @exception IOException
   */
  public long allocateSpace(SrvSession sess, TreeConnection tree, NetworkFile file, long alloc)
      throws IOException {

    // Check if content usage is enabled

    if (m_usageService.getEnabled() == false) return alloc;

    // Check if there is a live usage record for the user

    UserQuotaDetails userQuota = getQuotaDetails(sess, true);
    long allowedAlloc = 0L;

    if (userQuota != null) {

      // Check if the user has a usage quota

      synchronized (userQuota) {
        if (userQuota.hasUserQuota()) {

          // Check if the user has enough free space allocation

          if (alloc > 0 && userQuota.getAvailableSpace() >= alloc) {
            userQuota.addToCurrentUsage(alloc);
            allowedAlloc = alloc;
          }
        } else {

          // Update the live usage
          userQuota.addToCurrentUsage(alloc);
          allowedAlloc = alloc;
        }
      }
    } else if (logger.isDebugEnabled())
      logger.debug("Failed to allocate " + alloc + " bytes for sess " + sess.getUniqueId());

    // Check if the allocation was allowed

    if (allowedAlloc < alloc) {

      // DEBUG

      if (logger.isDebugEnabled()) logger.debug("Allocation failed userQuota=" + userQuota);

      throw new DiskFullException();
    } else if (logger.isDebugEnabled())
      logger.debug("Allocated " + alloc + " bytes, userQuota=" + userQuota);

    // Return the allocation size

    return allowedAlloc;
  }
  /**
   * Close the network file
   *
   * @param sess SrvSession
   * @param netFile NetworkFile
   * @exception IOException
   */
  public void closeFile(SrvSession sess, NetworkFile netFile) throws IOException {

    // Close the cached network file

    if (netFile instanceof CachedNetworkFile) {

      // Get the cached network file

      CachedNetworkFile cacheFile = (CachedNetworkFile) netFile;
      cacheFile.closeFile();

      // Get the file segment details

      FileSegment fileSeg = cacheFile.getFileSegment();

      // Check if the file data has been updated, if so then queue a file save

      if (fileSeg.isUpdated() && netFile.hasDeleteOnClose() == false) {

        // Set the modified date/time and file size for the file

        File tempFile = new File(fileSeg.getTemporaryFile());

        netFile.setModifyDate(tempFile.lastModified());
        netFile.setFileSize(tempFile.length());

        // Queue a file save request to save the data back to the repository, if not already queued

        if (fileSeg.isSaveQueued() == false) {

          // Create a file save request for the updated file segment

          SingleFileRequest fileReq =
              new SingleFileRequest(
                  FileRequest.SAVE,
                  cacheFile.getFileId(),
                  cacheFile.getStreamId(),
                  fileSeg.getInfo(),
                  netFile.getFullName(),
                  cacheFile.getFileState());

          // Check if there are any attributes to be added to the file request

          if (hasRequiredAttributes() && sess != null) {

            // Check if the user name is required

            if (m_reqAttributes.containsString(FileRequest.AttrUserName)) {

              // Add the user name attribute

              ClientInfo cInfo = sess.getClientInformation();
              String userName = "";

              if (cInfo != null && cInfo.getUserName() != null) userName = cInfo.getUserName();

              fileReq.addAttribute(new NameValue(FileRequest.AttrUserName, userName));
            }

            // Check if the protocol type is required

            if (m_reqAttributes.containsString(FileRequest.AttrProtocol)) {

              // Add the protocol type attribute

              fileReq.addAttribute(new NameValue(FileRequest.AttrProtocol, sess.getProtocolName()));
            }
          }

          // Set the file segment status

          fileSeg.setStatus(FileSegmentInfo.SaveWait, true);

          // Queue the file save request

          queueFileRequest(fileReq);
        } else if (Debug.EnableInfo && hasDebug()) {

          // DEBUG

          Debug.println("## FileLoader Save already queued for " + fileSeg);
        }
      }

      // Update the cache timeout for the temporary file if there are no references to the file. If
      // the file was
      // opened for sequential access only it will be expired quicker.

      else if (cacheFile.getFileState().getOpenCount() == 0) {

        // If the file was opened for sequential access only then we can delete it from the
        // temporary area
        // sooner

        long tmo = System.currentTimeMillis();

        if (cacheFile.isSequentialOnly()) tmo += SequentialFileExpire;
        else tmo += m_stateCache.getFileStateExpireInterval();

        // Set the file state expiry, the local file data will be deleted when the file state
        // expires (if there
        // are still no references to the file).

        cacheFile.getFileState().setExpiryTime(tmo);
      }

      // If the database is not online and the file is marked for delete then queue a delete file
      // request to do
      // the
      // delete when the database is back online

      if (m_dbCtx.isAvailable() == false && netFile.hasDeleteOnClose()) {

        // Queue an offline delete request for the file

        DeleteFileRequest deleteReq =
            new DeleteFileRequest(
                cacheFile.getFileId(),
                cacheFile.getStreamId(),
                fileSeg.getTemporaryFile(),
                cacheFile.getFullNameStream(),
                cacheFile.getFileState());
        m_dbCtx.addOfflineFileDelete(deleteReq);

        // DEBUG

        if (Debug.EnableInfo && hasDebug())
          Debug.println("## FileLoader queued offline delete, " + deleteReq);
      }
    }
  }