rdresumehandler.java

来自「Azureus is a powerful, full-featured, cr」· Java 代码 · 共 784 行 · 第 1/2 页

JAVA
784
字号
						writer_and_checker.checkPiece(
							i,
							new CheckPieceResultHandler()
							{
								public void
								processResult(
									int		piece_number,
									int		result,
									Object	user_data )
								{
									LGLogger.log(0, 0, LGLogger.INFORMATION, "Piece #" + piece_number + (result==CheckPieceResultHandler.OP_SUCCESS?" passed":" failed") + " re-check.");
	
									pending_checks_sem.release();
								}
							},
							null );
						
						pending_check_num++;
						
					}catch( Throwable e ){
					
						Debug.printStackTrace(e);
					}
				}								
			}
						
			while( pending_check_num > 0 ){
				
				pending_checks_sem.reserve();
				
				pending_check_num--;
			}
			
				//dump the newly built resume data to the disk/torrent
			
			if ( bOverallContinue && !resume_data_complete ){
				
				try{
					dumpResumeDataToDisk(false, false);
					
				}catch( Exception e ){
					
					Debug.out( "Failed to dump initial resume data to disk" );
				}
			}
		}finally{
			// System.out.println( "Check of '" + disk_manager.getDownloadManager().getDisplayName() + "' completed in " + (System.currentTimeMillis() - start));
		}
	}
	
	public void 
	dumpResumeDataToDisk(
		boolean savePartialPieces, 
		boolean force_recheck )
	
		throws Exception
	{
    
			// if file caching is enabled then this is an important time to ensure that the cache is
			// flushed as we are going to record details about the accuracy of written data.
			// First build the resume map from the data (as updates can still be goin on)
			// Then, flush the cache. This means that on a successful flush the built resume
			// data matches at least the valid state of the data
			// Then update the torrent
		
		DiskManagerFileInfo[]	files = disk_manager.getFiles();
		
		if ( !useFastResume ){
			
				// flush cache even if resume disable
			
			for (int i=0;i<files.length;i++){
				
				files[i].flushCache();
			}
			
			return;
		}

		boolean	was_complete = isTorrentResumeDataComplete( 
									download_manager_state, 
									disk_manager.getDownloadManager().getTorrentSaveDir(), 
									disk_manager.getDownloadManager().getTorrentSaveFile());
		
		DiskManagerPiece[] pieces	= disk_manager.getPieces();

			//build the piece byte[]
		
		byte[] resumeData = new byte[pieces.length];
		
		if ( !force_recheck ){
				
			for (int i = 0; i < resumeData.length; i++) {
		  	
			  	if ( pieces[i].getDone()){
			  		
					resumeData[i] = (byte)1;
			  		
			  	}else{
			  	
					resumeData[i] = (byte)0;
			  	}
			}
		}
		
		Map resumeMap = new HashMap();
	  
		Map resumeDirectory = new HashMap();
	  
	  		// We *really* shouldn't be using a localised string as a Map key (see bug 869749)
	  		// currently fixed by mangling such that decode works
	  
		// System.out.println( "writing resume data: key = " + ByteFormatter.nicePrint(path));
	  
		String resume_key = 
			torrent.isSimpleTorrent()?
				disk_manager.getDownloadManager().getTorrentSaveDir():
				disk_manager.getDownloadManager().getTorrentSaveDirAndFile();
		
		resume_key	= getCanonicalResumeKey( resume_key );

		resumeMap.put(resume_key, resumeDirectory);
	  
		resumeDirectory.put("resume data", resumeData);
	  
		Map partialPieces = new HashMap();
	
		if ( savePartialPieces && !force_recheck ){
	  		  		      
			for (int i = 0; i < pieces.length; i++) {
				
				DiskManagerPiece piece = pieces[i];
				
					// save the partial pieces for any pieces that have not yet been completed
					// and are in-progress (i.e. have at least one block downloaded)
				
				boolean[] downloaded = piece.getWritten();

				if (( !piece.getDone()) && piece.getCompleteCount() > 0 && downloaded != null ){
					
					
					List blocks = new ArrayList();
					
					for (int j = 0; j < downloaded.length; j++) {
						
						if (downloaded[j]){
							
							blocks.add(new Long(j));
						}
					}
          
					partialPieces.put("" + i, blocks);
				}
			}
			
			resumeDirectory.put("blocks", partialPieces);
		}
		
			// savePartialPieces has overloaded meanings. It also implies that the download
			// is stopping, as opposed to this being an interim resume data save, and therefore
			// that the resume data should be set as "valid". Being valid has the meaning that
			// blocks marked as not-done will *not* be checked when the torrent is restarted
			// to see if they are actually complete.
			// TODO: fix this up!!!!
		
		resumeDirectory.put("valid", new Long( force_recheck?0:(savePartialPieces?1:0)));
		
		for (int i=0;i<files.length;i++){
			
			files[i].flushCache();
		}
		
	  		// OK, we've got valid resume data and flushed the cache
	  
		download_manager_state.setResumeData( resumeMap );

		boolean	is_complete = 
			isTorrentResumeDataComplete( 
				download_manager_state, 
				disk_manager.getDownloadManager().getTorrentSaveDir(),
				disk_manager.getDownloadManager().getTorrentSaveFile());

		if ( was_complete && is_complete ){
	 
	  		// no change, no point in writing
	  		  	
		}else{
	  	
			download_manager_state.save();
		}
	}

		/**
		 * data_dir must be the parent folder for a simple torrent or the *actual* folder for non-simple
		 * @param torrent
		 * @param data_dir
		 */
	
	public static void
	setTorrentResumeDataComplete(
		DownloadManagerState	download_manager_state,
		String					resume_key  )
	{
		TOTorrent	torrent = download_manager_state.getTorrent();
		
		resume_key	= getCanonicalResumeKey( resume_key );

		int	piece_count = torrent.getNumberOfPieces();
		
		byte[] resumeData = new byte[piece_count];
		
		for (int i = 0; i < resumeData.length; i++) {
			
			resumeData[i] = (byte)1;
		}

		Map resumeMap = new HashMap();
		
		Map resumeDirectory = new HashMap();
		
		// We *really* shouldn't be using a localised string as a Map key (see bug 869749)
		// currently fixed by mangling such that decode works
		
		resumeMap.put(resume_key, resumeDirectory);
		
		resumeDirectory.put("resume data", resumeData);
		
		Map partialPieces = new HashMap();
		
		resumeDirectory.put("blocks", partialPieces);
		
		resumeDirectory.put("valid", new Long(1));	
				
		download_manager_state.setResumeData( resumeMap );
	}
	
	public static void
	setTorrentResumeDataNearlyComplete(
		DownloadManagerState	download_manager_state,
		String					torrent_save_dir,
		String					torrent_save_file )
	{
			// backwards compatability, resume data key is the dir
		
		TOTorrent	torrent = download_manager_state.getTorrent();
		
		String	resume_key = torrent.isSimpleTorrent()?
								torrent_save_dir:
								(torrent_save_dir + File.separator + torrent_save_file );
		
		resume_key	= getCanonicalResumeKey( resume_key );
		
		long	piece_count = torrent.getNumberOfPieces();
		
		byte[] resumeData = new byte[(int)piece_count];
		
		for (int i = 0; i < resumeData.length; i++) {
			
			resumeData[i] = (byte)1;
		}

			// randomly clear some pieces
		
		for (int i=0;i<3;i++){
			
			int	piece_num = (int)(Math.random()*piece_count);
						
			resumeData[piece_num]= 0;
		}
		
		Map resumeMap = new HashMap();
		
		Map resumeDirectory = new HashMap();
		
		// We *really* shouldn't be using a localised string as a Map key (see bug 869749)
		// currently fixed by mangling such that decode works
		
		resumeMap.put(resume_key, resumeDirectory);
		
		resumeDirectory.put("resume data", resumeData);
		
		Map partialPieces = new HashMap();
		
		resumeDirectory.put("blocks", partialPieces);
		
		resumeDirectory.put("valid", new Long(0));	
			
		download_manager_state.setResumeData( resumeMap );
	}
	
	public static boolean
	isTorrentResumeDataComplete(
		DownloadManagerState	download_manager_state,
		String					torrent_save_dir,
		String					torrent_save_file )
	{
		TOTorrent	torrent = download_manager_state.getTorrent();
		
			// backwards compatability, resume data key is the dir
		
		String	resume_key = torrent.isSimpleTorrent()?
								torrent_save_dir:
								(torrent_save_dir + File.separator + torrent_save_file );
		
		// System.out.println( "resume key = " + resume_key );
	
		resume_key	= getCanonicalResumeKey( resume_key );
		
		try{
			int	piece_count = torrent.getNumberOfPieces();
		
			Map resumeMap = download_manager_state.getResumeData();
		
			if (resumeMap != null) {
			
					// see bug 869749 for explanation of this mangling
				
				String mangled_path;
				
				try{
					mangled_path = new String(resume_key.getBytes(Constants.DEFAULT_ENCODING),Constants.BYTE_ENCODING);
									
				}catch( Throwable e ){
					
					Debug.printStackTrace( e );
					
					mangled_path = resume_key;
				}
				
				Map resumeDirectory = (Map)resumeMap.get(mangled_path);
				
				if ( resumeDirectory == null ){
					
					// unfortunately, if the torrent hasn't been saved and restored then the
					// mangling with not yet have taken place. So we have to also try the 
					// original key (see 878015)
					
					resumeDirectory = (Map)resumeMap.get(resume_key);
				}
				
				if (resumeDirectory != null) {
										
					byte[] 	resume_data =  (byte[])resumeDirectory.get("resume data");
					Map		blocks		= (Map)resumeDirectory.get("blocks");
					boolean	valid		= ((Long)resumeDirectory.get("valid")).intValue() == 1;
					
						// any partial pieced -> not complete
					if ( blocks == null || blocks.size() > 0 ){
						
						return( false );
					}
					
					if ( valid && resume_data.length == piece_count ){
						
						for (int i=0;i<resume_data.length;i++){
	
							if ( resume_data[i] == 0 ){
								
									// missing piece
								
								return( false );
							}
						}
						
						return( true );
					}
				}
			}
		}catch( Throwable e ){
		
			Debug.printStackTrace( e );
		}	
		
		return( false );
	}

	protected static String
	getCanonicalResumeKey(
		String		resume_key )
	{
		try{
			resume_key	= new File( resume_key).getCanonicalFile().toString();
			
		}catch( Throwable e ){
			
			Debug.printStackTrace( e );
		}
		
		return( resume_key );
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?