use of com.biglybt.core.torrent.TOTorrent in project BiglyBT by BiglySoftware.
the class GlobalManagerImpl method addDownloadManager.
/**
* @return true, if the download was added
*
* @author Rene Leonhardt
*/
@Override
public DownloadManager addDownloadManager(String torrent_file_name, byte[] optionalHash, String savePath, String saveFile, int initialState, boolean persistent, boolean for_seeding, DownloadManagerInitialisationAdapter _adapter) {
boolean needsFixup = false;
DownloadManager manager;
// wait for "load existing" to complete
loadingSem.reserve(60 * 1000);
DownloadManagerInitialisationAdapter adapter = getDMAdapter(_adapter);
/* to recover the initial state for non-persistent downloads the simplest way is to do it here
*/
List file_priorities = null;
if (!persistent) {
Map save_download_state = (Map) saved_download_manager_state.get(new HashWrapper(optionalHash));
if (save_download_state != null) {
if (save_download_state.containsKey("state")) {
int saved_state = ((Long) save_download_state.get("state")).intValue();
if (saved_state == DownloadManager.STATE_STOPPED) {
initialState = saved_state;
}
}
file_priorities = (List) save_download_state.get("file_priorities");
// non persistent downloads come in at random times
// If it has a position, it's probably invalid because the
// list has been fixed up to remove gaps. Set a flag to
// do another fixup after adding
Long lPosition = (Long) save_download_state.get("position");
if (lPosition != null) {
if (lPosition.longValue() != -1) {
needsFixup = true;
}
}
}
}
File torrentDir = null;
File fDest = null;
HashWrapper hash = null;
boolean deleteDest = false;
boolean removeFromAddingDM = false;
try {
File f = new File(torrent_file_name);
if (!f.exists()) {
throw (new IOException("Torrent file '" + torrent_file_name + "' doesn't exist"));
}
if (!f.isFile()) {
throw (new IOException("Torrent '" + torrent_file_name + "' is not a file"));
}
fDest = TorrentUtils.copyTorrentFileToSaveDir(f, persistent);
String fName = fDest.getCanonicalPath();
try {
if (optionalHash != null) {
hash = new HashWrapper(optionalHash);
} else {
// This does not trigger locale decoding :)
TOTorrent torrent = TorrentUtils.readFromFile(fDest, false);
hash = torrent.getHashWrapper();
}
if (hash != null) {
removeFromAddingDM = true;
// loaded check
DownloadManager existingDM = getDownloadManager(hash);
if (existingDM != null) {
deleteDest = true;
return existingDM;
}
try {
// loading check
addingDM_monitor.enter();
if (addingDMs.contains(hash)) {
removeFromAddingDM = false;
deleteDest = true;
return null;
}
addingDMs.add(hash);
} finally {
addingDM_monitor.exit();
}
}
} catch (Exception e) {
// ignore any error.. let it bork later in case old code relies
// on it borking later
}
// now do the creation!
DownloadManager new_manager = DownloadManagerFactory.create(this, optionalHash, fName, savePath, saveFile, initialState, persistent, for_seeding, file_priorities, adapter);
manager = addDownloadManager(new_manager, true, true);
if (manager == null || manager != new_manager) {
deleteDest = true;
} else {
if (initialState == DownloadManager.STATE_STOPPED) {
if (COConfigurationManager.getBooleanParameter("Default Start Torrents Stopped Auto Pause")) {
try {
paused_list_mon.enter();
paused_list.add(new Object[] { manager.getTorrent().getHashWrapper(), false });
} finally {
paused_list_mon.exit();
}
}
}
if (TorrentUtils.shouldDeleteTorrentFileAfterAdd(fDest, persistent)) {
deleteDest = true;
}
}
} catch (IOException e) {
System.out.println("DownloadManager::addDownloadManager: fails - td = " + torrentDir + ", fd = " + fDest);
System.err.println(Debug.getCompressedStackTrace());
// Debug.printStackTrace(e);
manager = DownloadManagerFactory.create(this, optionalHash, torrent_file_name, savePath, saveFile, initialState, persistent, for_seeding, file_priorities, adapter);
manager = addDownloadManager(manager, true, true);
} catch (Exception e) {
// get here on duplicate files, no need to treat as error
manager = DownloadManagerFactory.create(this, optionalHash, torrent_file_name, savePath, saveFile, initialState, persistent, for_seeding, file_priorities, adapter);
manager = addDownloadManager(manager, true, true);
} finally {
if (deleteDest) {
fDest.delete();
File backupFile;
try {
backupFile = new File(fDest.getCanonicalPath() + ".bak");
if (backupFile.exists())
backupFile.delete();
} catch (IOException e) {
}
}
if (removeFromAddingDM && hash != null) {
try {
addingDM_monitor.enter();
addingDMs.remove(hash);
} finally {
addingDM_monitor.exit();
}
}
}
if (needsFixup && manager != null) {
if (manager.getPosition() <= downloadManagerCount(manager.isDownloadComplete(false))) {
fixUpDownloadManagerPositions();
}
}
return manager;
}
use of com.biglybt.core.torrent.TOTorrent in project BiglyBT by BiglySoftware.
the class DownloadHistoryManagerImpl method getUID.
static long getUID(DownloadManager dm) {
TOTorrent torrent = dm.getTorrent();
long lhs;
if (torrent == null) {
lhs = 0;
} else {
try {
byte[] hash = torrent.getHash();
lhs = (hash[0] << 24) & 0xff000000 | (hash[1] << 16) & 0x00ff0000 | (hash[2] << 8) & 0x0000ff00 | hash[3] & 0x000000ff;
} catch (Throwable e) {
lhs = 0;
}
}
long date_added = dm.getDownloadState().getLongAttribute(DownloadManagerState.PARAM_DOWNLOAD_ADDED_TIME);
long rhs = date_added / 1000;
return ((lhs << 32) | rhs);
}
use of com.biglybt.core.torrent.TOTorrent in project BiglyBT by BiglySoftware.
the class CacheFileManagerImpl method allocateCacheSpace.
/**
* allocates space but does NOT add it to the cache list due to synchronization issues. Basically
* the caller mustn't hold their monitor when calling allocate, as a flush may result in one or more
* other files being flushed which results in their monitor being taken, and we've got an A->B and
* B->A classic deadlock situation. However, we must keep the file's cache and our cache in step.
* It is not acceptable to have an entry inserted into our records but not in the file's as this
* then screws up the flush algorithm (which assumes that if it finds an entry in our list, a flush
* of that file is guaranteed to release space). Therefore we add the cache entry in addCacheSpace
* so that the caller can safely do this while synchronised firstly on its monitor and then we can
* sync on our. Hence we only ever get A->B monitor grabs which won't deadlock
* @param file
* @param buffer
* @param file_position
* @param length
* @return
* @throws CacheFileManagerException
*/
protected CacheEntry allocateCacheSpace(int entry_type, CacheFileWithCache file, DirectByteBuffer buffer, long file_position, int length) throws CacheFileManagerException {
boolean ok = false;
boolean log = false;
while (!ok) {
// musn't invoke synchronised CacheFile methods while holding manager lock as this
// can cause deadlocks (as CacheFile calls manager methods with locks)
CacheEntry oldest_entry = null;
try {
this_mon.enter();
if (length < cache_space_free || cache_space_free == cache_size) {
ok = true;
} else {
oldest_entry = (CacheEntry) cache_entries.keySet().iterator().next();
}
} finally {
this_mon.exit();
}
if (!ok) {
log = true;
long old_free = cache_space_free;
CacheFileWithCache oldest_file = oldest_entry.getFile();
try {
oldest_file.flushCache(oldest_entry.getFilePosition(), true, cache_minimum_free_size);
} catch (CacheFileManagerException e) {
if (oldest_file != file) {
oldest_file.setPendingException(e);
} else {
throw (e);
}
}
long flushed = cache_space_free - old_free;
if (Logger.isEnabled()) {
TOTorrentFile tf = file.getTorrentFile();
TOTorrent torrent = tf == null ? null : tf.getTorrent();
Logger.log(new LogEvent(torrent, LOGID, "DiskCache: cache full, flushed " + flushed + " from " + oldest_file.getName()));
}
if (flushed == 0) {
try {
this_mon.enter();
if (cache_entries.size() > 0 && (CacheEntry) cache_entries.keySet().iterator().next() == oldest_entry) {
throw (new CacheFileManagerException(null, "Cache inconsistent: 0 flushed"));
}
} finally {
this_mon.exit();
}
}
}
}
CacheEntry entry = new CacheEntry(entry_type, file, buffer, file_position, length);
if (log && Logger.isEnabled()) {
TOTorrentFile tf = file.getTorrentFile();
TOTorrent torrent = tf == null ? null : tf.getTorrent();
Logger.log(new LogEvent(torrent, LOGID, "DiskCache: cr=" + cache_bytes_read + ",cw=" + cache_bytes_written + ",fr=" + file_bytes_read + ",fw=" + file_bytes_written));
}
return (entry);
}
use of com.biglybt.core.torrent.TOTorrent in project BiglyBT by BiglySoftware.
the class DownloadManagerEnhancer method getEnhancedDownload.
public EnhancedDownloadManager getEnhancedDownload(DownloadManager manager) {
TOTorrent torrent = manager.getTorrent();
if (torrent == null) {
return (null);
}
DownloadManager dm2 = manager.getGlobalManager().getDownloadManager(torrent);
if (dm2 != manager) {
return null;
}
synchronized (download_map) {
EnhancedDownloadManager res = (EnhancedDownloadManager) download_map.get(manager);
if (res == null) {
res = new EnhancedDownloadManager(DownloadManagerEnhancer.this, manager);
download_map.put(manager, res);
}
return (res);
}
}
use of com.biglybt.core.torrent.TOTorrent in project BiglyBT by BiglySoftware.
the class DownloadManagerEnhancer method resume.
protected void resume(DownloadManager dm) {
TOTorrent torrent = dm.getTorrent();
if (torrent == null) {
return;
}
try {
HashWrapper hw = torrent.getHashWrapper();
synchronized (pause_set) {
if (!pause_set.remove(hw)) {
return;
}
}
dm.resume();
} catch (Throwable e) {
Debug.out(e);
}
}
Aggregations