Package org.jmule.core.sharingmanager

Source Code of org.jmule.core.sharingmanager.SharingManagerImpl

/*
*  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.MAX_OFFER_FILES;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.jmule.core.JMIterable;
import org.jmule.core.JMThread;
import org.jmule.core.JMuleAbstractManager;
import org.jmule.core.JMuleCoreFactory;
import org.jmule.core.JMuleManagerException;
import org.jmule.core.configmanager.ConfigurationAdapter;
import org.jmule.core.configmanager.ConfigurationManager;
import org.jmule.core.configmanager.ConfigurationManagerException;
import org.jmule.core.configmanager.ConfigurationManagerSingleton;
import org.jmule.core.downloadmanager.DownloadManagerSingleton;
import org.jmule.core.edonkey.FileHash;
import org.jmule.core.edonkey.metfile.KnownMet;
import org.jmule.core.edonkey.metfile.KnownMetEntity;
import org.jmule.core.edonkey.metfile.PartMet;
import org.jmule.core.networkmanager.InternalNetworkManager;
import org.jmule.core.networkmanager.NetworkManagerSingleton;
import org.jmule.core.servermanager.InternalServerManager;
import org.jmule.core.servermanager.Server;
import org.jmule.core.servermanager.ServerManagerSingleton;
import org.jmule.core.statistics.JMuleCoreStats;
import org.jmule.core.statistics.JMuleCoreStatsProvider;
import org.jmule.core.uploadmanager.UploadManager;
import org.jmule.core.uploadmanager.UploadSession;
import org.jmule.core.utils.timer.JMTimer;
import org.jmule.core.utils.timer.JMTimerTask;

public class SharingManagerImpl extends JMuleAbstractManager implements InternalSharingManager {
 
  private InternalNetworkManager _network_manager;
  private InternalServerManager _server_manager;
 
  private Map<FileHash, SharedFile> sharedFiles;
  private LoadCompletedFiles load_completed_files;
  private LoadPartialFiles load_partial_files;
  private SharedFile current_hashing_file;

  private List<CompletedFileListener> completed_file_listeners = new LinkedList<CompletedFileListener>();

  private Map<FileHash, SharedFile> server_shared_files = new HashMap<FileHash, SharedFile>();
  private JMTimer sharing_manager_timer;
  private JMTimerTask rescan_dirs_task;
  private JMTimerTask server_sharing_task;
  private JMTimerTask store_metadata_task;
 
  SharingManagerImpl() {
   
  }

  public void initialize() {
    try {
      super.initialize();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }
    _network_manager = (InternalNetworkManager) NetworkManagerSingleton.getInstance();
    _server_manager = (InternalServerManager) ServerManagerSingleton.getInstance();
    sharing_manager_timer = new JMTimer();
    sharedFiles = new ConcurrentHashMap<FileHash, SharedFile>();

    Set<String> types = new HashSet<String>();
    types.add(JMuleCoreStats.ST_DISK_SHARED_FILES_COUNT);
    types.add(JMuleCoreStats.ST_DISK_SHARED_FILES_PARTIAL_COUNT);
    types.add(JMuleCoreStats.ST_DISK_SHARED_FILES_COMPLETE_COUNT);
    types.add(JMuleCoreStats.ST_DISK_SHARED_FILES_BYTES);
    types.add(JMuleCoreStats.ST_DISK_SHARED_FILES_PARTIAL_BYTES);
    types.add(JMuleCoreStats.ST_DISK_SHARED_FILES_COMPLETE_BYTES);

    JMuleCoreStats.registerProvider(types, new JMuleCoreStatsProvider() {
      public void updateStats(Set<String> types,
          Map<String, Object> values) {
        if (types.contains(JMuleCoreStats.ST_DISK_SHARED_FILES_COUNT))
          values.put(JMuleCoreStats.ST_DISK_SHARED_FILES_COUNT,
              sharedFiles.size());
        if (types
            .contains(JMuleCoreStats.ST_DISK_SHARED_FILES_PARTIAL_COUNT))
          values.put(
              JMuleCoreStats.ST_DISK_SHARED_FILES_PARTIAL_COUNT,
              getPartialFiles().size());
        if (types
            .contains(JMuleCoreStats.ST_DISK_SHARED_FILES_COMPLETE_COUNT))
          values.put(
              JMuleCoreStats.ST_DISK_SHARED_FILES_COMPLETE_COUNT,
              getCompletedFiles().size());
        if (types.contains(JMuleCoreStats.ST_DISK_SHARED_FILES_BYTES)) {
          long total_bytes = 0;
          for (PartialFile shared_file : getPartialFiles())
            total_bytes += shared_file.getDownloadedBytes();

          for (CompletedFile shared_file : getCompletedFiles())
            total_bytes += shared_file.length();

          values.put(JMuleCoreStats.ST_DISK_SHARED_FILES_BYTES,
              total_bytes);
        }
        if (types
            .contains(JMuleCoreStats.ST_DISK_SHARED_FILES_PARTIAL_BYTES)) {
          long total_bytes = 0;
          for (PartialFile shared_file : getPartialFiles())
            total_bytes += shared_file.getDownloadedBytes();
          values.put(
              JMuleCoreStats.ST_DISK_SHARED_FILES_PARTIAL_BYTES,
              total_bytes);
        }

        if (types
            .contains(JMuleCoreStats.ST_DISK_SHARED_FILES_COMPLETE_BYTES)) {
          long total_bytes = 0;
          for (CompletedFile shared_file : getCompletedFiles())
            total_bytes += shared_file.length();
          values.put(
              JMuleCoreStats.ST_DISK_SHARED_FILES_COMPLETE_BYTES,
              total_bytes);
        }
      }
    });

    JMuleCoreFactory.getSingleton().getConfigurationManager()
        .addConfigurationListener(new ConfigurationAdapter() {
          public void sharedDirectoriesChanged(List<File> sharedDirs) {
            loadCompletedFiles();
          }
        });
  }

  /**
   * A set of actions that are applied on the given file This interface is
   * meant to be used in conjunction with traverseDir method
   *
   * @see {@link #traverseDir(File, boolean, WorkOnFiles) traverseDir}
   * @author javajox
   */
  private interface WorkOnFiles {
    /**
     * A set of actions that are applied on the given file
     *
     * @param file
     */
    public void doWork(File file);

    /**
     * Tells if we still need to traverse the directory This method is very
     * important, if we need to interrupt the "traverse process" without
     * side effects we MUST call this method
     */
    public boolean stopTraverseDir();
  }

  /**
   * Traverse a directory in a non-recursive mode
   *
   * @param dir
   *            the directory that we have to traverse
   * @param with_part_met_extension
   *            has a role of filter, if given, only files with part.met at
   *            the end of file name are permitted
   * @param work_on_files
   *            the actions that are applied on the found file
   */
  private void traverseDir(File dir, boolean with_part_met_extension,
      WorkOnFiles work_on_files) {
    Queue<File> list_of_dirs = new LinkedList<File>();
    File[] list_of_files;
    File current_dir;

    list_of_dirs.offer(dir);
    while (list_of_dirs.size() != 0) {
      if (work_on_files.stopTraverseDir())
        return;
      current_dir = list_of_dirs.poll();
      if (with_part_met_extension)
        list_of_files = current_dir.listFiles(new FileFilter() {
          public boolean accept(File file) {
            if (file.isDirectory())
              return true;
            if (file.getName().endsWith(PART_MET_EXTENSION))
              return true;
            return false;
          }

        });
      else
        list_of_files = current_dir.listFiles();
      for (File file : list_of_files) {
        if (work_on_files.stopTraverseDir())
          return;
        if (file.isDirectory())
          list_of_dirs.offer(file);
        else {
          work_on_files.doWork(file);
        }
      }
    }
  }

  public void start() {
    try {
      super.start();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }

    rescan_dirs_task = new JMTimerTask() {
      public void run() {
        loadCompletedFiles();
      }
    };
    store_metadata_task = new JMTimerTask() {
      public void run() {
        writeMetadata();
      }
    };
    sharing_manager_timer.addTask(rescan_dirs_task,
        ConfigurationManager.DIR_RESCAN_INTERVAL, true);
   
    sharing_manager_timer.addTask(store_metadata_task,
        ConfigurationManager.WRITE_METADATA_INTERVAL, true);
  }
 
  protected boolean iAmStoppable() {
    return false;
  }
 
  public void startSharingFilesToServer() {
    server_sharing_task = new JMTimerTask() {
      public void run() {
        List<SharedFile> files_to_share = new LinkedList<SharedFile>();
        for (FileHash fileHash : sharedFiles.keySet()) {
          if (files_to_share.size() == MAX_OFFER_FILES)
            break;
          if (server_shared_files.containsKey(fileHash))
            break;
          files_to_share.add(sharedFiles.get(fileHash));
          server_shared_files
              .put(fileHash, sharedFiles.get(fileHash));
        }
        if (files_to_share.size() == 0) return ;
               
        Server server = _server_manager.getConnectedServer();
        _network_manager.offerFilesToServer(server.getClientID(),
            files_to_share);

      }
    };
    sharing_manager_timer.addTask(server_sharing_task, ConfigurationManager.SHARED_FILES_PUBLISH_INTERVAL, true);
    new JMThread() {
      public void run() {
        server_sharing_task.run();
      }     
    }.start();
  }

  public void stopSharingFilesToServer() {
    if (server_sharing_task != null)
      server_sharing_task.stopTask();
    server_shared_files.clear();
  }

  public boolean isLoadingCompletedFileProcessRunning() {

    if (load_completed_files == null)
      return false;

    return load_completed_files.isDone();

  }

  public boolean isLoadingPartialFileProcessRunning() {

    if (load_partial_files == null)
      return false;

    return load_partial_files.isDone();
  }

  private class LoadPartialFiles extends JMFileTask {
    public void run() {
      isDone = false;
      File shared_dir = new File(ConfigurationManager.TEMP_DIR);
      traverseDir(shared_dir, true, new WorkOnFiles() {
        public void doWork(File file) {
          try {
            PartMet part_met = new PartMet(file);
            part_met.loadFile();
            PartialFile partial_shared_file = new PartialFile(
                part_met);
            sharedFiles.put(partial_shared_file.getFileHash(),
                partial_shared_file);
            JMuleCoreFactory.getSingleton().getDownloadManager()
                .addDownload(partial_shared_file);
          } catch (Throwable t) {
            t.printStackTrace();
          }
        }

        public boolean stopTraverseDir() {

          return stop;
        }

      });
      isDone = true;
    }

    public double getPercent() {

      return 0;
    }
  }

  private class LoadCompletedFiles extends JMFileTask {

    private FileHashing file_hashing;
    private List<CompletedFile> files_needed_to_hash;

    Map<String, KnownMetEntity> known_file_list;
    Set<FileHash> files_hash_set = new HashSet<FileHash>();

    public void JMStop() {

      super.JMStop();

      if ((file_hashing != null) && (file_hashing.isAlive()))
        file_hashing.JMStop();

    }

    public void run() {
      isDone = false;
      String knownFilePath = ConfigurationManager.KNOWN_MET;

      // new files from user's shared dirs that need to be hashed
      files_needed_to_hash = new CopyOnWriteArrayList<CompletedFile>();

      files_hash_set.clear();
      for (FileHash fileHash : sharedFiles.keySet())
        if (!DownloadManagerSingleton.getInstance().hasDownload(
            fileHash))
          files_hash_set.add(fileHash);

      // load shared completed files
      try {
        KnownMet known_met = new KnownMet(knownFilePath);
        known_file_list = known_met.loadFile();
        known_met.close();
      } catch (Throwable e) {
        e.printStackTrace();
        known_file_list = new Hashtable<String, KnownMetEntity>();
      }

      File incoming_dir = new File(ConfigurationManager.INCOMING_DIR);
      List<File> shared_dirs = null;
      try {
        shared_dirs = ConfigurationManagerSingleton.getInstance()
            .getSharedFolders();
      } catch (ConfigurationManagerException e1) {

        e1.printStackTrace();
      }
      if (shared_dirs == null)
        shared_dirs = new LinkedList<File>();
      shared_dirs.add(incoming_dir);

      for (File dir : shared_dirs) {
        if (stop)
          return;
        traverseDir(dir, false, new WorkOnFiles() {
          String file_name;
          long file_size;
          KnownMetEntity known_met_entity = null;

          public void doWork(File file) {
            file_name = file.getName();
            file_size = file.length();
            known_met_entity = known_file_list.get(file_name
                + file_size);
            if (known_met_entity == null) {
              files_needed_to_hash.add(new CompletedFile(file));
            } else {
              FileHash hash = known_met_entity.getFileHash();
              if (files_hash_set.contains(hash))
                files_hash_set.remove(hash);
              if (sharedFiles.get(hash) != null)
                return; // file already in list
              CompletedFile shared_completed_file = new CompletedFile(
                  file);
              try {
                shared_completed_file
                    .setHashSet(known_met_entity
                        .getPartHashSet());
              } catch (SharedFileException e) {
                e.printStackTrace();
              }
              shared_completed_file.setTagList(known_met_entity
                  .getTagList());
              sharedFiles.put(
                  shared_completed_file.getFileHash(),
                  shared_completed_file);
            }
            known_met_entity = null;
          }

          public boolean stopTraverseDir() {

            return stop;
          }
        });

      }
      for (FileHash file_hash : files_hash_set) {
        sharedFiles.remove(file_hash);
      }

      // hash new files from the file system
      boolean need_to_write_metadata = files_needed_to_hash.size() != 0;
      for (CompletedFile shared_completed_file : files_needed_to_hash) {
        current_hashing_file = null;
        if (stop)
          return;
        try {
          current_hashing_file = shared_completed_file;
          FileChannel file_channel = new FileInputStream(
              shared_completed_file.getFile()).getChannel();
          file_hashing = new FileHashing(file_channel);
          file_hashing.start();
          file_hashing.join();
          file_channel.close();
          files_needed_to_hash.remove(shared_completed_file);
          if (!file_hashing.isDone())
            continue;
          if (sharedFiles.containsKey(file_hashing.getFileHashSet()
              .getFileHash()))
            continue;
          shared_completed_file.setHashSet(file_hashing
              .getFileHashSet());
          sharedFiles.put(shared_completed_file.getFileHash(),
              shared_completed_file);

          notifyCompletedFileAdded(shared_completed_file);
        } catch (Throwable t) {
          current_hashing_file = null;
          t.printStackTrace();
        }
      }
      current_hashing_file = null;
      // write our files in known.met
      if (need_to_write_metadata) {
        writeMetadata();
      }
      isDone = true;
    }

    public double getPercent() {
      if (file_hashing == null)
        return 100;
      if (!file_hashing.isAlive())
        return 100;
      return file_hashing.getPercent();
    }

    public SharedFile getCurrentHashingFile() {
      return current_hashing_file;
    }

    public List<CompletedFile> getUnhashedFiles() {
      return files_needed_to_hash;
    }

  }

  public List<CompletedFile> getUnhashedFiles() {
    if ((load_completed_files == null) || (!load_completed_files.isAlive()))
      return null;
    return load_completed_files.getUnhashedFiles();
  }

  public double getCurrentHashingFilePercent() {

    if ((load_completed_files == null) || (!load_completed_files.isAlive()))
      return 0;

    return load_completed_files.getPercent();
  }

  public SharedFile getCurrentHashingFile() {

    if ((load_completed_files == null) || (!load_completed_files.isAlive()))
      return null;

    return load_completed_files.getCurrentHashingFile();
  }

  public void stopLoadingCompletedFiles() {
    if ((load_completed_files == null) || (!load_completed_files.isAlive()))
      return;
    load_completed_files.JMStop();
  }

  public void stopLoadingPartialFiles() {

    if ((load_partial_files == null) || (!load_partial_files.isAlive()))
      return;

    load_partial_files.JMStop();

  }

  public void loadCompletedFiles() {
    if (load_completed_files != null)
      if (load_completed_files.isAlive())
        return;
    load_completed_files = new LoadCompletedFiles();
    load_completed_files.start();
  }

  public void loadPartialFiles() {

    load_partial_files = new LoadPartialFiles();

    load_partial_files.start();
  }

  public CompletedFile getCompletedFile(FileHash fileHash) {
    SharedFile sharedFile = sharedFiles.get(fileHash);
    if (sharedFile == null)
      return null;
    if (!sharedFile.exists()) {
      sharedFiles.remove(fileHash);
      return null;
    }
    if (sharedFile instanceof CompletedFile)
      return (CompletedFile) sharedFile;
    else
      return null;
  }

  public PartialFile getPartialFle(FileHash fileHash) {
    SharedFile sharedFile = sharedFiles.get(fileHash);
    if (sharedFile == null)
      return null;
    if (!sharedFile.exists()) {
      sharedFiles.remove(fileHash);
      return null;
    }
    if (sharedFile instanceof PartialFile)
      return (PartialFile) sharedFile;
    else
      return null;
  }

  public void makeCompletedFile(FileHash fileHash)
      throws SharingManagerException {
    File incoming_dir = new File(ConfigurationManager.INCOMING_DIR);

    PartialFile shared_partial_file = getPartialFle(fileHash);
    if (shared_partial_file == null)
      throw new SharingManagerException("The file " + fileHash
          + "doesn't exists");
    shared_partial_file.closeFile();
    shared_partial_file.deletePartialFile();
    File completed_file = new File(incoming_dir.getAbsoluteFile()
        + File.separator + shared_partial_file.getSharingName());
    UploadManager upload_manager = JMuleCoreFactory.getSingleton()
        .getUploadManager();
    try {

      if (upload_manager.hasUpload(fileHash)) { // JMule is now uploading
                            // file, need to
                            // synchronize moving
        UploadSession upload_sessison = upload_manager
            .getUpload(fileHash);
        synchronized (upload_sessison.getSharedFile()) {
          sharedFiles.remove(fileHash);
          // FileUtils.moveFile(shared_partial_file.getFile(),
          // completed_file);
          shared_partial_file.getFile().renameTo(completed_file);
          CompletedFile shared_completed_file = new CompletedFile(
              completed_file);
          shared_completed_file.setHashSet(shared_partial_file
              .getHashSet());
          sharedFiles.put(fileHash, shared_completed_file);
        }
      } else {
        sharedFiles.remove(fileHash);
        // FileUtils.moveFile(shared_partial_file.getFile(),
        // completed_file);
        shared_partial_file.getFile().renameTo(completed_file);
        CompletedFile shared_completed_file = new CompletedFile(
            completed_file);
        shared_completed_file.setHashSet(shared_partial_file
            .getHashSet());
        sharedFiles.put(fileHash, shared_completed_file);
      }
      writeMetadata();
    } catch (Throwable e) {
      e.printStackTrace();
      throw new SharingManagerException(e);
    }
  }

  public void addPartialFile(PartialFile partialFile) {
    sharedFiles.put(partialFile.getFileHash(), partialFile);
  }

  public int getFileCount() {
    return sharedFiles.size();
  }

  public boolean hasFile(FileHash fileHash) {
    return sharedFiles.containsKey(fileHash);
  }

  public boolean existsFile(FileHash fileHash) {
    if (!hasFile(fileHash))
      return false;
    SharedFile shared_file = sharedFiles.get(fileHash);
    if (!shared_file.exists())
      return false;
    return true;
  }

  public SharedFile getSharedFile(FileHash fileHash) {
    if (!hasFile(fileHash))
      return null;
    SharedFile sharedFile = sharedFiles.get(fileHash);

    return sharedFile;
  }

  public JMIterable<SharedFile> getSharedFiles() {
    return new JMIterable<SharedFile>(sharedFiles.values().iterator());
  }

  public List<PartialFile> getPartialFiles() {
    List<PartialFile> file_list = new LinkedList<PartialFile>();
    for (SharedFile file : sharedFiles.values()) {
      if (file instanceof PartialFile)
        file_list.add((PartialFile) file);
    }

    return file_list;
  }

  public List<CompletedFile> getCompletedFiles() {
    List<CompletedFile> file_list = new LinkedList<CompletedFile>();

    for (SharedFile file : sharedFiles.values())
      if (file instanceof CompletedFile)
        file_list.add((CompletedFile) file);

    return file_list;
  }

  public void writeMetadata() {
    try {
      KnownMet known_met = new KnownMet(ConfigurationManager.KNOWN_MET);
      known_met.writeFile(sharedFiles.values());
      known_met.close();
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }

  public void shutdown() {

    try {
      super.shutdown();
    } catch (JMuleManagerException e) {
      e.printStackTrace();
      return;
    }

    sharing_manager_timer.stop();

    stopLoadingCompletedFiles();

    stopLoadingPartialFiles();
    writeMetadata();

  }

  public void addCompletedFileListener(CompletedFileListener listener) {

    completed_file_listeners.add(listener);

  }

  public void removeCompletedFileListener(CompletedFileListener listener) {

    completed_file_listeners.remove(listener);
  }

  private void notifyCompletedFileAdded(CompletedFile file) {

    for (CompletedFileListener listener : completed_file_listeners) {

      listener.fileAdded(file);

    }

  }

  public SharedFile getSharedFile(File file) {
    for (SharedFile shared_file : sharedFiles.values()) {
      if (shared_file.getAbsolutePath().equals(file.getAbsolutePath()))
        return shared_file;
    }

    return null;
  }

  public void removeSharedFile(FileHash fileHash) {
    SharedFile shared_file = sharedFiles.get(fileHash);
    if (shared_file == null)
      return;
    sharedFiles.remove(fileHash);
    shared_file.closeFile();
    if (shared_file instanceof CompletedFile)
      return;
    shared_file.delete();
  }

}
TOP

Related Classes of org.jmule.core.sharingmanager.SharingManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.