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 17package java.nio; 18 19import android.system.ErrnoException; 20import java.io.FileDescriptor; 21import java.io.IOException; 22import 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 */ 28final 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