public String getString() { return ("type=" + type + ",acc=" + file_access.getString()); }
public void write(RandomAccessFile raf, DirectByteBuffer[] buffers, long position) throws FMFileManagerException { file_access.write(raf, buffers, position); }
public void flush() throws FMFileManagerException { file_access.flush(); }
public void setPieceComplete(RandomAccessFile raf, int piece_number, DirectByteBuffer piece_data) throws FMFileManagerException { file_access.setPieceComplete(raf, piece_number, piece_data); }
public void read(RandomAccessFile raf, DirectByteBuffer[] buffers, long offset) throws FMFileManagerException { file_access.read(raf, buffers, offset); }
public boolean isPieceCompleteProcessingNeeded(int piece_number) { return (file_access.isPieceCompleteProcessingNeeded(piece_number)); }
public void setLength(RandomAccessFile raf, long length) throws FMFileManagerException { file_access.setLength(raf, length); }
public long getLength(RandomAccessFile raf) throws FMFileManagerException { return (file_access.getLength(raf)); }
public void aboutToOpen() throws FMFileManagerException { file_access.aboutToOpen(); }
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(); // see if we have any potential data for the last piece 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); // see if we need to truncate 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 { // no last piece, truncate after the first piece 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) { // override original exception if there isn't one 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(); } } } }