Beispiel #1
0
  private ByteList bufferedRead(int number) throws IOException, BadDescriptorException {
    checkReadable();
    ensureRead();

    int resultSize = 0;

    // 128K seems to be the minimum at which the stat+seek is faster than reallocation
    final int BULK_THRESHOLD = 128 * 1024;
    if (number >= BULK_THRESHOLD
        && descriptor.isSeekable()
        && descriptor.getChannel() instanceof FileChannel) {
      //
      // If it is a file channel, then we can pre-allocate the output buffer
      // to the total size of buffered + remaining bytes in file
      //
      FileChannel fileChannel = (FileChannel) descriptor.getChannel();
      resultSize =
          (int)
              Math.min(
                  fileChannel.size() - fileChannel.position() + bufferedInputBytesRemaining(),
                  number);
    } else {
      //
      // Cannot discern the total read length - allocate at least enough for the buffered data
      //
      resultSize = Math.min(bufferedInputBytesRemaining(), number);
    }

    ByteList result = new ByteList(resultSize);
    bufferedRead(result, number);
    return result;
  }
Beispiel #2
0
 private void resetForWrite() throws IOException {
   if (descriptor.isSeekable()) {
     FileChannel fileChannel = (FileChannel) descriptor.getChannel();
     if (buffer.hasRemaining()) { // we have read ahead, and need to back up
       fileChannel.position(fileChannel.position() - buffer.remaining());
     }
   }
   // FIXME: Clearing read buffer here...is this appropriate?
   buffer.clear();
   reading = false;
 }
Beispiel #3
0
 /** @throws IOException */
 public synchronized long fgetpos()
     throws IOException, PipeException, InvalidValueException, BadDescriptorException {
   // Correct position for read / write buffering (we could invalidate, but expensive)
   if (descriptor.isSeekable()) {
     FileChannel fileChannel = (FileChannel) descriptor.getChannel();
     long pos = fileChannel.position();
     // Adjust for buffered data
     if (reading) {
       pos -= buffer.remaining();
       return pos - (pos > 0 && ungotc != -1 ? 1 : 0);
     } else {
       return pos + buffer.position();
     }
   } else if (descriptor.isNull()) {
     return 0;
   } else {
     throw new PipeException();
   }
 }
Beispiel #4
0
 /**
  * Implementation of libc "lseek", which seeks on seekable streams, raises EPIPE if the fd is
  * assocated with a pipe, socket, or FIFO, and doesn't do anything for other cases (like stdio).
  *
  * @throws IOException
  * @throws InvalidValueException
  */
 public synchronized void lseek(long offset, int type)
     throws IOException, InvalidValueException, PipeException, BadDescriptorException {
   if (descriptor.isSeekable()) {
     FileChannel fileChannel = (FileChannel) descriptor.getChannel();
     ungotc = -1;
     int adj = 0;
     if (reading) {
       // for SEEK_CUR, need to adjust for buffered data
       adj = buffer.remaining();
       buffer.clear();
       buffer.flip();
     } else {
       flushWrite();
     }
     try {
       switch (type) {
         case SEEK_SET:
           fileChannel.position(offset);
           break;
         case SEEK_CUR:
           fileChannel.position(fileChannel.position() - adj + offset);
           break;
         case SEEK_END:
           fileChannel.position(fileChannel.size() + offset);
           break;
       }
     } catch (IllegalArgumentException e) {
       throw new InvalidValueException();
     } catch (IOException ioe) {
       throw ioe;
     }
   } else if (descriptor.getChannel() instanceof SelectableChannel) {
     // TODO: It's perhaps just a coincidence that all the channels for
     // which we should raise are instanceof SelectableChannel, since
     // stdio is not...so this bothers me slightly. -CON
     throw new PipeException();
   } else {
   }
 }
Beispiel #5
0
  /**
   * @deprecated readall do busy loop for the IO which has NONBLOCK bit. You should implement the
   *     logic by yourself with fread().
   */
  @Deprecated
  public synchronized ByteList readall() throws IOException, BadDescriptorException {
    final long fileSize =
        descriptor.isSeekable() && descriptor.getChannel() instanceof FileChannel
            ? ((FileChannel) descriptor.getChannel()).size()
            : 0;
    //
    // Check file size - special files in /proc have zero size and need to be
    // handled by the generic read path.
    //
    if (fileSize > 0) {
      ensureRead();

      FileChannel channel = (FileChannel) descriptor.getChannel();
      final long left = fileSize - channel.position() + bufferedInputBytesRemaining();
      if (left <= 0) {
        eof = true;
        return null;
      }

      if (left > Integer.MAX_VALUE) {
        if (getRuntime() != null) {
          throw getRuntime().newIOError("File too large");
        } else {
          throw new IOException("File too large");
        }
      }

      ByteList result = new ByteList((int) left);
      ByteBuffer buf = ByteBuffer.wrap(result.getUnsafeBytes(), result.begin(), (int) left);

      //
      // Copy any buffered data (including ungetc byte)
      //
      copyBufferedBytes(buf);

      //
      // Now read unbuffered directly from the file
      //
      while (buf.hasRemaining()) {
        final int MAX_READ_CHUNK = 1 * 1024 * 1024;
        //
        // When reading into a heap buffer, the jvm allocates a temporary
        // direct ByteBuffer of the requested size.  To avoid allocating
        // a huge direct buffer when doing ludicrous reads (e.g. 1G or more)
        // we split the read up into chunks of no more than 1M
        //
        ByteBuffer tmp = buf.duplicate();
        if (tmp.remaining() > MAX_READ_CHUNK) {
          tmp.limit(tmp.position() + MAX_READ_CHUNK);
        }
        int n = channel.read(tmp);
        if (n <= 0) {
          break;
        }
        buf.position(tmp.position());
      }
      eof = true;
      result.length(buf.position());
      return result;
    } else if (descriptor.isNull()) {
      return new ByteList(0);
    } else {
      checkReadable();

      ByteList byteList = new ByteList();
      ByteList read = fread(BUFSIZE);

      if (read == null) {
        eof = true;
        return byteList;
      }

      while (read != null) {
        byteList.append(read);
        read = fread(BUFSIZE);
      }

      return byteList;
    }
  }