30 import java.nio.ByteBuffer; 31 32 33 /** 34 * File-descriptor based I/O utilities that are shared by NIO classes. 35 */ 36 37 public class IOUtil { 38 39 /** 40 * Max number of iovec structures that readv/writev supports 41 */ 42 static final int IOV_MAX; 43 44 private IOUtil() { } // No instantiation 45 46 static int write(FileDescriptor fd, ByteBuffer src, long position, 47 NativeDispatcher nd) 48 throws IOException 49 { 50 if (src instanceof DirectBuffer) 51 return writeFromNativeBuffer(fd, src, position, nd); 52 53 // Substitute a native buffer 54 int pos = src.position(); 55 int lim = src.limit(); 56 assert (pos <= lim); 57 int rem = (pos <= lim ? lim - pos : 0); 58 ByteBuffer bb = Util.getTemporaryDirectBuffer(rem); 59 try { 60 bb.put(src); 61 bb.flip(); 62 // Do not update src until we see how many bytes were written 63 src.position(pos); 64 65 int n = writeFromNativeBuffer(fd, bb, position, nd); 66 if (n > 0) { 67 // now update src 68 src.position(pos + n); 69 } 70 return n; 71 } finally { 72 Util.offerFirstTemporaryDirectBuffer(bb); 73 } 74 } 75 76 private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, 77 long position, NativeDispatcher nd) 78 throws IOException 79 { 80 int pos = bb.position(); 81 int lim = bb.limit(); 82 assert (pos <= lim); 83 int rem = (pos <= lim ? lim - pos : 0); 84 85 int written = 0; 86 if (rem == 0) 87 return 0; 88 if (position != -1) { 89 written = nd.pwrite(fd, 90 ((DirectBuffer)bb).address() + pos, 91 rem, position); 92 } else { 93 written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem); 94 } 95 if (written > 0) 96 bb.position(pos + written); 97 return written; 98 } 99 100 static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) 101 throws IOException 102 { 103 return write(fd, bufs, 0, bufs.length, nd); 104 } 105 106 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 107 NativeDispatcher nd) 108 throws IOException 109 { 110 IOVecWrapper vec = IOVecWrapper.get(length); 111 112 boolean completed = false; 113 int iov_len = 0; 114 try { 115 116 // Iterate over buffers to populate native iovec array. 117 int count = offset + length; 118 int i = offset; 119 while (i < count && iov_len < IOV_MAX) { 120 ByteBuffer buf = bufs[i]; 121 int pos = buf.position(); 122 int lim = buf.limit(); 123 assert (pos <= lim); 124 int rem = (pos <= lim ? lim - pos : 0); 125 if (rem > 0) { 126 vec.setBuffer(iov_len, buf, pos, rem); 127 128 // allocate shadow buffer to ensure I/O is done with direct buffer 129 if (!(buf instanceof DirectBuffer)) { 130 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem); 131 shadow.put(buf); 132 shadow.flip(); 133 vec.setShadow(iov_len, shadow); 134 buf.position(pos); // temporarily restore position in user buffer 135 buf = shadow; 136 pos = shadow.position(); 137 } 138 139 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos); 140 vec.putLen(iov_len, rem); 141 iov_len++; 142 } 143 i++; 144 } 145 if (iov_len == 0) 146 return 0L; 147 148 long bytesWritten = nd.writev(fd, vec.address, iov_len); 149 150 // Notify the buffers how many bytes were taken 169 return bytesWritten; 170 171 } finally { 172 // if an error occurred then clear refs to buffers and return any shadow 173 // buffers to cache 174 if (!completed) { 175 for (int j=0; j<iov_len; j++) { 176 ByteBuffer shadow = vec.getShadow(j); 177 if (shadow != null) 178 Util.offerLastTemporaryDirectBuffer(shadow); 179 vec.clearRefs(j); 180 } 181 } 182 } 183 } 184 185 static int read(FileDescriptor fd, ByteBuffer dst, long position, 186 NativeDispatcher nd) 187 throws IOException 188 { 189 if (dst.isReadOnly()) 190 throw new IllegalArgumentException("Read-only buffer"); 191 if (dst instanceof DirectBuffer) 192 return readIntoNativeBuffer(fd, dst, position, nd); 193 194 // Substitute a native buffer 195 ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining()); 196 try { 197 int n = readIntoNativeBuffer(fd, bb, position, nd); 198 bb.flip(); 199 if (n > 0) 200 dst.put(bb); 201 return n; 202 } finally { 203 Util.offerFirstTemporaryDirectBuffer(bb); 204 } 205 } 206 207 private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, 208 long position, NativeDispatcher nd) 209 throws IOException 210 { 211 int pos = bb.position(); 212 int lim = bb.limit(); 213 assert (pos <= lim); 214 int rem = (pos <= lim ? lim - pos : 0); 215 216 if (rem == 0) 217 return 0; 218 int n = 0; 219 if (position != -1) { 220 n = nd.pread(fd, ((DirectBuffer)bb).address() + pos, 221 rem, position); 222 } else { 223 n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem); 224 } 225 if (n > 0) 226 bb.position(pos + n); 227 return n; 228 } 229 230 static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) 231 throws IOException 232 { 233 return read(fd, bufs, 0, bufs.length, nd); 234 } 235 236 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 237 NativeDispatcher nd) 238 throws IOException 239 { 240 IOVecWrapper vec = IOVecWrapper.get(length); 241 242 boolean completed = false; 243 int iov_len = 0; 244 try { 245 246 // Iterate over buffers to populate native iovec array. 247 int count = offset + length; 248 int i = offset; 249 while (i < count && iov_len < IOV_MAX) { 250 ByteBuffer buf = bufs[i]; 251 if (buf.isReadOnly()) 252 throw new IllegalArgumentException("Read-only buffer"); 253 int pos = buf.position(); 254 int lim = buf.limit(); 255 assert (pos <= lim); 256 int rem = (pos <= lim ? lim - pos : 0); 257 258 if (rem > 0) { 259 vec.setBuffer(iov_len, buf, pos, rem); 260 261 // allocate shadow buffer to ensure I/O is done with direct buffer 262 if (!(buf instanceof DirectBuffer)) { 263 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem); 264 vec.setShadow(iov_len, shadow); 265 buf = shadow; 266 pos = shadow.position(); 267 } 268 269 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos); 270 vec.putLen(iov_len, rem); 271 iov_len++; 272 } 273 i++; 274 } 275 if (iov_len == 0) 276 return 0L; 277 278 long bytesRead = nd.readv(fd, vec.address, iov_len); 279 280 // Notify the buffers how many bytes were read 281 long left = bytesRead; 282 for (int j=0; j<iov_len; j++) { 283 ByteBuffer shadow = vec.getShadow(j); | 30 import java.nio.ByteBuffer; 31 32 33 /** 34 * File-descriptor based I/O utilities that are shared by NIO classes. 35 */ 36 37 public class IOUtil { 38 39 /** 40 * Max number of iovec structures that readv/writev supports 41 */ 42 static final int IOV_MAX; 43 44 private IOUtil() { } // No instantiation 45 46 static int write(FileDescriptor fd, ByteBuffer src, long position, 47 NativeDispatcher nd) 48 throws IOException 49 { 50 return write(fd, src, position, false, -1, nd); 51 } 52 53 static int write(FileDescriptor fd, ByteBuffer src, long position, 54 boolean directIO, int alignment, NativeDispatcher nd) 55 throws IOException 56 { 57 if (src instanceof DirectBuffer) { 58 return writeFromNativeBuffer(fd, src, position, directIO, alignment, nd); 59 } 60 61 // Substitute a native buffer 62 int pos = src.position(); 63 int lim = src.limit(); 64 assert (pos <= lim); 65 int rem = (pos <= lim ? lim - pos : 0); 66 ByteBuffer bb; 67 if (directIO) { 68 if (rem % alignment != 0) 69 throw new IllegalArgumentException("DirectByteBuffer is not properly aligned"); 70 bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment); 71 } else { 72 bb = Util.getTemporaryDirectBuffer(rem); 73 } 74 try { 75 bb.put(src); 76 bb.flip(); 77 // Do not update src until we see how many bytes were written 78 src.position(pos); 79 80 int n = writeFromNativeBuffer(fd, bb, position, directIO, alignment, nd); 81 if (n > 0) { 82 // now update src 83 src.position(pos + n); 84 } 85 return n; 86 } finally { 87 Util.offerFirstTemporaryDirectBuffer(bb); 88 } 89 } 90 91 private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, long position, 92 boolean directIO, int alignment, NativeDispatcher nd) 93 throws IOException 94 { 95 int pos = bb.position(); 96 int lim = bb.limit(); 97 assert (pos <= lim); 98 int rem = (pos <= lim ? lim - pos : 0); 99 100 if (directIO && (bb.alignmentOffset(pos, alignment) != 0) && (rem % alignment != 0)) { 101 throw new IllegalArgumentException("DirectByteBuffer is not properly aligned"); 102 } 103 104 int written = 0; 105 if (rem == 0) 106 return 0; 107 if (position != -1) { 108 written = nd.pwrite(fd, 109 ((DirectBuffer)bb).address() + pos, 110 rem, position); 111 } else { 112 written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem); 113 } 114 if (written > 0) 115 bb.position(pos + written); 116 return written; 117 } 118 119 static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) 120 throws IOException 121 { 122 return write(fd, bufs, 0, bufs.length, false, -1, nd); 123 } 124 125 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 126 NativeDispatcher nd) 127 throws IOException 128 { 129 return write(fd, bufs, offset, length, false, -1, nd); 130 } 131 132 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 133 boolean directIO, int alignment, NativeDispatcher nd) 134 throws IOException 135 { 136 IOVecWrapper vec = IOVecWrapper.get(length); 137 138 boolean completed = false; 139 int iov_len = 0; 140 try { 141 142 // Iterate over buffers to populate native iovec array. 143 int count = offset + length; 144 int i = offset; 145 while (i < count && iov_len < IOV_MAX) { 146 ByteBuffer buf = bufs[i]; 147 int pos = buf.position(); 148 int lim = buf.limit(); 149 assert (pos <= lim); 150 int rem = (pos <= lim ? lim - pos : 0); 151 if (directIO && (rem % alignment != 0)) 152 throw new IllegalArgumentException("IO size or position is not aligned"); 153 154 if (rem > 0) { 155 vec.setBuffer(iov_len, buf, pos, rem); 156 157 // allocate shadow buffer to ensure I/O is done with direct buffer 158 if (!(buf instanceof DirectBuffer)) { 159 ByteBuffer shadow; 160 if (directIO) 161 shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment); 162 else 163 shadow = Util.getTemporaryDirectBuffer(rem); 164 shadow.put(buf); 165 shadow.flip(); 166 vec.setShadow(iov_len, shadow); 167 buf.position(pos); // temporarily restore position in user buffer 168 buf = shadow; 169 pos = shadow.position(); 170 } 171 172 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos); 173 vec.putLen(iov_len, rem); 174 iov_len++; 175 } 176 i++; 177 } 178 if (iov_len == 0) 179 return 0L; 180 181 long bytesWritten = nd.writev(fd, vec.address, iov_len); 182 183 // Notify the buffers how many bytes were taken 202 return bytesWritten; 203 204 } finally { 205 // if an error occurred then clear refs to buffers and return any shadow 206 // buffers to cache 207 if (!completed) { 208 for (int j=0; j<iov_len; j++) { 209 ByteBuffer shadow = vec.getShadow(j); 210 if (shadow != null) 211 Util.offerLastTemporaryDirectBuffer(shadow); 212 vec.clearRefs(j); 213 } 214 } 215 } 216 } 217 218 static int read(FileDescriptor fd, ByteBuffer dst, long position, 219 NativeDispatcher nd) 220 throws IOException 221 { 222 return read(fd, dst, position, false, -1, nd); 223 } 224 225 static int read(FileDescriptor fd, ByteBuffer dst, long position, 226 boolean directIO, int alignment, NativeDispatcher nd) 227 throws IOException 228 { 229 if (dst.isReadOnly()) 230 throw new IllegalArgumentException("Read-only buffer"); 231 if (dst instanceof DirectBuffer) 232 return readIntoNativeBuffer(fd, dst, position, directIO, alignment, nd); 233 234 // Substitute a native buffer 235 ByteBuffer bb; 236 if (directIO) { 237 if (dst.remaining() % alignment != 0) 238 throw new IllegalArgumentException("DirectByteBuffer is not properly aligned"); 239 bb = Util.getTemporaryAlignedDirectBuffer(dst.remaining(), alignment); 240 } else { 241 bb = Util.getTemporaryDirectBuffer(dst.remaining()); 242 } 243 try { 244 int n = readIntoNativeBuffer(fd, bb, position, directIO, alignment,nd); 245 bb.flip(); 246 if (n > 0) 247 dst.put(bb); 248 return n; 249 } finally { 250 Util.offerFirstTemporaryDirectBuffer(bb); 251 } 252 } 253 254 private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, long position, 255 boolean directIO, int alignment, NativeDispatcher nd) 256 throws IOException 257 { 258 int pos = bb.position(); 259 int lim = bb.limit(); 260 assert (pos <= lim); 261 int rem = (pos <= lim ? lim - pos : 0); 262 263 if(directIO && !(bb.alignmentOffset(pos, alignment) != 0) && (rem % alignment != 0)) 264 throw new IllegalArgumentException("DirectByteBuffer is not properly aligned"); 265 266 if (rem == 0) 267 return 0; 268 int n = 0; 269 if (position != -1) { 270 n = nd.pread(fd, ((DirectBuffer)bb).address() + pos, 271 rem, position); 272 } else { 273 n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem); 274 } 275 if (n > 0) 276 bb.position(pos + n); 277 return n; 278 } 279 280 static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd) 281 throws IOException 282 { 283 return read(fd, bufs, 0, bufs.length, false, -1, nd); 284 } 285 286 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 287 NativeDispatcher nd) 288 throws IOException 289 { 290 return read(fd, bufs, offset, bufs.length, false, -1, nd); 291 } 292 293 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, 294 boolean directIO, int alignment, NativeDispatcher nd) 295 throws IOException 296 { 297 IOVecWrapper vec = IOVecWrapper.get(length); 298 299 boolean completed = false; 300 int iov_len = 0; 301 try { 302 303 // Iterate over buffers to populate native iovec array. 304 int count = offset + length; 305 int i = offset; 306 while (i < count && iov_len < IOV_MAX) { 307 ByteBuffer buf = bufs[i]; 308 if (buf.isReadOnly()) 309 throw new IllegalArgumentException("Read-only buffer"); 310 int pos = buf.position(); 311 int lim = buf.limit(); 312 assert (pos <= lim); 313 int rem = (pos <= lim ? lim - pos : 0); 314 315 if (directIO && (rem % alignment != 0)) 316 throw new IllegalArgumentException("IO size or position is not aligned"); 317 318 if (rem > 0) { 319 vec.setBuffer(iov_len, buf, pos, rem); 320 321 // allocate shadow buffer to ensure I/O is done with direct buffer 322 if (!(buf instanceof DirectBuffer)) { 323 ByteBuffer shadow; 324 if (directIO) { 325 shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment); 326 } else { 327 shadow = Util.getTemporaryDirectBuffer(rem); 328 } 329 vec.setShadow(iov_len, shadow); 330 buf = shadow; 331 pos = shadow.position(); 332 } 333 334 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos); 335 vec.putLen(iov_len, rem); 336 iov_len++; 337 } 338 i++; 339 } 340 if (iov_len == 0) 341 return 0L; 342 343 long bytesRead = nd.readv(fd, vec.address, iov_len); 344 345 // Notify the buffers how many bytes were read 346 long left = bytesRead; 347 for (int j=0; j<iov_len; j++) { 348 ByteBuffer shadow = vec.getShadow(j); |