⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 partialfile.java

📁 JMule是一个基于Java开发
💻 JAVA
字号:
/* *  JMule - Java file sharing client *  Copyright (C) 2007-2008 JMule team ( jmule@jmule.org / http://jmule.org ) * *  Any parts of this program derived from other projects, or contributed *  by third-party developers are copyrighted by their respective authors. * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version 2 *  of the License, or (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. * */package org.jmule.core.sharingmanager;import static org.jmule.core.edonkey.E2DKConstants.FT_FILESIZE;import static org.jmule.core.edonkey.E2DKConstants.PARTSIZE;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.nio.ByteBuffer;import java.util.Arrays;import java.util.Queue;import java.util.concurrent.ConcurrentLinkedQueue;import org.jmule.core.JMThread;import org.jmule.core.configmanager.ConfigurationManager;import org.jmule.core.downloadmanager.FileChunk;import org.jmule.core.edonkey.E2DKConstants;import org.jmule.core.edonkey.impl.FileHash;import org.jmule.core.edonkey.impl.PartHashSet;import org.jmule.core.edonkey.metfile.PartMet;import org.jmule.core.edonkey.metfile.PartMetException;import org.jmule.core.edonkey.packet.tag.TagList;import org.jmule.core.utils.MD4;import org.jmule.core.utils.MD4FileHasher;import org.jmule.util.Convert;import org.jmule.util.Misc;/** *  * @author binary256 * @version $$Revision: 1.11 $$ * Last changed by $$Author: binary256_ $$ on $$Date: 2008/10/19 18:53:03 $$ */public class PartialFile extends SharedFile {		public static final String PART_FILE_EXTENSION = ".part";		private String tempFileName;		private String metFileName;		private boolean checkedParts[];		private boolean hasHashSet = false;		private PartMet partFile;		public PartialFile(PartMet partFile) throws SharedFileException {				String tempDir = ConfigurationManager.TEMP_DIR;				file = new File(tempDir+File.separator+partFile.getTempFileName());				try {			readChannel = new RandomAccessFile(file,"rws").getChannel();			readChannel.position(0);		} catch (Throwable e) {			throw new SharedFileException("Failed to open "+file+"\n"+Misc.getStackTrace(e));		}				try {			writeChannel = new RandomAccessFile(file,"rws").getChannel();			writeChannel.position(0);		} catch (Throwable e) {			throw new SharedFileException("Failed to open "+file+"\n"+Misc.getStackTrace(e));		}				this.partFile = partFile;		this.tagList = partFile.getTagList();		tempFileName = tempDir + File.separator + partFile.getTempFileName();				metFileName = tempDir + File.separator + partFile.getName();				hashSet = partFile.getFileHashSet();		if (hashSet.isEmpty()) {			hasHashSet = false;		}		else			hasHashSet = true;				checkedParts = new boolean[Misc.getPartCount(length())];				int partCount = Misc.getPartCount(length());				for(int i = 0;i < partCount;i++) {			if (partFile.getGapList().getIntersectedGaps(PARTSIZE*i, PARTSIZE*(i+1)-1).size()==0)				checkedParts[i] = true;				else				checkedParts[i] = false;		}	}		public PartialFile(String fileName, long fileSize,FileHash fileHash,PartHashSet hashSet,TagList tagList) throws SharedFileException {				String tempDir = ConfigurationManager.TEMP_DIR;				tempFileName = tempDir + File.separator+fileName + PART_FILE_EXTENSION;				metFileName = tempDir + File.separator+fileName +  PartMet.PART_MET_FILE_EXTENTSION;				file = new File(tempFileName);				try {			readChannel = new RandomAccessFile(file,"rws").getChannel();			readChannel.position(0);		} catch (Throwable e) {			throw new SharedFileException("Failed to open "+file+"\n"+Misc.getStackTrace(e));		}				try {			writeChannel = new RandomAccessFile(file,"rws").getChannel();			writeChannel.position(0);		} catch (Throwable e) {			throw new SharedFileException("Failed to open "+file+"\n"+Misc.getStackTrace(e));		}				try {						partFile = new PartMet(metFileName);					} catch (PartMetException e1) {						throw new SharedFileException("Failed to create part.met file " + metFileName);					}				partFile.setTagList(tagList);				partFile.setFileSize(Convert.longToInt((fileSize)));				partFile.setTempFileName(fileName + ".part");				partFile.setRealFileName(fileName);						this.tagList = partFile.getTagList();				GapList gapList = new GapList();				gapList.addGap(0, fileSize);				partFile.setGapList(gapList);				if (hashSet==null) {			hasHashSet = false;			this.hashSet = new PartHashSet(fileHash);		} else 			hasHashSet = true;		checkedParts = new boolean[Misc.getPartCount(fileSize)];				int partCount = Misc.getPartCount(fileSize);				for(int i = 0;i<partCount;i++)							checkedParts[i] = false;						partFile.setFileHash(fileHash);				partFile.setFileHashSet(hashSet);				try {						partFile.writeFile();					} catch (PartMetException e) {						throw new SharedFileException("Failed to write part.met file");		}	}			public void setHashSet(PartHashSet newSet) throws SharedFileException  {		int partCount = Misc.getPartCount(this.length());		if (newSet.size() < partCount)			throw new SharedFileException("Wrong hash set response");				hasHashSet = true;		hashSet.clear();		for(int i = 0;i<partCount;i++)			hashSet.add(newSet.get(i));							partFile.setFileHashSet(hashSet);				try {					partFile.writeFile();				}catch(PartMetException e) {					}	}		public void deletePartialFile() {		partFile.delete();	}		public void delete() {		deletePartialFile();		super.delete();	}		public String toString() {				return "[ "+partFile.getName()+" "+this.length()+" Completed : "+Math.round(getPercentCompleted())+" % GapList : "+partFile.getGapList()+" ] ";			}		public String getSharingName() {				if (partFile == null) return null;				return this.partFile.getRealFileName();			}		public long getPartCount() {		long part_count = (long) Math.ceil((double)length() / (double)PARTSIZE);		if (length() % PARTSIZE!=0) part_count++;		return part_count;	}		public long getAvailablePartCount() {		long part_count = 0;		for(int i = 0;i<checkedParts.length;i++)			if (checkedParts[i])				part_count++;		return part_count;	}	public boolean isCompleted() {		if (getPercentCompleted()== 100d) return true;		return false;	}		public synchronized void writeData(FileChunk fileChunk) throws SharedFileException {			try { 				if (writeChannel == null) {										try {						writeChannel = new RandomAccessFile(file,"rws").getChannel();					} catch (Throwable e) {						throw new SharedFileException("Error on opening file");					}									}				//** Check file limit and add more data if need **//				long toAdd = 0;				if (writeChannel.size()<=fileChunk.getChunkStart()) {					toAdd = fileChunk.getChunkStart() - writeChannel.size();					toAdd += fileChunk.getChunkData().capacity();									} else				if ((writeChannel.size()>fileChunk.getChunkStart())&&(writeChannel.size()<=fileChunk.getChunkEnd())) {					toAdd = fileChunk.getChunkEnd() - writeChannel.size();				}				if (toAdd != 0) {					toAdd += E2DKConstants.PARTSIZE;					if (toAdd + writeChannel.size()>length()) {						toAdd = length() - writeChannel.size();					}					addBytes(toAdd);				}				writeChannel.position(fileChunk.getChunkStart());				fileChunk.getChunkData().position(0);				writeChannel.write(fileChunk.getChunkData());				partFile.getGapList().removeGap(fileChunk.getChunkStart(), fileChunk.getChunkStart()+fileChunk.getChunkData().capacity());								fileChunk.getChunkData().clear();								try {					partFile.writeFile();				} catch (PartMetException e) {					throw new SharedFileException("Failed to save part.met file\n"+Misc.getStackTrace(e));				}				checkFilePartsIntegrity();			}catch(Throwable t) {				throw new SharedFileException("Failed to write data\n"+Misc.getStackTrace(t));			}			}	private void addBytes(long bytes) {		long WRITE_BLOCK = 1024*1024*20;		ByteBuffer block = Misc.getByteBuffer(WRITE_BLOCK);			long blockCount = bytes / WRITE_BLOCK;				try {						writeChannel.position(writeChannel.size());					long byteCount = 0;						for(long i = 0;i<blockCount;i++) {								byteCount +=WRITE_BLOCK;								block.position(0);								writeChannel.write(block);							}			block.clear();			System.gc();			if ((bytes - byteCount)==0) return ;						ByteBuffer block2 = Misc.getByteBuffer(bytes - byteCount);						block2.position(0);						writeChannel.write(block2);			block2.clear();		} catch (IOException e) {									e.printStackTrace();					}			}	/**	 * @return true - file is ok !	 */	public boolean checkFullFileIntegrity() {				if (!hasHashSet()) return false;				PartHashSet fileHashSet = partFile.getFileHashSet();		PartHashSet newSet = MD4FileHasher.calcHashSets(writeChannel);		if (newSet.size()!=fileHashSet.size()) 			return false;				for(int i = 0;i<fileHashSet.size();i++) {						byte b[] = newSet.get(i);						byte a[] = fileHashSet.get(i);													if (!Arrays.equals(a, b)) {								long begin = PARTSIZE*i;								long end = PARTSIZE*(i+1)-1;								if (end>length()) end = length();								//Adding gap								this.partFile.getGapList().addGap(begin,end);							return false;			}					}				if (!newSet.getFileHash().equals(fileHashSet.getFileHash())) {						partFile.getGapList().addGap(0, length());						return false;					}				return true;	}		private boolean checkFilePartsIntegrity() {				if (!hasHashSet()) return false;				if (checkedParts.length==0) return true;				boolean status = true;				for(int i = 0;i<checkedParts.length;i++) {						if (!checkedParts[i]) {							long begin = PARTSIZE*i;						long end = PARTSIZE*(i+1)-1;						if(partFile.getGapList().getIntersectedGaps(begin, end).size()==0) {								if (checkPartIntegrity(i)) checkedParts[i] = true;								else {										partFile.getGapList().addGap(begin, end);										status = false;									}			}						}		}				return status;	}			private boolean checkPartIntegrity(int partID) {				long start = PARTSIZE*partID;				MD4 msgDigest = new MD4();				ByteBuffer partData = Misc.getByteBuffer(PARTSIZE);		msgDigest.reset();		try {						readChannel.position(start);						int count = readChannel.read(partData);			partData.limit(count);			msgDigest.update(partData);						ByteBuffer hashset = Misc.getByteBuffer(16);						msgDigest.finalDigest(hashset);						if (!Arrays.equals(hashSet.get(partID),hashset.array())) {				return false;			}			return true;					} catch (IOException e) {						return false;					}	}		public GapList getGapList() {				return partFile.getGapList();			}		public String getMetFileName() {				return metFileName;			}			public PartMet getPartMetFile() {				return partFile;			}		public long getDownloadedBytes() {				return length() - partFile.getGapList().byteCount();			}		public double getPercentCompleted() {				return (double)(getDownloadedBytes()*100)/(double)length();			}		public boolean hasHashSet() {				return this.hasHashSet;			}	public String getTempFileName() {				return tempFileName;			}			public long length() {				try {						return Convert.intToLong(tagList.getDWORDTag(FT_FILESIZE));					} catch (Throwable e) {			return 0; }	}		public void closeFile() {				if (write_thread != null)			if (write_thread.isAlive()) write_thread.JMStop();				partFile.close();		super.closeFile();	}			/*	 *  speed research	 */	private Queue<FileChunk> write_list = new ConcurrentLinkedQueue<FileChunk>();		private WriteThread write_thread;		private void writeChunk(FileChunk chunk) {		write_list.offer(chunk);		if (write_thread != null)			if (write_thread.isAlive()) return ;		write_thread = new WriteThread();		write_thread.start();	}		private class WriteThread extends JMThread {				private boolean stop = false;				public void JMStop() {			stop = true;		}				public WriteThread() {			super("File write thread");		}				public void run() {			while(!stop) {				if (write_list.size() == 0) return ;				System.out.println("Before Size : " + write_list.size());				FileChunk chunk = write_list.poll();				System.out.println("After Size : " + write_list.size());				try {										/** Check file limit and add more data if need **/										long toAdd = 0;										if (readChannel.size()<=chunk.getChunkStart()) {												toAdd = chunk.getChunkStart() - readChannel.size();												toAdd += chunk.getChunkData().capacity();											} else											if ((readChannel.size()>chunk.getChunkStart())&&(readChannel.size()<=chunk.getChunkEnd())) {												toAdd = chunk.getChunkEnd() - readChannel.size();											}					System.out.println("A");					if (toAdd != 0) {												addBytes(toAdd);											}					System.out.println("B");					readChannel.position(chunk.getChunkStart());										chunk.getChunkData().position(0);										readChannel.write(chunk.getChunkData());					System.out.println("C");					try {												partFile.writeFile();											} catch (PartMetException e) {												throw new SharedFileException("Failed to save part.met file");											}					System.out.println("D");					checkFilePartsIntegrity();									}catch(Throwable t) {									}							}		}	}	}

⌨️ 快捷键说明

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