Search in sources :

Example 1 with FMFileManagerException

use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.

the class FMFileAccessController method convert.

protected void convert(int target_type) throws FMFileManagerException {
    if (type == target_type) {
        return;
    }
    if (type == FMFile.FT_PIECE_REORDER || target_type == FMFile.FT_PIECE_REORDER) {
        if (target_type == FMFile.FT_PIECE_REORDER_COMPACT || type == FMFile.FT_PIECE_REORDER_COMPACT) {
            // these two access modes are in fact identical at the moment
            type = target_type;
            return;
        }
        throw (new FMFileManagerException("Conversion to/from piece-reorder not supported"));
    }
    File file = owner.getLinkedFile();
    RandomAccessFile raf = null;
    boolean ok = false;
    try {
        FMFileAccess target_access;
        if (target_type == FMFile.FT_LINEAR) {
            target_access = new FMFileAccessLinear(owner);
        } else {
            target_access = new FMFileAccessCompact(owner.getOwner().getTorrentFile(), control_dir, controlFileName, new FMFileAccessLinear(owner));
        }
        if (file.exists()) {
            raf = new RandomAccessFile(file, FMFileImpl.WRITE_ACCESS_MODE);
            // due to the simplistic implementation of compact we only actually need to deal with
            // the last piece of the file (first piece is in the right place already)
            FMFileAccessCompact compact_access;
            if (target_type == FMFile.FT_LINEAR) {
                compact_access = (FMFileAccessCompact) file_access;
            } else {
                compact_access = (FMFileAccessCompact) target_access;
            }
            long length = file_access.getLength(raf);
            long last_piece_start = compact_access.getLastPieceStart();
            long last_piece_length = compact_access.getLastPieceLength();
            if (last_piece_length > 0 && length > last_piece_start) {
                long data_length = length - last_piece_start;
                if (data_length > last_piece_length) {
                    Debug.out("data length inconsistent: len=" + data_length + ",limit=" + last_piece_length);
                    data_length = last_piece_length;
                }
                DirectByteBuffer buffer = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_FILE, (int) data_length);
                try {
                    file_access.read(raf, new DirectByteBuffer[] { buffer }, last_piece_start);
                    if (target_type == FMFile.FT_COMPACT) {
                        long first_piece_length = compact_access.getFirstPieceLength();
                        long physical_length = raf.length();
                        if (physical_length > first_piece_length) {
                            raf.setLength(first_piece_length);
                        }
                    }
                    buffer.flip(DirectByteBuffer.AL_FILE);
                    target_access.write(raf, new DirectByteBuffer[] { buffer }, last_piece_start);
                } finally {
                    buffer.returnToPool();
                }
            } else {
                if (target_type == FMFile.FT_COMPACT) {
                    long first_piece_length = compact_access.getFirstPieceLength();
                    long physical_length = raf.length();
                    if (physical_length > first_piece_length) {
                        raf.setLength(first_piece_length);
                    }
                }
            }
            target_access.setLength(raf, length);
            target_access.flush();
        }
        type = target_type;
        file_access = target_access;
        ok = true;
    } catch (Throwable e) {
        Debug.printStackTrace(e);
        throw (new FMFileManagerException("convert fails", e));
    } finally {
        try {
            if (raf != null) {
                try {
                    raf.close();
                } catch (Throwable e) {
                    if (ok) {
                        ok = false;
                        throw (new FMFileManagerException("convert fails", e));
                    }
                }
            }
        } finally {
            if (!ok) {
                // conversion failed - replace with linear access, caller is responsible for
                // handling this (marking file requiring recheck)
                type = FMFile.FT_LINEAR;
                file_access = new FMFileAccessLinear(owner);
            }
            if (type == FMFile.FT_LINEAR) {
                new File(control_dir, controlFileName).delete();
            }
        }
    }
}
Also used : FMFileManagerException(com.biglybt.core.diskmanager.file.FMFileManagerException) RandomAccessFile(java.io.RandomAccessFile) RandomAccessFile(java.io.RandomAccessFile) FMFile(com.biglybt.core.diskmanager.file.FMFile) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) File(java.io.File)

Example 2 with FMFileManagerException

use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.

the class FMFileAccessPieceReorderer method readWrite.

protected void readWrite(RandomAccessFile raf, DirectByteBuffer[] buffers, long position, boolean is_read) throws FMFileManagerException {
    long total_length = 0;
    for (DirectByteBuffer buffer : buffers) {
        total_length += buffer.remaining(SS_FILE);
    }
    if (!is_read && position + total_length > current_length) {
        current_length = position + total_length;
        setDirty();
    }
    long current_position = position;
    while (total_length > 0) {
        int piece_number;
        int piece_offset;
        if (current_position < first_piece_length) {
            piece_number = 0;
            piece_offset = (int) current_position;
        } else {
            long offset = current_position - first_piece_length;
            piece_number = (int) (offset / piece_size) + 1;
            piece_offset = (int) (offset % piece_size);
        }
        int count = readWritePiece(raf, buffers, piece_number, piece_offset, is_read);
        if (count == 0) {
            if (is_read) {
                for (DirectByteBuffer buffer : buffers) {
                    ByteBuffer bb = buffer.getBuffer(SS_FILE);
                    int rem = bb.remaining();
                    if (rem > 0) {
                        bb.put(new byte[rem]);
                        // not great this... to obey the normal file access semantics reads are
                        // never partial (normally we'd extend the file to accomodate the read but
                        // in the case of re-order access we don't want to do this when hash checking
                        // a file. The issue is in the unlikely case where our padding happens to
                        // match the real file contents and results in a piece hash check succeeding
                        // even though the data doesn't actually exist on disk... So I've added this
                        // flag to cause hash checking to always fail if the resulting data isn't 'real'
                        // this of course relies on this buffer being passed back to the checking process
                        // intact, which is the case currently during rechecks...
                        buffer.setFlag(DirectByteBuffer.FL_CONTAINS_TRANSIENT_DATA);
                    }
                }
            } else {
                throw (new FMFileManagerException("partial write operation"));
            }
            return;
        }
        total_length -= count;
        current_position += count;
    }
}
Also used : FMFileManagerException(com.biglybt.core.diskmanager.file.FMFileManagerException) ByteBuffer(java.nio.ByteBuffer)

Example 3 with FMFileManagerException

use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.

the class FMFileAccessPieceReorderer method readWritePiece.

protected int readWritePiece(RandomAccessFile raf, DirectByteBuffer[] buffers, int piece_number, int piece_offset, boolean is_read) throws FMFileManagerException {
    String str = is_read ? "read" : "write";
    if (piece_number >= num_pieces) {
        throw (new FMFileManagerException("Attempt to " + str + " piece " + piece_number + ": last=" + num_pieces));
    }
    int this_piece_size = piece_number == 0 ? first_piece_length : (piece_number == (num_pieces - 1) ? last_piece_length : piece_size);
    final int piece_space = this_piece_size - piece_offset;
    if (piece_space <= 0) {
        throw (new FMFileManagerException("Attempt to " + str + " piece " + piece_number + ", offset " + piece_offset + " - no space in piece"));
    }
    int rem_space = piece_space;
    int[] limits = new int[buffers.length];
    for (int i = 0; i < buffers.length; i++) {
        DirectByteBuffer buffer = buffers[i];
        limits[i] = buffer.limit(SS_FILE);
        int rem = buffer.remaining(SS_FILE);
        if (rem > rem_space) {
            buffer.limit(SS_FILE, buffer.position(SS_FILE) + rem_space);
            rem_space = 0;
        } else {
            rem_space -= rem;
        }
    }
    try {
        long piece_start = getPieceOffset(raf, piece_number, !is_read);
        if (TRACE) {
            System.out.println(str + " to " + piece_number + "/" + piece_offset + "/" + this_piece_size + "/" + piece_space + "/" + rem_space + "/" + piece_start);
        }
        if (piece_start == -1) {
            return (0);
        }
        long piece_io_position = piece_start + piece_offset;
        if (is_read) {
            delegate.read(raf, buffers, piece_io_position);
        } else {
            delegate.write(raf, buffers, piece_io_position);
        }
        return (piece_space - rem_space);
    } finally {
        for (int i = 0; i < buffers.length; i++) {
            buffers[i].limit(SS_FILE, limits[i]);
        }
    }
}
Also used : FMFileManagerException(com.biglybt.core.diskmanager.file.FMFileManagerException)

Example 4 with FMFileManagerException

use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.

the class FMFileImpl method moveFile.

@Override
public void moveFile(File new_unlinked_file) throws FMFileManagerException {
    try {
        this_mon.enter();
        TOTorrentFile tf = owner.getTorrentFile();
        String new_canonical_path;
        File new_linked_file = manager.getFileLink(tf.getTorrent(), tf.getIndex(), new_unlinked_file);
        try {
            try {
                new_canonical_path = new_linked_file.getCanonicalPath();
            } catch (IOException ioe) {
                String msg = ioe.getMessage();
                if (msg != null && msg.contains("There are no more files")) {
                    String abs_path = new_linked_file.getAbsolutePath();
                    String error = "Caught 'There are no more files' exception during new_file.getCanonicalPath(). " + "os=[" + Constants.OSName + "], new_file.getPath()=[" + new_linked_file.getPath() + "], new_file.getAbsolutePath()=[" + abs_path + "]. ";
                    // "new_canonical_path temporarily set to [" +abs_path+ "]";
                    Debug.out(error, ioe);
                }
                throw ioe;
            }
        } catch (Throwable e) {
            throw (new FMFileManagerException("getCanonicalPath fails", e));
        }
        if (new_linked_file.exists()) {
            throw (new FMFileManagerException("moveFile fails - file '" + new_canonical_path + "' already exists"));
        }
        boolean was_open = isOpen();
        // full close, this will release any slots in the limited file case
        close();
        createDirs(new_linked_file);
        if (!linked_file.exists() || FileUtil.renameFile(linked_file, new_linked_file)) {
            linked_file = new_linked_file;
            canonical_path = new_canonical_path;
            reserveFile();
            if (was_open) {
                // ensure open will regain slots in limited file case
                ensureOpen("moveFile target");
            }
        } else {
            try {
                reserveFile();
            } catch (FMFileManagerException e) {
                Debug.printStackTrace(e);
            }
            if (was_open) {
                try {
                    ensureOpen("moveFile recovery");
                } catch (FMFileManagerException e) {
                    Debug.printStackTrace(e);
                }
            }
            throw (new FMFileManagerException("moveFile fails"));
        }
    } finally {
        this_mon.exit();
    }
}
Also used : FMFileManagerException(com.biglybt.core.diskmanager.file.FMFileManagerException) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) IOException(java.io.IOException) RandomAccessFile(java.io.RandomAccessFile) FMFile(com.biglybt.core.diskmanager.file.FMFile) TOTorrentFile(com.biglybt.core.torrent.TOTorrentFile) File(java.io.File)

Example 5 with FMFileManagerException

use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.

the class CacheFileWithoutCacheMT method moveFile.

@Override
public void moveFile(File new_file) throws CacheFileManagerException {
    try {
        synchronized (this) {
            moving = true;
        }
        while (true) {
            synchronized (this) {
                boolean surviving = false;
                for (int i = 1; i < files_use_count.length; i++) {
                    if (files_use_count[i] > 0) {
                        surviving = true;
                        break;
                    }
                }
                if (!surviving) {
                    for (int i = 1; i < files_use_count.length; i++) {
                        FMFile file = files[i];
                        if (file.isClone()) {
                            synchronized (CacheFileWithoutCacheMT.class) {
                                num_clones--;
                            }
                        }
                        file.close();
                    }
                    files = new FMFile[] { base_file };
                    files_use_count = new int[] { files_use_count[0] };
                    base_file.moveFile(new_file);
                    break;
                }
            }
            try {
                System.out.println("CacheFileWithoutCacheMT: waiting for clones to die");
                Thread.sleep(250);
            } catch (Throwable e) {
            }
        }
    } catch (FMFileManagerException e) {
        manager.rethrow(this, e);
    } finally {
        synchronized (this) {
            moving = false;
        }
    }
}
Also used : FMFileManagerException(com.biglybt.core.diskmanager.file.FMFileManagerException) FMFile(com.biglybt.core.diskmanager.file.FMFile)

Aggregations

FMFileManagerException (com.biglybt.core.diskmanager.file.FMFileManagerException)35 FMFile (com.biglybt.core.diskmanager.file.FMFile)14 TOTorrentFile (com.biglybt.core.torrent.TOTorrentFile)8 File (java.io.File)7 IOException (java.io.IOException)7 ByteBuffer (java.nio.ByteBuffer)6 MappedByteBuffer (java.nio.MappedByteBuffer)6 FileChannel (java.nio.channels.FileChannel)6 CacheFileManagerException (com.biglybt.core.diskmanager.cache.CacheFileManagerException)3 LogEvent (com.biglybt.core.logging.LogEvent)3 RandomAccessFile (java.io.RandomAccessFile)3 HashMap (java.util.HashMap)3 Map (java.util.Map)3 FMFileOwner (com.biglybt.core.diskmanager.file.FMFileOwner)1 TOTorrent (com.biglybt.core.torrent.TOTorrent)1 FileNotFoundException (java.io.FileNotFoundException)1