Skip to content

Commit

Permalink
Rework link storage to support future fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
parg committed Nov 23, 2024
1 parent dc914ca commit 415879f
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 390 deletions.
2 changes: 0 additions & 2 deletions core/src/com/biglybt/core/disk/impl/DiskManagerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,6 @@

state.setFileLink( file_info.getIndex(), from_file, to_link );

state.save(false);

return( null );
}

Expand Down
10 changes: 5 additions & 5 deletions core/src/com/biglybt/core/diskmanager/file/impl/FMFileImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ public void parameterChanged(String parameterName) {
@Override
public void
moveFile(
File new_unlinked_file,
File new_linked_file,
FileUtil.ProgressListener pl )

throws FMFileManagerException
Expand All @@ -343,11 +343,11 @@ public void parameterChanged(String parameterName) {

length_cache = getLength();

TOTorrentFile tf = owner.getTorrentFile();

String new_canonical_path;

File new_linked_file = manager.getFileLink( tf.getTorrent(), tf.getIndex(), new StringInterner.FileKey( new_unlinked_file )).getFile();

// 3701 - switched the passed file to always be the actual destination regardless of any links, these are set up separately as required by callers
// TOTorrentFile tf = owner.getTorrentFile();
// File new_linked_file = manager.getFileLink( tf.getTorrent(), tf.getIndex(), new StringInterner.FileKey( new_unlinked_file )).getFile();

try{

Expand Down
112 changes: 47 additions & 65 deletions core/src/com/biglybt/core/diskmanager/file/impl/FMFileManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
*
*/

import java.io.File;
import java.util.*;

import com.biglybt.core.config.COConfigurationManager;
Expand Down Expand Up @@ -65,20 +64,20 @@
}
}

protected final LinkedHashMap map;
protected final LinkedHashMap<FMFileLimited,FMFileLimited> map;
protected final AEMonitor map_mon = new AEMonitor( "FMFileManager:Map");

protected final HashMap<Object,LinkFileMap> links = new HashMap<>();
protected final HashMap<HashWrapper,LinkFileMap> links = new HashMap<>();
protected final AEMonitor links_mon = new AEMonitor( "FMFileManager:Links");

protected final boolean limited;
protected final int limit_size;

protected AESemaphore close_queue_sem;
protected List close_queue;
protected final AEMonitor close_queue_mon = new AEMonitor( "FMFileManager:CQ");
protected AESemaphore close_queue_sem;
protected List<FMFileLimited> close_queue;
protected final AEMonitor close_queue_mon = new AEMonitor( "FMFileManager:CQ");

protected List files;
protected List<FMFile> files;
protected final AEMonitor files_mon = new AEMonitor( "FMFileManager:File");

protected
Expand All @@ -92,48 +91,43 @@

System.out.println( "FMFileManager::init: limit = " + limit_size );

files = new ArrayList();
files = new ArrayList<>();
}

map = new LinkedHashMap( limit_size, (float)0.75, true ); // ACCESS order selected - this means oldest
map = new LinkedHashMap<>( limit_size, (float)0.75, true ); // ACCESS order selected - this means oldest

if ( limited ){

close_queue_sem = new AESemaphore("FMFileManager::closeqsem");

close_queue = new LinkedList();
close_queue = new LinkedList<>();

Thread t = new AEThread("FMFileManager::closeQueueDispatcher")
new AEThread2("FMFileManager::closeQueueDispatcher")
{
@Override
public void
runSupport()
run()
{
closeQueueDispatch();
}
};

t.setDaemon(true);

t.start();
}.start();
}
}

protected LinkFileMap
getLinksEntry(
TOTorrent torrent )
{
Object links_key;
HashWrapper links_key;

try{

links_key = torrent.getHashWrapper();

}catch( Throwable e ){

Debug.printStackTrace(e);

links_key = "";
links_key = new HashWrapper( new byte[0]);
}

LinkFileMap links_entry = links.get( links_key );
Expand All @@ -157,35 +151,14 @@
try{
links_mon.enter();

LinkFileMap links_entry = getLinksEntry( torrent );

Iterator<LinkFileMap.Entry> it = new_links.entryIterator();

while( it.hasNext()){

LinkFileMap.Entry entry = it.next();

int index = entry.getIndex();

StringInterner.FileKey source = entry.getFromFile();
StringInterner.FileKey target = entry.getToFile();

// System.out.println( "setLink:" + source + " -> " + target );

if ( target != null && !FileUtil.areFilePathsIdentical( source.getFile(), target.getFile() )){

if ( index >= 0 ){

links_entry.put( index, source, target );

}else{
try{
HashWrapper links_key = torrent.getHashWrapper();

links_entry.putMigration( source, target );
}
}else{
links.put( links_key, new_links );

}catch( Throwable e ){

links_entry.remove( index, source );
}
Debug.printStackTrace(e);
}
}finally{

Expand All @@ -200,23 +173,25 @@
int file_index,
StringInterner.FileKey file )
{
// this function works on the currently defined links and will only accept
// them as valid if their 'from' location matches the 'file' being queried.
// if not the original file is returned, NOT null
// Reworked as of 3701 to NOT rely on the crap below...

// x this function works on the currently defined links and will only accept
// x them as valid if their 'from' location matches the 'file' being queried.
// x if not the original file is returned, NOT null

// These semantics are important during file-move operations as the move-file
// logic does not update links until AFTER the move is complete. If we don't
// verify the 'from' path in this case then the old existing linkage overrides
// the new destination during the move process and causes it to fail with
// 'file already exists'. There is possibly an argument that we shouldn't
// take links into account when moving
// x These semantics are important during file-move operations as the move-file
// x logic does not update links until AFTER the move is complete. If we don't
// x verify the 'from' path in this case then the old existing linkage overrides
// x the new destination during the move process and causes it to fail with
// x 'file already exists'. There is possibly an argument that we shouldn't
// x take links into account when moving

try{
links_mon.enter();

LinkFileMap links_entry = getLinksEntry( torrent );

LinkFileMap.Entry entry = links_entry.getEntry( file_index, file.getFile());
LinkFileMap.Entry entry = links_entry.getEntry( file_index );

StringInterner.FileKey res = null;

Expand All @@ -226,14 +201,22 @@

}else{

res = entry.getToFile();

/*
if ( file.equals( entry.getFromFile())){
res = entry.getToFile();
if ( res == null ){
res = file;
}
}else{
res = file;
}
*/
}

// System.out.println( "getLink:" + file + " -> " + res );
Expand All @@ -247,8 +230,11 @@
}

@Override
public boolean hasLinks(TOTorrent torrent) {
return getLinksEntry(torrent).hasLinks();
public boolean
hasLinks(
TOTorrent torrent)
{
return( getLinksEntry(torrent).size() > 0 );
}

@Override
Expand Down Expand Up @@ -565,13 +551,9 @@ public boolean hasLinks(TOTorrent torrent) {

int index = entry.getIndex();

StringInterner.FileKey source = entry.getFromFile();
StringInterner.FileKey target = entry.getToFile();

if ( target != null && !FileUtil.areFilePathsIdentical( source.getFile(), target.getFile())){

writer.println( index + ": " + source + " -> " + target );
}

writer.println( index + ": -> " + target );
}

}finally{
Expand Down
4 changes: 2 additions & 2 deletions core/src/com/biglybt/core/download/DownloadManagerState.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
public static final String AT_PEER_SOURCES = "peersources";
public static final String AT_PEER_SOURCES_DENIED = "peersourcesdenied";
public static final String AT_TRACKER_CLIENT_EXTENSIONS = "trackerclientextensions";
public static final String AT_FILE_LINKS_DEPRECATED = "filelinks";
//public static final String AT_FILE_LINKS_DEPRECATED = "filelinks";
public static final String AT_FILE_LINKS2 = "filelinks2";
public static final String AT_FILE_ALLOC_REQUEST = "allocreq"; // Map
public static final String AT_FILE_STORE_TYPES = "storetypes";
Expand Down Expand Up @@ -379,7 +379,7 @@
public void
setFileLinks(
List<Integer> source_indexes,
List<File> link_sources,
List<File> link_sources_may_have_nulls,
List<File> link_destinations );

public void
Expand Down
57 changes: 35 additions & 22 deletions core/src/com/biglybt/core/download/impl/DownloadManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1994,7 +1994,8 @@ public void perform(TimerEvent event){

private void
updateFileLinks(
File old_save_path, File new_save_path)
File old_save_path,
File new_save_path)
{
old_save_path = FileUtil.getCanonicalFileSafe( old_save_path );

Expand All @@ -2006,10 +2007,12 @@ public void perform(TimerEvent event){

Iterator<LinkFileMap.Entry> it = links.entryIterator();

List<Integer> from_indexes = new ArrayList<>();
List<File> from_links = new ArrayList<>();
List<File> to_links = new ArrayList<>();
List<Integer> from_indexes = new ArrayList<>();
List<File> from_links_may_have_nulls = new ArrayList<>();
List<File> to_links = new ArrayList<>();

DiskManagerFileInfo[] dm_files = getDiskManagerFileInfoSet().getFiles();

while(it.hasNext()){

LinkFileMap.Entry entry = it.next();
Expand All @@ -2029,22 +2032,36 @@ public void perform(TimerEvent event){

int file_index = entry.getIndex();

StringInterner.FileKey from_fk = entry.getFromFile();
// preparation for future removal of the "from-file"

File from_maybe_null;

StringInterner.FileKey from_fk_maybe_null = entry.getFromFileMaybeNull();

File from = FileUtil.getCanonicalFileSafe( from_fk.getFile());
if ( from_fk_maybe_null == null ){

from_maybe_null = null;

}else{

from_maybe_null = FileUtil.getCanonicalFileSafe( from_fk_maybe_null.getFile());
}

updateFileLink( file_index, old_save_path, new_save_path, from, to,
from_indexes, from_links, to_links );
updateFileLink(
file_index,
old_save_path, new_save_path,
from_maybe_null, to,
from_indexes, from_links_may_have_nulls, to_links );

}catch( Exception e ){

Debug.printStackTrace(e);
}
}

if ( from_links.size() > 0 ){
if ( from_links_may_have_nulls.size() > 0 ){

download_manager_state.setFileLinks( from_indexes, from_links, to_links );
download_manager_state.setFileLinks( from_indexes, from_links_may_have_nulls, to_links );
}
}

Expand All @@ -2061,7 +2078,7 @@ public void perform(TimerEvent event){
int file_index,
File old_path,
File new_path,
File from_loc,
File from_loc_maybe_null,
File to_loc,
List<Integer> from_indexes,
List<File> from_links,
Expand All @@ -2074,9 +2091,9 @@ public void perform(TimerEvent event){

if ( torrent.isSimpleTorrent()){

if (!FileUtil.areFilePathsIdentical(old_path, from_loc)) {
if (from_loc_maybe_null != null && !FileUtil.areFilePathsIdentical(old_path, from_loc_maybe_null)) {

throw new RuntimeException("assert failure: old_path=" + old_path + ", from_loc=" + from_loc);
throw new RuntimeException("assert failure: old_path=" + old_path + ", from_loc=" + from_loc_maybe_null);
}

//System.out.println( " adding " + old_path + " -> null" );
Expand Down Expand Up @@ -2112,27 +2129,23 @@ public void perform(TimerEvent event){

}else{

String from_loc_to_use = FileUtil.translateMoveFilePath( old_path_str,
new_path_str, from_loc.getAbsolutePath() );

if ( from_loc_to_use == null ){

return;
}
String from_loc_to_use_maybe_null =
from_loc_maybe_null==null?null:FileUtil.translateMoveFilePath( old_path_str,
new_path_str, from_loc_maybe_null.getAbsolutePath() );

String to_loc_to_use = FileUtil.translateMoveFilePath( old_path_str,
new_path_str, to_loc.getAbsolutePath() );

// delete old

from_indexes.add( file_index );
from_links.add( from_loc );
from_links.add( from_loc_maybe_null );
to_links.add( null );

// add new

from_indexes.add( file_index );
from_links.add( FileUtil.newFile(from_loc_to_use));
from_links.add( from_loc_to_use_maybe_null==null?null:FileUtil.newFile(from_loc_to_use_maybe_null));
to_links.add( to_loc_to_use == null ? to_loc : FileUtil.newFile(to_loc_to_use));
}
}
Expand Down
Loading

0 comments on commit 415879f

Please sign in to comment.