use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.
the class FMFileAccessController method convertSupport.
private void convertSupport(int target_type, boolean force) throws FMFileManagerException {
if (type == target_type) {
return;
}
if (type == FMFile.FT_PIECE_REORDER || type == FMFile.FT_PIECE_REORDER_COMPACT || target_type == FMFile.FT_PIECE_REORDER || target_type == FMFile.FT_PIECE_REORDER_COMPACT) {
if ((target_type == FMFile.FT_PIECE_REORDER_COMPACT && type == FMFile.FT_PIECE_REORDER) || (target_type == FMFile.FT_PIECE_REORDER && 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();
FileAccessor fa = 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()) {
fa = FileUtil.newFileAccessor(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(fa);
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(fa, new DirectByteBuffer[] { buffer }, last_piece_start);
if (target_type == FMFile.FT_COMPACT) {
long first_piece_length = compact_access.getFirstPieceLength();
long physical_length = fa.getLength();
if (physical_length > first_piece_length) {
fa.setLength(first_piece_length);
}
}
buffer.flip(DirectByteBuffer.AL_FILE);
target_access.write(fa, 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 = fa.getLength();
if (physical_length > first_piece_length) {
fa.setLength(first_piece_length);
}
}
}
target_access.setLength(fa, 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 (fa != null) {
try {
fa.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) {
FileUtil.newFile(control_dir, controlFileName).delete();
}
}
}
}
use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.
the class FMFileAccessPieceReorderer method configBorked.
private void configBorked(String error) throws FMFileManagerException {
piece_map = new int[num_pieces];
piece_reverse_map = new int[num_pieces];
Arrays.fill(piece_map, -1);
piece_map[0] = 0;
piece_reverse_map[0] = 0;
current_length = getFile().getLinkedFile().length();
int piece_count = (int) ((current_length + piece_size - 1) / piece_size) + 1;
if (piece_count > num_pieces) {
piece_count = num_pieces;
}
for (int i = 1; i < piece_count; i++) {
piece_map[i] = i;
piece_reverse_map[i] = i;
}
next_piece_index = piece_count;
writeConfig();
FMFileManagerException e = new FMFileManagerException(error);
e.setRecoverable(false);
throw (e);
}
use of com.biglybt.core.diskmanager.file.FMFileManagerException in project BiglyBT by BiglySoftware.
the class FMFileAccessPieceReorderer method readWritePiece.
protected int readWritePiece(FileAccessor fa, 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(fa, 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(fa, buffers, piece_io_position);
} else {
delegate.write(fa, 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 FMFileAccessPieceReorderer method readWrite.
protected void readWrite(FileAccessor fa, 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(fa, 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 FMFileAccessCompact method readState.
protected void readState() throws FMFileManagerException {
try {
Map data = FileUtil.readResilientFile(controlFileDir, controlFileName, false);
if (data != null && data.size() > 0) {
// Long version = (Long)data.get( "version" );
Long length = (Long) data.get("length");
current_length = length.longValue();
}
} catch (Throwable e) {
throw (new FMFileManagerException("Failed to read control file state", e));
}
}
Aggregations