All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.integritychecker.ui.impl.IntegrityCheckerPresentationControlActor Maven / Gradle / Ivy

/*
 * #%L
 * *********************************************************************************************************************
 * 
 * SolidBlue - open source safe data
 * http://solidblue.tidalwave.it - hg clone https://bitbucket.org/tidalwave/solidblue-src
 * %%
 * Copyright (C) 2011 - 2014 Tidalwave s.a.s. (http://tidalwave.it)
 * %%
 * *********************************************************************************************************************
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 * 
 * *********************************************************************************************************************
 * 
 * $Id$
 * 
 * *********************************************************************************************************************
 * #L%
 */
package it.tidalwave.integritychecker.ui.impl;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
import org.joda.time.Duration;
import org.joda.time.format.PeriodFormat;
import org.joda.time.format.PeriodFormatter;
import it.tidalwave.netbeans.util.Locator;
import it.tidalwave.messagebus.annotation.ListensTo;
import it.tidalwave.actor.Collaboration;
import it.tidalwave.actor.CollaborationCompletedMessage;
import it.tidalwave.actor.CollaborationStartedMessage;
import it.tidalwave.actor.MessageSupport;
import it.tidalwave.actor.annotation.Actor;
import it.tidalwave.actor.annotation.Message;
import it.tidalwave.actor.annotation.OriginatedBy;
import it.tidalwave.actor.io.filescan.FileDiscoveredMessage;
import it.tidalwave.integritychecker.archive.ScanRequest;
import it.tidalwave.integritychecker.fingerprint.FingerprintComputedMessage;
import it.tidalwave.integritychecker.ui.IntegrityCheckerFieldsBean;
import it.tidalwave.integritychecker.ui.IntegrityCheckerPresentationProvider;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import static java.util.concurrent.TimeUnit.*;

/***********************************************************************************************************************
 * 
 * @stereotype Actor
 * @stereotype Control
 * 
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 **********************************************************************************************************************/
@Actor(threadSafe=false) @NotThreadSafe @Slf4j
public class IntegrityCheckerPresentationControlActor
  {
    private static final double K10 = 1000;
    private static final double M10 = 1000000;
    
    @Message(outOfBand=true, daemon=true) @ToString
    private static class RefreshPresentationMessage extends MessageSupport
      {
      }
            
    // TODO: @Inject
    private IntegrityCheckerPresentationProvider presentation = Locator.find(IntegrityCheckerPresentationProvider.class);
    
    private final IntegrityCheckerFieldsBean fields = new IntegrityCheckerFieldsBean();
    
    private boolean autoRefresh = false;
    
    private int totalFileCount;
    
    private long totalDataSize;
    
    private int processedFileCount;
    
    private long processedDataSize;
    
    private final PeriodFormatter periodFormatter = PeriodFormat.getDefault();
    
    /*******************************************************************************************************************
     * 
     * Resets statistics when a new scan is started.
     * 
     ******************************************************************************************************************/
    void onScanStarted (final @ListensTo @Nonnull CollaborationStartedMessage cMessage,
                        final @OriginatedBy @Nonnull ScanRequest message)
      {
        log.info("onScanStarted({}, {})", cMessage, message);
        totalFileCount = 0;
        totalDataSize = 0;
        processedFileCount = 0;
        processedDataSize = 0;
        autoRefresh = true;
        new RefreshPresentationMessage().send();
        presentation.get().renderBeginOfScan();
      }
    
    /*******************************************************************************************************************
     * 
     * Stops activities when the scan has been completed.
     * 
     ******************************************************************************************************************/
    void onScanCompleted (final @ListensTo @Nonnull CollaborationCompletedMessage cMessage,
                          final @OriginatedBy @Nonnull ScanRequest message)
      {
        log.info("onScanCompleted({}, {})", cMessage, message);
        autoRefresh = false;
        fields.setProgressLabel("done");
        new RefreshPresentationMessage().send();
      }
    
    /*******************************************************************************************************************
     * 
     * Updates the statistics for a new discovered file.
     * 
     ******************************************************************************************************************/
    void onFileDiscovered (final @ListensTo @Nonnull FileDiscoveredMessage message)
      {
        log.trace("onFileDiscovered({})", message);
        totalFileCount++;
        totalDataSize += message.getPath().toFile().length();
      }
    
    /*******************************************************************************************************************
     * 
     * Updates the statistics for a new fingerprint computed.
     * 
     ******************************************************************************************************************/
    void onFingerprintComputed (final @ListensTo @Nonnull FingerprintComputedMessage message)
      {
        log.trace("onFingerprintComputed({})", message);
        processedFileCount++;
        processedDataSize += message.getPath().toFile().length();
        final Collaboration collaboration = message.getCollaboration();
        final long elapsedTime = collaboration.getDuration().getMillis();
        final double speed = (processedDataSize / M10) / (elapsedTime / K10);
        final int eta = 1000 * (int)(((totalDataSize - processedDataSize) / M10) / speed);
        
        fields.setProcessed(String.format("%.1f MB in %d files", processedDataSize / M10, processedFileCount));
        fields.setTotal(String.format("%.1f MB in %d files", totalDataSize / M10, totalFileCount));
        fields.setElapsedTime(periodFormatter.print(new Duration(truncatedToSecond(elapsedTime)).toPeriod()));
        fields.setRemainingTime(periodFormatter.print(new Duration(truncatedToSecond(eta)).toPeriod()));
        fields.setSpeed(String.format("%.1f MB/s", speed));
        fields.setPending(Integer.toString(collaboration.getDeliveringMessagesCount()));
        fields.setRunning(Integer.toString(collaboration.getRunningThreadsCount()));
        fields.setProgress(processedDataSize / (float)totalDataSize);
        fields.setProgressLabel(String.format("%.1f %%", 100 * fields.getProgress()));
      }
    
    /*******************************************************************************************************************
     * 
     * Updates the presentation.
     * 
     ******************************************************************************************************************/
    void onRefreshPresentation (final @ListensTo @Nonnull RefreshPresentationMessage message)
      {
        presentation.get().populate(fields);
        
        if (autoRefresh)
          {
            new RefreshPresentationMessage().sendLater(1, SECONDS);
          }
      }
    
    /*******************************************************************************************************************
     * 
     * 
     ******************************************************************************************************************/
    @Nonnegative 
    private static long truncatedToSecond (final @Nonnegative long time)
      {
        return time - time % 1000;
      }
  }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy