Changeset 580bb5a6


Ignore:
Timestamp:
May 23, 2012 4:36:37 PM (8 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
501f2f85
Parents:
e27df77
Message:
  • i2psnark:
    • Fixes when complete except for skipped files (ticket #447) status in UI, don't connect outbound, disconnect seeds when done
    • More classes pkg private
Location:
apps/i2psnark/java/src/org/klomp/snark
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • apps/i2psnark/java/src/org/klomp/snark/CoordinatorListener.java

    re27df77 r580bb5a6  
    2525 * Callback used when some peer changes state.
    2626 */
    27 public interface CoordinatorListener
     27interface CoordinatorListener
    2828{
    2929  /**
  • apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java

    re27df77 r580bb5a6  
    4949 * Coordinates what peer does what.
    5050 */
    51 public class PeerCoordinator implements PeerListener
     51class PeerCoordinator implements PeerListener
    5252{
    5353  private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerCoordinator.class);
     
    116116   */
    117117  private final List<Piece> wantedPieces;
     118
     119  /** The total number of bytes in wantedPieces, or -1 if not yet known.
     120   *  Sync on wantedPieces.
     121   *  @since 0.9.1
     122   */
     123  private long wantedBytes;
    118124
    119125  /** partial pieces - lock by synching on wantedPieces - TODO store Requests, not PartialPieces */
     
    172178  }
    173179
    174   // only called externally from Storage after the double-check fails
     180  /**
     181   * Only called externally from Storage after the double-check fails.
     182   * Sets wantedBytes too.
     183   */
    175184  public void setWantedPieces()
    176185  {
    177     if (metainfo == null || storage == null)
     186    if (metainfo == null || storage == null) {
     187        wantedBytes = -1;
    178188        return;
     189    }
    179190    // Make a list of pieces
    180191      synchronized(wantedPieces) {
     
    182193          BitField bitfield = storage.getBitField();
    183194          int[] pri = storage.getPiecePriorities();
     195          long count = 0;
    184196          for (int i = 0; i < metainfo.getPieces(); i++) {
    185197              // only add if we don't have and the priority is >= 0
     
    190202                      p.setPriority(pri[i]);
    191203                  wantedPieces.add(p);
    192               }
    193           }
     204                  count += metainfo.getPieceLength(i);
     205              }
     206          }
     207          wantedBytes = count;
    194208          Collections.shuffle(wantedPieces, _random);
    195209      }
     
    234248
    235249  /**
    236    * Returns how many bytes are still needed to get the complete file.
     250   *  Bytes not yet in storage. Does NOT account for skipped files.
     251   *  Not exact (does not adjust for last piece size).
     252   * Returns how many bytes are still needed to get the complete torrent.
    237253   * @return -1 if in magnet mode
    238254   */
     
    243259    // XXX - Only an approximation.
    244260    return ((long) storage.needed()) * metainfo.getPieceLength(0);
     261  }
     262
     263  /**
     264   *  Bytes still wanted. DOES account for skipped files.
     265   *  @return exact value. or -1 if no storage yet.
     266   *  @since 0.9.1
     267   */
     268  public long getNeededLength() {
     269      return wantedBytes;
    245270  }
    246271
     
    331356  }
    332357
     358  /**
     359   *  Inbound.
     360   *  Not halted, peers < max.
     361   *  @since 0.9.1
     362   */
    333363  public boolean needPeers()
    334364  {
    335365        return !halted && peers.size() < getMaxConnections();
     366  }
     367
     368  /**
     369   *  Outbound.
     370   *  Not halted, peers < max, and need pieces.
     371   *  @since 0.9.1
     372   */
     373  public boolean needOutboundPeers() {
     374        return wantedBytes != 0 && needPeers();
    336375  }
    337376 
     
    473512  }
    474513
    475 // returns true if actual attempt to add peer occurs
     514  /**
     515   * Add peer (inbound or outbound)
     516   * @return true if actual attempt to add peer occurs
     517   */
    476518  public boolean addPeer(final Peer peer)
    477519  {
     
    756798                      Piece piece = new Piece(i);
    757799                      wantedPieces.add(piece);
     800                      wantedBytes += metainfo.getPieceLength(i);
    758801                      // As connections are already up, new Pieces will
    759802                      // not have their PeerID list populated, so do that.
     
    778821                   iter.remove();
    779822                   toCancel.add(p);
     823                   wantedBytes -= metainfo.getPieceLength(p.getId());
    780824               }
    781825          }
     
    911955          }
    912956        wantedPieces.remove(p);
     957        wantedBytes -= metainfo.getPieceLength(p.getId());
    913958      }
    914959
    915960    // just in case
    916961    removePartialPiece(piece);
     962
     963    boolean done = wantedBytes <= 0;
    917964
    918965    // Announce to the world we have it!
     
    925972            if (p.isConnected())
    926973              {
    927                   if (completed() && p.isCompleted())
     974                  if (done && p.isCompleted())
    928975                      toDisconnect.add(p);
    929976                  else
     
    938985          }
    939986   
    940     if (completed()) {
     987    if (done) {
     988        // put msg on the console if partial, since Storage won't do it
     989        if (!completed())
     990            snark.storageCompleted(storage);
     991
    941992        synchronized (partialPieces) {
    942993            for (PartialPiece ppp : partialPieces) {
     
    12631314
    12641315  /**
     1316   *  Get peers from PEX -
    12651317   *  PeerListener callback
    12661318   *  @since 0.8.4
    12671319   */
    12681320  public void gotPeers(Peer peer, List<PeerID> peers) {
    1269       if (completed() || !needPeers())
     1321      if (!needOutboundPeers())
    12701322          return;
    12711323      Destination myDest = _util.getMyDestination();
  • apps/i2psnark/java/src/org/klomp/snark/Snark.java

    re27df77 r580bb5a6  
    783783
    784784    /**
     785     *  Bytes not yet in storage. Does NOT account for skipped files.
    785786     *  @return exact value. or -1 if no storage yet.
    786787     *          getNeeded() * pieceLength(0) isn't accurate if last piece
     
    803804
    804805    /**
     806     *  Bytes still wanted. DOES account for skipped files.
     807     *  FIXME -1 when not running.
     808     *  @return exact value. or -1 if no storage yet or when not running.
     809     *  @since 0.9.1
     810     */
     811    public long getNeededLength() {
     812        PeerCoordinator coord = coordinator;
     813        if (coord != null)
     814            return coord.getNeededLength();
     815        return -1;
     816    }
     817
     818    /**
     819     *  Does not account for skipped files.
    805820     *  @return number of pieces still needed (magnet mode or not), or -1 if unknown
    806821     *  @since 0.8.4
  • apps/i2psnark/java/src/org/klomp/snark/Storage.java

    re27df77 r580bb5a6  
    339339
    340340  /**
    341    *  Must call setPiecePriorities() after calling this
     341   *  Must call Snark.updatePiecePriorities()
     342   *  (which calls getPiecePriorities()) after calling this.
    342343   *  @param file canonical path (non-directory)
    343344   *  @param pri default 0; <0 to disable
  • apps/i2psnark/java/src/org/klomp/snark/StorageListener.java

    re27df77 r580bb5a6  
    2424 * Callback used when Storage changes.
    2525 */
    26 public interface StorageListener
     26interface StorageListener
    2727{
    2828  /**
  • apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java

    re27df77 r580bb5a6  
    7373  private boolean started;
    7474
    75   private List trackers;
     75  private List<Tracker> trackers;
    7676
    7777  /**
     
    261261              Tracker tr = (Tracker)iter.next();
    262262              if ((!stop) && (!tr.stop) &&
    263                   (completed || coordinator.needPeers()) &&
     263                  (completed || coordinator.needOutboundPeers()) &&
    264264                  (event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
    265265              {
     
    293293                    }
    294294
    295                     if ( (left != 0) && (!completed) ) {
     295                    if (coordinator.needOutboundPeers()) {
    296296                        // we only want to talk to new people if we need things
    297297                        // from them (duh)
     
    342342
    343343            // Get peers from PEX
    344             if (left > 0 && coordinator.needPeers() && (meta == null || !meta.isPrivate()) && !stop) {
     344            if (coordinator.needOutboundPeers() && (meta == null || !meta.isPrivate()) && !stop) {
    345345                Set<PeerID> pids = coordinator.getPEXPeers();
    346346                if (!pids.isEmpty()) {
     
    366366            if (_util.getDHT() != null && (meta == null || !meta.isPrivate()) && !stop) {
    367367                int numwant;
    368                 if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
     368                if (event.equals(STOPPED_EVENT) || !coordinator.needOutboundPeers())
    369369                    numwant = 1;
    370370                else
     
    460460        buf.append("&event=").append(event);
    461461    buf.append("&numwant=");
    462     if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
     462    if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needOutboundPeers())
    463463        buf.append('0');
    464464    else
  • apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java

    re27df77 r580bb5a6  
    891891        }
    892892        long total = snark.getTotalLength();
     893        // includes skipped files, -1 for magnet mode
    893894        long remaining = snark.getRemainingLength();
    894895        if (remaining > total)
    895896            remaining = total;
     897        // does not include skipped files, -1 for magnet mode or when not running.
     898        long needed = snark.getNeededLength();
     899        if (needed > total)
     900            needed = total;
    896901        long downBps = snark.getDownloadRate();
    897902        long upBps = snark.getUploadRate();
    898903        long remainingSeconds;
    899         if (downBps > 0)
    900             remainingSeconds = remaining / downBps;
     904        if (downBps > 0 && needed > 0)
     905            remainingSeconds = needed / downBps;
    901906        else
    902907            remainingSeconds = -1;
     
    939944                "<br>" + err;
    940945            }
    941         } else if (remaining == 0) {  // < 0 means no meta size yet
    942             if (isRunning && curPeers > 0 && !showPeers)
    943                 statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
     946        } else if (remaining == 0 || needed == 0) {  // < 0 means no meta size yet
     947            // partial complete or seeding
     948            if (isRunning) {
     949                String img;
     950                String txt;
     951                if (remaining == 0) {
     952                    img = "seeding";
     953                    txt = _("Seeding");
     954                } else {
     955                    // partial
     956                    img = "complete";
     957                    txt = _("Complete");
     958                }
     959                if (curPeers > 0 && !showPeers)
     960                    statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + img + ".png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + txt +
    944961                               ": <a href=\"" + uri + "?p=" + Base64.encode(snark.getInfoHash()) + "\">" +
    945962                               curPeers + thinsp(noThinsp) +
    946963                               ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
    947             else if (isRunning)
    948                 statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
     964                else
     965                    statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + img + ".png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + txt +
    949966                               ": " + curPeers + thinsp(noThinsp) +
    950967                               ngettext("1 peer", "{0} peers", knownPeers);
    951             else
     968            } else {
    952969                statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "complete.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Complete");
     970            }
    953971        } else {
    954972            if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
     
    10631081        out.write("</td>\n\t");
    10641082        out.write("<td align=\"right\" class=\"snarkTorrentRateDown\">");
    1065         if(isRunning && remaining != 0)
     1083        if(isRunning && needed > 0)
    10661084            out.write(formatSize(downBps) + "ps");
    10671085        out.write("</td>\n\t");
     
    11091127                // Can't figure out how to escape double quotes inside the onclick string.
    11101128                // Single quotes in translate strings with parameters must be doubled.
    1111                 // Then the remaining single quite must be escaped
     1129                // Then the remaining single quote must be escaped
    11121130                out.write(_("Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?", fullFilename));
    11131131                out.write("')) { return false; }\"");
     
    11281146            // Can't figure out how to escape double quotes inside the onclick string.
    11291147            // Single quotes in translate strings with parameters must be doubled.
    1130             // Then the remaining single quite must be escaped
     1148            // Then the remaining single quote must be escaped
    11311149            out.write(_("Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?", fullFilename));
    11321150            out.write("')) { return false; }\"");
     
    11951213                out.write("</td>\n\t");
    11961214                out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
    1197                 if (remaining > 0) {
     1215                if (needed > 0) {
    11981216                    if (peer.isInteresting() && !peer.isChoked()) {
    11991217                        out.write("<span class=\"unchoked\">");
     
    18871905                buf.append("<br>").append(_("Complete"));
    18881906            // else unknown
     1907            long needed = snark.getNeededLength();
     1908            if (needed > 0)
     1909                buf.append("<br>").append(_("Remaining")).append(": ").append(formatSize(needed));
    18891910            buf.append("<br>").append(_("Size")).append(": ").append(formatSize(snark.getTotalLength()));
    18901911            MetaInfo meta = snark.getMetaInfo();
Note: See TracChangeset for help on using the changeset viewer.