예제 #1
0
 void startAsyncDataSerivce() {
   if (asyncDataServiceStarted) {
     return;
   }
   fileContextCache.start();
   this.asyncDataService = new AsyncDataService();
   asyncDataServiceStarted = true;
 }
예제 #2
0
 void shutdownAsyncDataService() {
   if (!asyncDataServiceStarted) {
     return;
   }
   asyncDataServiceStarted = false;
   asyncDataService.shutdown();
   fileContextCache.shutdown();
 }
예제 #3
0
  void handleCommit(
      DFSClient dfsClient,
      FileHandle fileHandle,
      long commitOffset,
      Channel channel,
      int xid,
      Nfs3FileAttributes preOpAttr) {
    int status;
    OpenFileCtx openFileCtx = fileContextCache.get(fileHandle);

    if (openFileCtx == null) {
      LOG.info(
          "No opened stream for fileId:"
              + fileHandle.getFileId()
              + " commitOffset="
              + commitOffset
              + ". Return success in this case.");
      status = Nfs3Status.NFS3_OK;

    } else {
      COMMIT_STATUS ret =
          openFileCtx.checkCommit(dfsClient, commitOffset, channel, xid, preOpAttr, false);
      switch (ret) {
        case COMMIT_FINISHED:
        case COMMIT_INACTIVE_CTX:
          status = Nfs3Status.NFS3_OK;
          break;
        case COMMIT_INACTIVE_WITH_PENDING_WRITE:
        case COMMIT_ERROR:
          status = Nfs3Status.NFS3ERR_IO;
          break;
        case COMMIT_WAIT:
          // Do nothing. Commit is async now.
          return;
        case COMMIT_SPECIAL_WAIT:
          status = Nfs3Status.NFS3ERR_JUKEBOX;
          break;
        case COMMIT_SPECIAL_SUCCESS:
          status = Nfs3Status.NFS3_OK;
          break;
        default:
          LOG.error("Should not get commit return code:" + ret.name());
          throw new RuntimeException("Should not get commit return code:" + ret.name());
      }
    }

    // Send out the response
    Nfs3FileAttributes postOpAttr = null;
    try {
      postOpAttr = getFileAttr(dfsClient, new FileHandle(preOpAttr.getFileId()), iug);
    } catch (IOException e1) {
      LOG.info("Can't get postOpAttr for fileId: " + preOpAttr.getFileId(), e1);
    }
    WccData fileWcc = new WccData(Nfs3Utils.getWccAttr(preOpAttr), postOpAttr);
    COMMIT3Response response = new COMMIT3Response(status, fileWcc, Nfs3Constant.WRITE_COMMIT_VERF);
    Nfs3Utils.writeChannelCommit(
        channel, response.serialize(new XDR(), xid, new VerifierNone()), xid);
  }
예제 #4
0
 /** If the file is in cache, update the size based on the cached data size */
 Nfs3FileAttributes getFileAttr(
     DFSClient client, FileHandle fileHandle, IdMappingServiceProvider iug) throws IOException {
   String fileIdPath = Nfs3Utils.getFileIdPath(fileHandle);
   Nfs3FileAttributes attr = Nfs3Utils.getFileAttr(client, fileIdPath, iug);
   if (attr != null) {
     OpenFileCtx openFileCtx = fileContextCache.get(fileHandle);
     if (openFileCtx != null) {
       attr.setSize(openFileCtx.getNextOffset());
       attr.setUsed(openFileCtx.getNextOffset());
     }
   }
   return attr;
 }
예제 #5
0
  Nfs3FileAttributes getFileAttr(DFSClient client, FileHandle dirHandle, String fileName)
      throws IOException {
    String fileIdPath = Nfs3Utils.getFileIdPath(dirHandle) + "/" + fileName;
    Nfs3FileAttributes attr = Nfs3Utils.getFileAttr(client, fileIdPath, iug);

    if ((attr != null) && (attr.getType() == NfsFileType.NFSREG.toValue())) {
      OpenFileCtx openFileCtx = fileContextCache.get(new FileHandle(attr.getFileId()));

      if (openFileCtx != null) {
        attr.setSize(openFileCtx.getNextOffset());
        attr.setUsed(openFileCtx.getNextOffset());
      }
    }
    return attr;
  }
예제 #6
0
  // Do a possible commit before read request in case there is buffered data
  // inside DFSClient which has been flushed but not synced.
  int commitBeforeRead(DFSClient dfsClient, FileHandle fileHandle, long commitOffset) {
    int status;
    OpenFileCtx openFileCtx = fileContextCache.get(fileHandle);

    if (openFileCtx == null) {
      if (LOG.isDebugEnabled()) {
        LOG.debug(
            "No opened stream for fileId:"
                + fileHandle.getFileId()
                + " commitOffset="
                + commitOffset
                + ". Return success in this case.");
      }
      status = Nfs3Status.NFS3_OK;

    } else {
      COMMIT_STATUS ret = openFileCtx.checkCommit(dfsClient, commitOffset, null, 0, null, true);
      switch (ret) {
        case COMMIT_FINISHED:
        case COMMIT_INACTIVE_CTX:
          status = Nfs3Status.NFS3_OK;
          break;
        case COMMIT_INACTIVE_WITH_PENDING_WRITE:
        case COMMIT_ERROR:
          status = Nfs3Status.NFS3ERR_IO;
          break;
        case COMMIT_WAIT:
        case COMMIT_SPECIAL_WAIT:
          /**
           * This should happen rarely in some possible cases, such as read request arrives before
           * DFSClient is able to quickly flush data to DN, or Prerequisite writes is not available.
           * Won't wait since we don't want to block read.
           */
          status = Nfs3Status.NFS3ERR_JUKEBOX;
          break;
        case COMMIT_SPECIAL_SUCCESS:
          // Read beyond eof could result in partial read
          status = Nfs3Status.NFS3_OK;
          break;
        default:
          LOG.error("Should not get commit return code:" + ret.name());
          throw new RuntimeException("Should not get commit return code:" + ret.name());
      }
    }
    return status;
  }
예제 #7
0
 boolean addOpenFileStream(FileHandle h, OpenFileCtx ctx) {
   return fileContextCache.put(h, ctx);
 }
예제 #8
0
  void handleWrite(
      DFSClient dfsClient,
      WRITE3Request request,
      Channel channel,
      int xid,
      Nfs3FileAttributes preOpAttr)
      throws IOException {
    int count = request.getCount();
    byte[] data = request.getData().array();
    if (data.length < count) {
      WRITE3Response response = new WRITE3Response(Nfs3Status.NFS3ERR_INVAL);
      Nfs3Utils.writeChannel(channel, response.serialize(new XDR(), xid, new VerifierNone()), xid);
      return;
    }

    FileHandle handle = request.getHandle();
    if (LOG.isDebugEnabled()) {
      LOG.debug("handleWrite " + request);
    }

    // Check if there is a stream to write
    FileHandle fileHandle = request.getHandle();
    OpenFileCtx openFileCtx = fileContextCache.get(fileHandle);
    if (openFileCtx == null) {
      LOG.info("No opened stream for fileId:" + fileHandle.getFileId());

      String fileIdPath = Nfs3Utils.getFileIdPath(fileHandle.getFileId());
      HdfsDataOutputStream fos = null;
      Nfs3FileAttributes latestAttr = null;
      try {
        int bufferSize =
            config.getInt(
                CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_KEY,
                CommonConfigurationKeysPublic.IO_FILE_BUFFER_SIZE_DEFAULT);

        fos = dfsClient.append(fileIdPath, bufferSize, null, null);

        latestAttr = Nfs3Utils.getFileAttr(dfsClient, fileIdPath, iug);
      } catch (RemoteException e) {
        IOException io = e.unwrapRemoteException();
        if (io instanceof AlreadyBeingCreatedException) {
          LOG.warn(
              "Can't append file:"
                  + fileIdPath
                  + ". Possibly the file is being closed. Drop the request:"
                  + request
                  + ", wait for the client to retry...");
          return;
        }
        throw e;
      } catch (IOException e) {
        LOG.error("Can't apapend to file:" + fileIdPath, e);
        if (fos != null) {
          fos.close();
        }
        WccData fileWcc = new WccData(Nfs3Utils.getWccAttr(preOpAttr), preOpAttr);
        WRITE3Response response =
            new WRITE3Response(
                Nfs3Status.NFS3ERR_IO,
                fileWcc,
                count,
                request.getStableHow(),
                Nfs3Constant.WRITE_COMMIT_VERF);
        Nfs3Utils.writeChannel(
            channel, response.serialize(new XDR(), xid, new VerifierNone()), xid);
        return;
      }

      // Add open stream
      String writeDumpDir =
          config.get(
              NfsConfigKeys.DFS_NFS_FILE_DUMP_DIR_KEY, NfsConfigKeys.DFS_NFS_FILE_DUMP_DIR_DEFAULT);
      openFileCtx =
          new OpenFileCtx(
              fos,
              latestAttr,
              writeDumpDir + "/" + fileHandle.getFileId(),
              dfsClient,
              iug,
              aixCompatMode,
              config);

      if (!addOpenFileStream(fileHandle, openFileCtx)) {
        LOG.info("Can't add new stream. Close it. Tell client to retry.");
        try {
          fos.close();
        } catch (IOException e) {
          LOG.error("Can't close stream for fileId:" + handle.getFileId(), e);
        }
        // Notify client to retry
        WccData fileWcc = new WccData(latestAttr.getWccAttr(), latestAttr);
        WRITE3Response response =
            new WRITE3Response(
                Nfs3Status.NFS3ERR_JUKEBOX,
                fileWcc,
                0,
                request.getStableHow(),
                Nfs3Constant.WRITE_COMMIT_VERF);
        Nfs3Utils.writeChannel(
            channel, response.serialize(new XDR(), xid, new VerifierNone()), xid);
        return;
      }

      if (LOG.isDebugEnabled()) {
        LOG.debug("Opened stream for appending file:" + fileHandle.getFileId());
      }
    }

    // Add write into the async job queue
    openFileCtx.receivedNewWrite(dfsClient, request, channel, xid, asyncDataService, iug);
    return;
  }