private void doHttpMaxFailover() {
   long maxTimeAgo = clock.now() - silentPeriodForMaxHttpRequest;
   if (!httpRequestControl.requestQueued(HttpRequestControl.RequestReason.MAX)
       && UpdateSettings.LAST_SIMPP_FAILOVER.getValue() < maxTimeAgo) {
     int rndDelay = RANDOM.nextInt(maxMaxHttpRequestDelay) + minMaxHttpRequestDelay;
     final String rndUri = maxedUpdateList.get(RANDOM.nextInt(maxedUpdateList.size()));
     LOG.debug("Scheduling http max failover in: " + rndDelay + ", to: " + rndUri);
     backgroundExecutor.schedule(
         new Runnable() {
           public void run() {
             String url = rndUri;
             try {
               launchHTTPUpdate(url);
             } catch (URISyntaxException e) {
               httpRequestControl.requestFinished();
               httpRequestControl.cancelRequest();
               LOG.warn("uri failure", e);
             }
           }
         },
         rndDelay,
         TimeUnit.MILLISECONDS);
   } else {
     LOG.debug("Ignoring http max failover.");
   }
 }
  /** Determines if we're far enough past the timestamp to start a new in network download. */
  private boolean canStartDownload() {
    long now = clock.now();

    if (LOG.isDebugEnabled()) LOG.debug("now is " + now + " next time is " + _nextDownloadTime);

    return now > _nextDownloadTime;
  }
  /** begins an http failover. */
  private void checkForStaleUpdateAndMaybeDoHttpFailover() {
    LOG.debug("checking for timeout http failover");
    long monthAgo = clock.now() - ONE_MONTH;
    if (UpdateSettings.LAST_UPDATE_TIMESTAMP.getValue() < monthAgo
        && // more than a month ago
        UpdateSettings.LAST_HTTP_FAILOVER.getValue() < monthAgo
        && // and last failover too
        !httpRequestControl.requestQueued(
            HttpRequestControl.RequestReason.TIMEOUT)) { // and we're not already doing a failover

      long when = (connectionServices.isConnected() ? 1 : 5) * 60 * 1000;
      if (LOG.isDebugEnabled()) LOG.debug("scheduling http failover in " + when);

      backgroundExecutor.schedule(
          new Runnable() {
            public void run() {
              try {
                launchHTTPUpdate(timeoutUpdateLocation);
              } catch (URISyntaxException e) {
                httpRequestControl.requestFinished();
                httpRequestControl.cancelRequest();
                LOG.warn(e.toString(), e);
              }
            }
          },
          when,
          TimeUnit.MILLISECONDS);
    }
  }
  /** @return whether we killed any hopeless update downloads */
  private void killHopelessUpdates(List<? extends DownloadInformation> updates) {
    if (updates == null) return;

    if (!downloadManager.get().hasInNetworkDownload()) return;

    long now = clock.now();
    for (DownloadInformation info : updates) {
      Downloader downloader = downloadManager.get().getDownloaderForURN(info.getUpdateURN());
      if (downloader != null && downloader instanceof InNetworkDownloader) {
        InNetworkDownloader iDownloader = (InNetworkDownloader) downloader;
        if (isHopeless(iDownloader, now)) iDownloader.stop(false);
      }
    }
  }
Beispiel #5
0
 @Override
 public void initialize() {
   // Increment the session counter
   int sessions = ApplicationSettings.SESSIONS.getValue();
   ApplicationSettings.SESSIONS.setValue(sessions + 1);
   // Record the time between sessions
   long lastShutdown = ApplicationSettings.LAST_SHUTDOWN_TIME.getValue();
   long downtime;
   if (lastShutdown == 0) downtime = DEFAULT_DOWNTIME;
   else downtime = Math.max(0, (clock.now() - lastShutdown) / 1000);
   // If the number of downtimes is greater that the number of uptimes,
   // the last session must have ended without recording the uptime or
   // shutdown time. To avoid double-counting the downtime we should
   // overwrite the last downtime instead of appending.
   String[] downtimes = ApplicationSettings.DOWNTIME_HISTORY.get();
   String[] uptimes = ApplicationSettings.UPTIME_HISTORY.get();
   if (downtimes.length > uptimes.length)
     downtimes = updateHistory(downtimes, Long.toString(downtime));
   else downtimes = appendToHistory(downtimes, Long.toString(downtime));
   ApplicationSettings.DOWNTIME_HISTORY.set(downtimes);
   // Measure the time between refreshes
   lastUpdateTime = clock.now();
 }
Beispiel #6
0
 /** Refreshes the uptime statistics. Package access for testing. */
 void refreshStats() {
   long now = clock.now();
   long elapsed = (now - lastUpdateTime) / 1000;
   if (elapsed > 0) {
     currentUptime += elapsed;
     updateUptimeHistory(currentUptime);
     long totalUptime = ApplicationSettings.TOTAL_UPTIME.getValue() + elapsed;
     ApplicationSettings.TOTAL_UPTIME.setValue(totalUptime);
     int sessions = ApplicationSettings.SESSIONS.getValue();
     if (sessions > 0) {
       ApplicationSettings.AVERAGE_UPTIME.setValue(totalUptime / sessions);
     }
     ApplicationSettings.FRACTIONAL_UPTIME.setValue(stats.calculateFractionalUptime());
     ApplicationSettings.LAST_SHUTDOWN_TIME.setValue(now); // Pessimistic
   }
   lastUpdateTime = now;
 }
  /**
   * Tries to download updates.
   *
   * @return whether we had any non-hopeless updates.
   */
  private void downloadUpdates(
      List<? extends DownloadInformation> toDownload, ReplyHandler source) {
    if (toDownload == null) toDownload = Collections.emptyList();

    killObsoleteUpdates(toDownload);

    for (DownloadInformation next : toDownload) {
      if (isHopeless(next)) continue;

      if (downloadManager.get().isSavedDownloadsLoaded()
          && fileManager.get().getManagedFileList().isLoadFinished()) {

        // TODO: remove the cast
        ManagedDownloader md =
            (ManagedDownloader) downloadManager.get().getDownloaderForURN(next.getUpdateURN());

        // Skip to the next one since we already have a complete file.
        if (hasCompleteFile(next.getUpdateURN())) {
          if (md != null) {
            md.stop(false);
          }
          continue;
        }

        // If we don't have an existing download ...
        // and there's no existing InNetwork downloads &
        // no existing Store downloads &
        // we're allowed to start a new one.
        if (md == null && !downloadManager.get().hasInNetworkDownload() && canStartDownload()) {
          LOG.debug("Starting a new InNetwork Download");
          try {
            md = (ManagedDownloader) downloadManager.get().download(next, clock.now());
          } catch (SaveLocationException sle) {
            LOG.error("Unable to construct download", sle);
          }
        }

        if (md != null) {
          if (source != null) md.addDownload(rfd(source, next), false);
          else addCurrentDownloadSources(md, next);
        }
      }
    }
  }
  /**
   * Stores the given data to disk & posts an update to neighboring connections. Starts the download
   * of any updates
   */
  private void storeAndUpdate(byte[] data, UpdateCollection uc, UpdateType updateType) {
    if (LOG.isTraceEnabled())
      LOG.trace("Retrieved new data from: " + updateType + ", storing & updating.");
    if (uc.getId() == IGNORE_ID && updateType == UpdateType.FROM_NETWORK)
      throw new IllegalStateException("shouldn't be here!");

    // If an http max request is pending, don't even bother with this stuff.
    // We want to get it straight from the source...
    if (updateType == UpdateType.FROM_NETWORK
        && httpRequestControl.isRequestPending()
        && httpRequestControl.getRequestReason() == HttpRequestControl.RequestReason.MAX) return;

    _lastId = uc.getId();

    _lastTimestamp = uc.getTimestamp();
    UpdateSettings.LAST_UPDATE_TIMESTAMP.setValue(_lastTimestamp);

    long delay = UpdateSettings.UPDATE_DOWNLOAD_DELAY.getValue();
    long random = Math.abs(RANDOM.nextLong() % delay);
    _nextDownloadTime = _lastTimestamp + random;

    _lastBytes = data;

    if (updateType != UpdateType.FROM_DISK) {
      // cancel any http and pretend we just updated.
      if (httpRequestControl.getRequestReason() == HttpRequestControl.RequestReason.TIMEOUT)
        httpRequestControl.cancelRequest();
      UpdateSettings.LAST_HTTP_FAILOVER.setValue(clock.now());

      FileUtils.verySafeSave(CommonUtils.getUserSettingsDir(), FILENAME, data);
      capabilitiesVMFactory.updateCapabilities();
      connectionManager.get().sendUpdatedCapabilities();
    }

    Version limeV;
    try {
      limeV = new Version(LimeWireUtils.getLimeWireVersion());
    } catch (VersionFormatException vfe) {
      LOG.warn("Invalid LimeWire version", vfe);
      return;
    }

    Version javaV = null;
    try {
      javaV = new Version(VersionUtils.getJavaVersion());
    } catch (VersionFormatException vfe) {
      LOG.warn("Invalid java version", vfe);
    }

    // don't allow someone to set the style to be above major.
    int style = Math.min(UpdateStyle.STYLE_MAJOR, UpdateSettings.UPDATE_STYLE.getValue());

    UpdateData updateInfo =
        uc.getUpdateDataFor(
            limeV, ApplicationSettings.getLanguage(), LimeWireUtils.isPro(), style, javaV);

    List<DownloadInformation> updatesToDownload = uc.getUpdatesWithDownloadInformation();
    _killingObsoleteNecessary = true;

    // if we have an update for our machine, prepare the command line
    // and move our update to the front of the list of updates
    if (updateInfo != null && updateInfo.getUpdateURN() != null) {
      prepareUpdateCommand(updateInfo);
      updatesToDownload = new LinkedList<DownloadInformation>(updatesToDownload);
      updatesToDownload.add(0, updateInfo);
    }

    _updateInfo = updateInfo;
    _updatesToDownload = updatesToDownload;

    downloadUpdates(updatesToDownload, null);
    if (updateInfo == null) {
      LOG.warn("No relevant update info to notify about.");
      return;
    } else if (updateInfo.getUpdateURN() == null || isHopeless(updateInfo)) {
      if (LOG.isDebugEnabled())
        LOG.debug(
            "we have an update, but it doesn't need a download.  "
                + "or all our updates are hopeles. Scheduling URL notification...");

      updateInfo.setUpdateCommand(null);

      backgroundExecutor.schedule(
          new NotificationFailover(_lastId),
          delay(clock.now(), uc.getTimestamp()),
          TimeUnit.MILLISECONDS);
    } else if (isMyUpdateDownloaded(updateInfo)) {
      LOG.debug("there is an update for me, but I happen to have it on disk");
      fireUpdate(updateInfo);
    } else LOG.debug("we have an update, it needs a download.  Rely on callbacks");
  }