public TorrentHandle addTorrent(File outputParent, File torrentFile) {
    TorrentHandle torrent = session.addTorrent(torrentFile, outputParent);

    log.info("added torrent: " + torrent.getName() + " , path: " + torrentFile.getAbsolutePath());

    shareTorrent(torrent);
    infoHashToTorrentMap.put(torrent.getInfoHash().toString().toLowerCase(), torrent);

    return torrent;
  }
  private LibtorrentEngine() {
    log.info("Starting up libtorrent with version: " + LibTorrent.version());

    session = new Session();

    sessionSettings = SessionSettings.newDefaults();
    //		sessionSettings = SessionSettings.newMinMemoryUsage();
    //		sessionSettings = SessionSettings.newHighPerformanceSeed();

    //		sessionSettings.setTorrentConnectBoost(5);
    //		sessionSettings.setMinReconnectTime(1);
    //		session.stopDHT();

    sessionSettings.setActiveDownloads(5);
    sessionSettings.setActiveLimit(30);
    sessionSettings.setActiveSeeds(20);
    //		sessionSettings.setActiveDHTLimit(5);
    //		sessionSettings.setActiveTrackerLimit(30);

    sessionSettings.setUploadRateLimit(4000000);
    sessionSettings.setDownloadRateLimit(4000000);

    // These worked great!
    //		sessionSettings.setMixedModeAlgorithm(BandwidthMixedAlgo.);
    session.stopLSD();
    session.stopDHT();
    sessionSettings.announceDoubleNAT(true);
    sessionSettings.setPeerConnectTimeout(60);

    sessionSettings.useReadCache(false);
    sessionSettings.setMaxPeerlistSize(500);
    //		sessionSettings.setMaxPeerlistSize(20);
    sessionSettings.setHalgOpenLimit(5);

    //		sessionSettings.setDHTAnnounceInterval(3600);
    sessionSettings.setMinAnnounceInterval(3600);
    //		sessionSettings.setLocalServiceAnnounceInterval(3600);

    //		sessionSettings.setNoConnectPrivilegedPorts(true);

    sessionSettings.setTrackerBackoff(10);
    sessionSettings.setAutoManageInterval(600);
    sessionSettings.setRateLimitIPOverhead(true);
    //		sessionSettings.setTrackerReceiveTimeout(1);
    //		sessionSettings.setTrackerCompletionTimeout(1);
    //		sessionSettings.setStopTrackerTimeout(1);
    //		sessionSettings.setActiveLsdLimit(1);

    //		sessionSettings.setPeerTimeout(5);
    //		sessionSettings.setInactivityTimeout(5);

    //				sessionSettings.setMaxPeerlistSize(10);

    //		sessionSettings.setMaxPausedPeerlistSize(0);
    //				sessionSettings.setChokingAlgorithm(ChokingAlgorithm.RATE_BASED_CHOKER);
    //		sessionSettings.setCacheSize(999999);

    //		sessionSettings.setPeerConnectTimeout(35);

    //		sessionSettings.allowMultipleConnectionsPerIp(true);

    //		sessionSettings.setPeerTimeout(15);
    //				sessionSettings.setInactivityTimeout(30);

    //				sessionSettings.setConnectionsLimit(100000);

    //				sessionSettings.setConnectionSpeed(3000);

    // Performance settings

    //		sessionSettings.setAutoManageInterval(10);
    //		sessionSettings.setAutoScrapeInterval(5);
    //		sessionSettings.setMinAnnounceInterval(5);

    //		sessionSettings.setAnnounceToAllTrackers(false);
    //		sessionSettings.setDHTAnnounceInterval(5);
    //		sessionSettings.setMaxAllowedInRequestQueue(9999);
    //		sessionSettings.setUnchokeSlotsLimit(800);
    //		sessionSettings.setCacheExpiry(9999);

    //		sessionSettings.setAutoManagePreferSeeds(true);

    //		sessionSettings.setSendBufferLowWatermark(50);

    session.setSettings(sessionSettings);

    log.info("active seed limit: " + String.valueOf(session.getSettings().getActiveLimit()));

    this.scanInfos = new LinkedHashSet<ScanInfo>();
    this.infoHashToTorrentMap = new HashMap<String, TorrentHandle>();

    session.addListener(
        new AlertListener() {

          @Override
          public int[] types() {
            // TODO Auto-generated method stub
            return null;
          }

          @Override
          public void alert(Alert<?> alert) {
            //				log.debug(alert.getType() + " - " + alert.getSwig().what() + " - " +
            // alert.getSwig().message());

          }
        });
  }
 public void updateSettings() {
   session.setSettings(sessionSettings);
   log.info("Libtorrent settings updated");
 }
  private void shareTorrent(TorrentHandle torrent) {

    // Add the listeners
    session.addListener(
        new TorrentAlertAdapter(torrent) {

          //			@Override
          //			public void stats(StatsAlert alert) {
          //				TorrentStats ts = TorrentStats.create(torrent);
          //				log.info(ts.toString());
          //
          //				super.stats(alert);
          //			}

          @Override
          public void stateChanged(StateChangedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void blockFinished(BlockFinishedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void torrentFinished(TorrentFinishedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void blockDownloading(BlockDownloadingAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void peerConnect(PeerConnectAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void peerSnubbed(PeerSnubbedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void peerUnsnubbe(PeerUnsnubbedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void saveResumeData(SaveResumeDataAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void saveResumeDataFailed(SaveResumeDataFailedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void peerDisconnected(PeerDisconnectedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void peerBan(PeerBanAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void peerError(PeerErrorAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void peerBlocked(PeerBlockedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void trackerAnnounce(TrackerAnnounceAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void trackerReply(TrackerReplyAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
            torrent.setAutoManaged(true);
          }

          @Override
          public void trackerWarning(TrackerWarningAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void trackerError(TrackerErrorAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void dhtReply(DhtReplyAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
            //				torrent.setAutoManaged(true);
          }

          @Override
          public void torrentPaused(TorrentPausedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());

            //								torrent.saveResumeData();
            //				torrent.resume();
          }

          @Override
          public void torrentError(TorrentErrorAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void torrentResumed(TorrentResumedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void torrentUpdate(TorrentUpdateAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void torrentChecked(TorrentCheckedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }

          @Override
          public void fastresumeRejected(FastresumeRejectedAlert alert) {
            log.debug(
                alert.getType()
                    + " - "
                    + alert.getSwig().what()
                    + " - "
                    + alert.getSwig().message());
          }
        });

    torrent.resume();
  }
  public Integer getActiveTorrents() {
    for (TorrentHandle t : session.getTorrents()) {}

    return 0;
  }
  public void startSeedingLibrary() {

    Tools.dbInit();
    List<Library> library = LIBRARY.findAll();
    library.isEmpty();
    Tools.dbClose();

    // start sharing them
    Integer i = 0;
    while (i < library.size()) {
      log.info("File #" + i.toString() + "/" + library.size() + " songs in library");
      Library track = library.get(i);
      String torrentPath = track.getString("torrent_path");
      String filePath = track.getString("file_path");

      File outputParent = new File(filePath).getParentFile();

      TorrentHandle torrent = addTorrent(outputParent, new File(torrentPath));

      // Set up the scanInfo
      ScanInfo si = ScanInfo.create(new File(filePath));
      si.setStatus(ScanStatus.Seeding);
      si.setMbid(track.getString("mbid"));
      scanInfos.add(si);

      // Do increments of every x, but only after the x'th torrent announce was a success
      if (i % 25 == 0) {
        //				log.info("active torrents:" + session.getStatus().get)
        torrent.setAutoManaged(false);
        torrent.resume();
        torrent.forceReannounce();
        try {
          final CountDownLatch signal = new CountDownLatch(1);

          session.addListener(
              new TorrentAlertAdapter(torrent) {
                @Override
                public void trackerReply(TrackerReplyAlert alert) {
                  log.info("Tracked reply received for torrent " + torrent.getName());
                  signal.countDown();
                  torrent.setAutoManaged(true);
                }

                @Override
                public void peerConnect(PeerConnectAlert alert) {
                  log.info("Peer connect alert received for torrent " + torrent.getName());
                  signal.countDown();
                  torrent.setAutoManaged(true);
                }
              });

          signal.await();
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

      i++;
    }

    log.info("Done seeding library, total of " + session.getTorrents().size() + " torrents shared");
  }