Home | History | Annotate | Download | only in nio
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package java.nio;
     18 
     19 import android.system.ErrnoException;
     20 import java.io.FileDescriptor;
     21 import java.io.IOException;
     22 import libcore.io.Libcore;
     23 
     24 /**
     25  * Used to implement java.nio read(ByteBuffer[])/write(ByteBuffer[]) operations as POSIX readv(2)
     26  * and writev(2) calls.
     27  */
     28 final class IoVec {
     29     enum Direction { READV, WRITEV };
     30 
     31     private final ByteBuffer[] byteBuffers;
     32     private final int offset;
     33     private final int bufferCount;
     34 
     35     private final Object[] ioBuffers;
     36     private final int[] offsets;
     37     private final int[] byteCounts;
     38 
     39     private final Direction direction;
     40 
     41     IoVec(ByteBuffer[] byteBuffers, int offset, int bufferCount, Direction direction) {
     42         this.byteBuffers = byteBuffers;
     43         this.offset = offset;
     44         this.bufferCount = bufferCount;
     45         this.direction = direction;
     46         this.ioBuffers = new Object[bufferCount];
     47         this.offsets = new int[bufferCount];
     48         this.byteCounts = new int[bufferCount];
     49     }
     50 
     51     int init() {
     52         int totalRemaining = 0;
     53         for (int i = 0; i < bufferCount; ++i) {
     54             ByteBuffer b = byteBuffers[i + offset];
     55             if (direction == Direction.READV) {
     56                 b.checkWritable();
     57             }
     58             int remaining = b.remaining();
     59             if (b.isDirect()) {
     60                 ioBuffers[i] = b;
     61                 offsets[i] = b.position();
     62             } else {
     63                 ioBuffers[i] = NioUtils.unsafeArray(b);
     64                 offsets[i] = NioUtils.unsafeArrayOffset(b) + b.position();
     65             }
     66             byteCounts[i] = remaining;
     67             totalRemaining += remaining;
     68         }
     69         return totalRemaining;
     70     }
     71 
     72     int doTransfer(FileDescriptor fd) throws IOException {
     73         try {
     74             if (direction == Direction.READV) {
     75                 int result = Libcore.os.readv(fd, ioBuffers, offsets, byteCounts);
     76                 if (result == 0) {
     77                     result = -1;
     78                 }
     79                 return result;
     80             } else {
     81                 return Libcore.os.writev(fd, ioBuffers, offsets, byteCounts);
     82             }
     83         } catch (ErrnoException errnoException) {
     84             throw errnoException.rethrowAsIOException();
     85         }
     86     }
     87 
     88     void didTransfer(int byteCount) {
     89         for (int i = 0; byteCount > 0 && i < bufferCount; ++i) {
     90             ByteBuffer b = byteBuffers[i + offset];
     91             if (byteCounts[i] < byteCount) {
     92                 b.position(b.limit());
     93                 byteCount -= byteCounts[i];
     94             } else {
     95                 b.position((direction == Direction.WRITEV ? b.position() : 0) + byteCount);
     96                 byteCount = 0;
     97             }
     98         }
     99     }
    100 }
    101