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();
}
}
}
}
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;
}
}
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]);
}
}
}
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();
}
}
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;
}
}
}
Aggregations