OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [gnu/] [java/] [nio/] [channels/] [FileChannelImpl.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* FileChannelImpl.java --
2
   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.java.nio.channels;
40
 
41
import gnu.classpath.Configuration;
42
import gnu.java.nio.FileLockImpl;
43
 
44
import java.io.File;
45
import java.io.FileNotFoundException;
46
import java.io.IOException;
47
import java.nio.ByteBuffer;
48
import java.nio.MappedByteBuffer;
49
import java.nio.channels.ClosedChannelException;
50
import java.nio.channels.FileChannel;
51
import java.nio.channels.FileLock;
52
import java.nio.channels.NonReadableChannelException;
53
import java.nio.channels.NonWritableChannelException;
54
import java.nio.channels.ReadableByteChannel;
55
import java.nio.channels.WritableByteChannel;
56
 
57
/**
58
 * This file is not user visible !
59
 * But alas, Java does not have a concept of friendly packages
60
 * so this class is public.
61
 * Instances of this class are created by invoking getChannel
62
 * Upon a Input/Output/RandomAccessFile object.
63
 */
64
public final class FileChannelImpl extends FileChannel
65
{
66
  // These are mode values for open().
67
  public static final int READ   = 1;
68
  public static final int WRITE  = 2;
69
  public static final int APPEND = 4;
70
 
71
  // EXCL is used only when making a temp file.
72
  public static final int EXCL   = 8;
73
  public static final int SYNC   = 16;
74
  public static final int DSYNC  = 32;
75
 
76
  public static FileChannelImpl in;
77
  public static FileChannelImpl out;
78
  public static FileChannelImpl err;
79
 
80
  private static native void init();
81
 
82
  static
83
  {
84
    if (Configuration.INIT_LOAD_LIBRARY)
85
      {
86
        System.loadLibrary("javanio");
87
      }
88
 
89
    init();
90
 
91
    in  = new FileChannelImpl(0, READ);
92
    out = new FileChannelImpl(1, WRITE);
93
    err = new FileChannelImpl(2, WRITE);
94
  }
95
 
96
  /**
97
   * This is the actual native file descriptor value
98
   */
99
  // System's notion of file descriptor.  It might seem redundant to
100
  // initialize this given that it is reassigned in the constructors.
101
  // However, this is necessary because if open() throws an exception
102
  // we want to make sure this has the value -1.  This is the most
103
  // efficient way to accomplish that.
104
  private int fd = -1;
105
 
106
  private int mode;
107
 
108
  final String description;
109
 
110
  /* Open a file.  MODE is a combination of the above mode flags. */
111
  /* This is a static factory method, so that VM implementors can decide
112
   * substitute subclasses of FileChannelImpl. */
113
  public static FileChannelImpl create(File file, int mode)
114
    throws FileNotFoundException
115
  {
116
    return new FileChannelImpl(file, mode);
117
  }
118
 
119
  private FileChannelImpl(File file, int mode)
120
    throws FileNotFoundException
121
  {
122
    String path = file.getPath();
123
    description = path;
124
    fd = open (path, mode);
125
    this.mode = mode;
126
 
127
    // First open the file and then check if it is a a directory
128
    // to avoid race condition.
129
    if (file.isDirectory())
130
      {
131
        try
132
          {
133
              close();
134
          }
135
        catch (IOException e)
136
          {
137
              /* ignore it */
138
          }
139
 
140
        throw new FileNotFoundException(description + " is a directory");
141
      }
142
  }
143
 
144
  /**
145
   * Constructor for default channels in, out and err.
146
   *
147
   * Used by init() (native code).
148
   *
149
   * @param fd the file descriptor (0, 1, 2 for stdin, stdout, stderr).
150
   *
151
   * @param mode READ or WRITE
152
   */
153
  FileChannelImpl (int fd, int mode)
154
  {
155
    this.fd = fd;
156
    this.mode = mode;
157
    this.description = "descriptor(" + fd + ")";
158
  }
159
 
160
  private native int open (String path, int mode) throws FileNotFoundException;
161
 
162
  public native int available () throws IOException;
163
  private native long implPosition () throws IOException;
164
  private native void seek (long newPosition) throws IOException;
165
  private native void implTruncate (long size) throws IOException;
166
 
167
  public native void unlock (long pos, long len) throws IOException;
168
 
169
  public native long size () throws IOException;
170
 
171
  protected native void implCloseChannel() throws IOException;
172
 
173
  /**
174
   * Makes sure the Channel is properly closed.
175
   */
176
  protected void finalize() throws IOException
177
  {
178
    if (fd != -1)
179
      close();
180
  }
181
 
182
  public int read (ByteBuffer dst) throws IOException
183
  {
184
    int result;
185
    byte[] buffer = new byte [dst.remaining ()];
186
 
187
    result = read (buffer, 0, buffer.length);
188
 
189
    if (result > 0)
190
      dst.put (buffer, 0, result);
191
 
192
    return result;
193
  }
194
 
195
  public int read (ByteBuffer dst, long position)
196
    throws IOException
197
  {
198
    if (position < 0)
199
      throw new IllegalArgumentException ("position: " + position);
200
    long oldPosition = implPosition ();
201
    position (position);
202
    int result = read(dst);
203
    position (oldPosition);
204
 
205
    return result;
206
  }
207
 
208
  public native int read ()
209
    throws IOException;
210
 
211
  public native int read (byte[] buffer, int offset, int length)
212
    throws IOException;
213
 
214
  public long read (ByteBuffer[] dsts, int offset, int length)
215
    throws IOException
216
  {
217
    long result = 0;
218
 
219
    for (int i = offset; i < offset + length; i++)
220
      {
221
        result += read (dsts [i]);
222
      }
223
 
224
    return result;
225
  }
226
 
227
  public int write (ByteBuffer src) throws IOException
228
  {
229
    int len = src.remaining ();
230
    if (src.hasArray())
231
      {
232
        byte[] buffer = src.array();
233
        write(buffer, src.arrayOffset() + src.position(), len);
234
        src.position(src.position() + len);
235
      }
236
    else
237
      {
238
        // Use a more efficient native method! FIXME!
239
        byte[] buffer = new byte [len];
240
        src.get (buffer, 0, len);
241
        write (buffer, 0, len);
242
      }
243
    return len;
244
  }
245
 
246
  public int write (ByteBuffer src, long position)
247
    throws IOException
248
  {
249
    if (position < 0)
250
      throw new IllegalArgumentException ("position: " + position);
251
 
252
    if (!isOpen ())
253
      throw new ClosedChannelException ();
254
 
255
    if ((mode & WRITE) == 0)
256
       throw new NonWritableChannelException ();
257
 
258
    int result;
259
    long oldPosition;
260
 
261
    oldPosition = implPosition ();
262
    seek (position);
263
    result = write(src);
264
    seek (oldPosition);
265
 
266
    return result;
267
  }
268
 
269
  public native void write (byte[] buffer, int offset, int length)
270
    throws IOException;
271
 
272
  public native void write (int b) throws IOException;
273
 
274
  public long write(ByteBuffer[] srcs, int offset, int length)
275
    throws IOException
276
  {
277
    long result = 0;
278
 
279
    for (int i = offset;i < offset + length;i++)
280
      {
281
        result += write (srcs[i]);
282
      }
283
 
284
    return result;
285
  }
286
 
287
  public native MappedByteBuffer mapImpl (char mode, long position, int size)
288
    throws IOException;
289
 
290
  public MappedByteBuffer map (FileChannel.MapMode mode,
291
                               long position, long size)
292
    throws IOException
293
  {
294
    char nmode = 0;
295
    if (mode == MapMode.READ_ONLY)
296
      {
297
        nmode = 'r';
298
        if ((this.mode & READ) == 0)
299
          throw new NonReadableChannelException();
300
      }
301
    else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE)
302
      {
303
        nmode = mode == MapMode.READ_WRITE ? '+' : 'c';
304
        if ((this.mode & (READ|WRITE)) != (READ|WRITE))
305
          throw new NonWritableChannelException();
306
      }
307
    else
308
      throw new IllegalArgumentException ("mode: " + mode);
309
 
310
    if (position < 0 || size < 0 || size > Integer.MAX_VALUE)
311
      throw new IllegalArgumentException ("position: " + position
312
                                          + ", size: " + size);
313
    return mapImpl(nmode, position, (int) size);
314
  }
315
 
316
  /**
317
   * msync with the disk
318
   */
319
  public void force (boolean metaData) throws IOException
320
  {
321
    if (!isOpen ())
322
      throw new ClosedChannelException ();
323
 
324
    force ();
325
  }
326
 
327
  private native void force ();
328
 
329
  // like transferTo, but with a count of less than 2Gbytes
330
  private int smallTransferTo (long position, int count,
331
                               WritableByteChannel target)
332
    throws IOException
333
  {
334
    ByteBuffer buffer;
335
    try
336
      {
337
        // Try to use a mapped buffer if we can.  If this fails for
338
        // any reason we'll fall back to using a ByteBuffer.
339
        buffer = map (MapMode.READ_ONLY, position, count);
340
      }
341
    catch (IOException e)
342
      {
343
        buffer = ByteBuffer.allocate (count);
344
        read (buffer, position);
345
        buffer.flip();
346
      }
347
 
348
    return target.write (buffer);
349
  }
350
 
351
  public long transferTo (long position, long count,
352
                          WritableByteChannel target)
353
    throws IOException
354
  {
355
    if (position < 0
356
        || count < 0)
357
      throw new IllegalArgumentException ("position: " + position
358
                                          + ", count: " + count);
359
 
360
    if (!isOpen ())
361
      throw new ClosedChannelException ();
362
 
363
    if ((mode & READ) == 0)
364
       throw new NonReadableChannelException ();
365
 
366
    final int pageSize = 65536;
367
    long total = 0;
368
 
369
    while (count > 0)
370
      {
371
        int transferred
372
          = smallTransferTo (position, (int)Math.min (count, pageSize),
373
                             target);
374
        if (transferred < 0)
375
          break;
376
        total += transferred;
377
        position += transferred;
378
        count -= transferred;
379
      }
380
 
381
    return total;
382
  }
383
 
384
  // like transferFrom, but with a count of less than 2Gbytes
385
  private int smallTransferFrom (ReadableByteChannel src, long position,
386
                                 int count)
387
    throws IOException
388
  {
389
    ByteBuffer buffer = null;
390
 
391
    if (src instanceof FileChannel)
392
      {
393
        try
394
          {
395
            // Try to use a mapped buffer if we can.  If this fails
396
            // for any reason we'll fall back to using a ByteBuffer.
397
            buffer = ((FileChannel)src).map (MapMode.READ_ONLY, position,
398
                                             count);
399
          }
400
        catch (IOException e)
401
          {
402
          }
403
      }
404
 
405
    if (buffer == null)
406
      {
407
        buffer = ByteBuffer.allocate ((int) count);
408
        src.read (buffer);
409
        buffer.flip();
410
      }
411
 
412
    return write (buffer, position);
413
  }
414
 
415
  public long transferFrom (ReadableByteChannel src, long position,
416
                            long count)
417
    throws IOException
418
  {
419
    if (position < 0
420
        || count < 0)
421
      throw new IllegalArgumentException ("position: " + position
422
                                          + ", count: " + count);
423
 
424
    if (!isOpen ())
425
      throw new ClosedChannelException ();
426
 
427
    if ((mode & WRITE) == 0)
428
       throw new NonWritableChannelException ();
429
 
430
    final int pageSize = 65536;
431
    long total = 0;
432
 
433
    while (count > 0)
434
      {
435
        int transferred = smallTransferFrom (src, position,
436
                                             (int)Math.min (count, pageSize));
437
        if (transferred < 0)
438
          break;
439
        total += transferred;
440
        position += transferred;
441
        count -= transferred;
442
      }
443
 
444
    return total;
445
  }
446
 
447
  // Shared sanity checks between lock and tryLock methods.
448
  private void lockCheck(long position, long size, boolean shared)
449
    throws IOException
450
  {
451
    if (position < 0
452
        || size < 0)
453
      throw new IllegalArgumentException ("position: " + position
454
                                          + ", size: " + size);
455
 
456
    if (!isOpen ())
457
      throw new ClosedChannelException();
458
 
459
    if (shared && ((mode & READ) == 0))
460
      throw new NonReadableChannelException();
461
 
462
    if (!shared && ((mode & WRITE) == 0))
463
      throw new NonWritableChannelException();
464
  }
465
 
466
  public FileLock tryLock (long position, long size, boolean shared)
467
    throws IOException
468
  {
469
    lockCheck(position, size, shared);
470
 
471
    boolean completed = false;
472
    try
473
      {
474
        begin();
475
        boolean lockable = lock(position, size, shared, false);
476
        completed = true;
477
        return (lockable
478
                ? new FileLockImpl(this, position, size, shared)
479
                : null);
480
      }
481
    finally
482
      {
483
        end(completed);
484
      }
485
  }
486
 
487
  /** Try to acquire a lock at the given position and size.
488
   * On success return true.
489
   * If wait as specified, block until we can get it.
490
   * Otherwise return false.
491
   */
492
  private native boolean lock(long position, long size,
493
                              boolean shared, boolean wait) throws IOException;
494
 
495
  public FileLock lock (long position, long size, boolean shared)
496
    throws IOException
497
  {
498
    lockCheck(position, size, shared);
499
 
500
    boolean completed = false;
501
    try
502
      {
503
        boolean lockable = lock(position, size, shared, true);
504
        completed = true;
505
        return (lockable
506
                ? new FileLockImpl(this, position, size, shared)
507
                : null);
508
      }
509
    finally
510
      {
511
        end(completed);
512
      }
513
  }
514
 
515
  public long position ()
516
    throws IOException
517
  {
518
    if (!isOpen ())
519
      throw new ClosedChannelException ();
520
 
521
    return implPosition ();
522
  }
523
 
524
  public FileChannel position (long newPosition)
525
    throws IOException
526
  {
527
    if (newPosition < 0)
528
      throw new IllegalArgumentException ("newPostition: " + newPosition);
529
 
530
    if (!isOpen ())
531
      throw new ClosedChannelException ();
532
 
533
    // FIXME note semantics if seeking beyond eof.
534
    // We should seek lazily - only on a write.
535
    seek (newPosition);
536
    return this;
537
  }
538
 
539
  public FileChannel truncate (long size)
540
    throws IOException
541
  {
542
    if (size < 0)
543
      throw new IllegalArgumentException ("size: " + size);
544
 
545
    if (!isOpen ())
546
      throw new ClosedChannelException ();
547
 
548
    if ((mode & WRITE) == 0)
549
       throw new NonWritableChannelException ();
550
 
551
    if (size < size ())
552
      implTruncate (size);
553
 
554
    return this;
555
  }
556
 
557
  public String toString()
558
  {
559
    return (this.getClass()
560
            + "[fd=" + fd
561
            + ",mode=" + mode + ","
562
            + description + "]");
563
  }
564
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.