code: @Override
    public int open(String path, FuseFileInfo fi) {
      final AlluxioURI uri = mPathResolverCache.getUnchecked(path);
      // (see {@code man 2 open} for the structure of the flags bitfield)
      // File creation flags are the last two bits of flags
      final int flags = fi.flags.get();
      LOG.trace("open({}, 0x{}) [Alluxio: {}]", path, Integer.toHexString(flags), uri);
  
      try {
        final URIStatus status = mFileSystem.getStatus(uri);
        if (status.isFolder()) {
          LOG.error("Cannot open folder {}", path);
          return -ErrorCodes.EISDIR();
        }
  
        if (!status.isCompleted() && !waitForFileCompleted(uri)) {
          LOG.error("Cannot open incomplete folder {}", path);
          return -ErrorCodes.EFAULT();
        }
  
        if (mOpenFiles.size() >= MAX_OPEN_FILES) {
          LOG.error("Cannot open {}: too many open files (MAX_OPEN_FILES: {})", path, MAX_OPEN_FILES);
          return ErrorCodes.EMFILE();
        }
  
        FileInStream is = mFileSystem.openFile(uri);
        synchronized (mOpenFiles) {
          mOpenFiles.add(new OpenFileEntry(mNextOpenFileId, path, is, null));
          fi.fh.set(mNextOpenFileId);
          // Assuming I will never wrap around (2^64 open files are quite a lot anyway)
          mNextOpenFileId += 1;
        }
      } catch (FileDoesNotExistException | InvalidPathException e) {
        LOG.debug("Failed to open file {}, path does not exist or is invalid", path);
        return -ErrorCodes.ENOENT();
      } catch (Throwable t) {
        LOG.error("Failed to open file {}", path, t);
        return AlluxioFuseUtils.getErrorCode(t);
      }
  
      return 0;
    }
docs: Opens an existing file for reading.
  
  Note that the opening an existing file would fail, because of Alluxio's write-once semantics.
  
  @param path the FS path of the file to open
  @param fi FileInfo data structure kept by FUSE
  @return 0 on success, a negative value on error