<commit_before>/*
 * This software is licensed under the GNU Affero General Public License, quoted below.
 *
 * This file is a part of PowerAPI.
 *
 * Copyright (C) 2011-2015 Inria, University of Lille 1.
 *
 * PowerAPI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * PowerAPI 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PowerAPI.
 *
 * If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
 */
package org.powerapi

import org.powerapi.configuration.TimeoutConfiguration

import scala.concurrent.{ Await, Future }
import scala.concurrent.duration.{ FiniteDuration, DurationInt }

import akka.actor.{ ActorRef, ActorRefFactory, ActorSystem, Props }
import akka.event.LoggingReceive
import akka.pattern.{ after, gracefulStop }

import org.powerapi.core.{Configuration, ActorComponent, MessageBus}
import org.powerapi.core.target.Target
import org.powerapi.core.power._

/**
 * PowerAPI object encapsulates all the messages.
 */
object PowerMeterMessages {
  case object StopAll
}

/**
 * Represents the main actor of a PowerMeter. Used to handle all the actors created for one PowerMeter.
 */
class PowerMeterActor(modules: Seq[PowerModule], eventBus: MessageBus) extends ActorComponent {
  import PowerMeterMessages._
  import org.powerapi.core.{ Clocks, Monitors }
  import org.powerapi.core.MonitorChannel.MonitorStart
  
  var clockSupervisor: Option[ActorRef] = None
  var monitorSupervisor: Option[ActorRef] = None
  
  // Starts the mandatory supervisors.
  override def preStart(): Unit = {
    clockSupervisor = Some(context.actorOf(Props(classOf[Clocks], eventBus), "clockSupervisor"))
    monitorSupervisor = Some(context.actorOf(Props(classOf[Monitors], eventBus), "monitorSupervisor"))
    
    modules.foreach(module => {
      module(eventBus)
      module.start(context)
    })
  }
  
  def receive = LoggingReceive {
    case msg: MonitorStart => {
      monitorSupervisor match {
        case Some(actorRef) => actorRef ! msg
        case _ => log.error("The monitor supervisor is not created")
      }
    }
    case StopAll => stopAll()
  } orElse default
  
  def stopAll(): Unit = {
    monitorSupervisor match {
      case Some(actorRef) => context.stop(actorRef)
      case _ => log.error("The monitor supervisor is not created")
    }

    clockSupervisor match {
      case Some(actorRef) => context.stop(actorRef)
      case _ => log.error("The clock supervisor is not created")
    }

    modules.foreach(module => {
      module.stop(context)
    })
  }
}

/**
 * Implements the main functionalities for configuring a <i>Software-Defined Power Meter</i>.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
class PowerMeter(modules: Seq[PowerModule], system: ActorSystem) extends Configuration with TimeoutConfiguration {
  import org.powerapi.core.Monitor
  import org.powerapi.core.MonitorChannel.MonitorStart
  import PowerMeterMessages._

  private val eventBus = new MessageBus
  private val powerMeterActor = system.actorOf(Props(classOf[PowerMeterActor], modules, eventBus))
  
  /**
   * Triggers a new power monitoring for a specific set of targets at a given frequency.
   *
   * @param frequency Sampling frequency for estimating the power consumption.
   * @param targets System targets to be monitored (and grouped by timestamp).
   * @return the acknowledgment of the triggered power monitoring.
   */
  def monitor(frequency: FiniteDuration)(targets: Target*): PowerMonitoring = {
    val monitor = new Monitor(eventBus, system)
    powerMeterActor ! MonitorStart("", monitor.muid, frequency, targets.toList)
    monitor
  }

  /**
   * Blocks and actively waits for a specific duration before returning.
   *
   * @param duration: duration to wait for.
   * @return the instance of the power meter.
   */
  def waitFor(duration: FiniteDuration): this.type = {
    import scala.concurrent.ExecutionContext.Implicits._

    Await.result(after(duration, using = system.scheduler) {
      Future successful "waitFor completed"
    }, duration + 1.seconds)

    this
  }

  /**
   * Shuts down the current instance of power meter.
   */
  def shutdown(): Unit = {
    powerMeterActor ! StopAll
    Await.result(gracefulStop(powerMeterActor, timeout.duration), timeout.duration)
  }
}

object PowerMeter {
  implicit lazy val system = ActorSystem(s"PowerMeter-${System.nanoTime()}")
  
  /**
   * Loads a specific power module as a tuple (sensor,formula).
   *
   * Example: `PowerMeter.load(PowerSpyModule, system)`
   *
   * @param modules: the list of power modules to be loaded within the PowerMeter.
   * @return the resulting instance of the requested power meter.
   */
  def load(modules: PowerModule*): PowerMeter = {
    new PowerMeter(modules, system)
  }
}

/**
 * A PowerModule groups a sets of tightly coupled elements that need to be deployed together.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
trait PowerModule {
  import org.powerapi.core.APIComponent

  // Underlying classes of a power module, used to create the actors.
  def underlyingSensorsClasses: Seq[(Class[_ <: APIComponent], Seq[Any])]
  def underlyingFormulaeClasses: Seq[(Class[_ <: APIComponent], Seq[Any])]

  protected var eventBus: Option[MessageBus] = None
  private var sensors: List[ActorRef]  = List()<commit_msg>refactor(api): change function name<commit_after>/*
 * This software is licensed under the GNU Affero General Public License, quoted below.
 *
 * This file is a part of PowerAPI.
 *
 * Copyright (C) 2011-2015 Inria, University of Lille 1.
 *
 * PowerAPI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * PowerAPI 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PowerAPI.
 *
 * If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
 */
package org.powerapi

import org.powerapi.configuration.TimeoutConfiguration

import scala.concurrent.{ Await, Future }
import scala.concurrent.duration.{ FiniteDuration, DurationInt }

import akka.actor.{ ActorRef, ActorRefFactory, ActorSystem, Props }
import akka.event.LoggingReceive
import akka.pattern.{ after, gracefulStop }

import org.powerapi.core.{Configuration, ActorComponent, MessageBus}
import org.powerapi.core.target.Target
import org.powerapi.core.power._

/**
 * PowerAPI object encapsulates all the messages.
 */
object PowerMeterMessages {
  case object StopAll
}

/**
 * Represents the main actor of a PowerMeter. Used to handle all the actors created for one PowerMeter.
 */
class PowerMeterActor(modules: Seq[PowerModule], eventBus: MessageBus) extends ActorComponent {
  import PowerMeterMessages._
  import org.powerapi.core.{ Clocks, Monitors }
  import org.powerapi.core.MonitorChannel.MonitorStart
  
  var clockSupervisor: Option[ActorRef] = None
  var monitorSupervisor: Option[ActorRef] = None
  
  // Starts the mandatory supervisors.
  override def preStart(): Unit = {
    clockSupervisor = Some(context.actorOf(Props(classOf[Clocks], eventBus), "clockSupervisor"))
    monitorSupervisor = Some(context.actorOf(Props(classOf[Monitors], eventBus), "monitorSupervisor"))
    
    modules.foreach(module => {
      module(eventBus)
      module.start(context)
    })
  }
  
  def receive = LoggingReceive {
    case msg: MonitorStart => {
      monitorSupervisor match {
        case Some(actorRef) => actorRef ! msg
        case _ => log.error("The monitor supervisor is not created")
      }
    }
    case StopAll => stopAll()
  } orElse default
  
  def stopAll(): Unit = {
    monitorSupervisor match {
      case Some(actorRef) => context.stop(actorRef)
      case _ => log.error("The monitor supervisor is not created")
    }

    clockSupervisor match {
      case Some(actorRef) => context.stop(actorRef)
      case _ => log.error("The clock supervisor is not created")
    }

    modules.foreach(module => {
      module.stop(context)
    })
  }
}

/**
 * Implements the main functionalities for configuring a <i>Software-Defined Power Meter</i>.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
class PowerMeter(modules: Seq[PowerModule], system: ActorSystem) extends Configuration with TimeoutConfiguration {
  import org.powerapi.core.Monitor
  import org.powerapi.core.MonitorChannel.MonitorStart
  import PowerMeterMessages._

  private val eventBus = new MessageBus
  private val powerMeterActor = system.actorOf(Props(classOf[PowerMeterActor], modules, eventBus))
  
  /**
   * Triggers a new power monitoring for a specific set of targets at a given frequency.
   *
   * @param frequency Sampling frequency for estimating the power consumption.
   * @param targets System targets to be monitored (and grouped by timestamp).
   * @return the acknowledgment of the triggered power monitoring.
   */
  def monitor(frequency: FiniteDuration)(targets: Target*): PowerMonitoring = {
    val monitor = new Monitor(eventBus, system)
    powerMeterActor ! MonitorStart("", monitor.muid, frequency, targets.toList)
    monitor
  }

  /**
   * Blocks and actively waits for a specific duration before returning.
   *
   * @param duration: duration to wait for.
   * @return the instance of the power meter.
   */
  def waitFor(duration: FiniteDuration): this.type = {
    import scala.concurrent.ExecutionContext.Implicits._

    Await.result(after(duration, using = system.scheduler) {
      Future successful "waitFor completed"
    }, duration + 1.seconds)

    this
  }

  /**
   * Shuts down the current instance of power meter.
   */
  def shutdown(): Unit = {
    powerMeterActor ! StopAll
    Await.result(gracefulStop(powerMeterActor, timeout.duration), timeout.duration)
  }
}

object PowerMeter {
  implicit lazy val system = ActorSystem(s"PowerMeter-${System.nanoTime()}")
  
  /**
   * Loads a specific power module as a tuple (sensor,formula).
   *
   * Example: `PowerMeter.load(PowerSpyModule, system)`
   *
   * @param modules: the list of power modules to be loaded within the PowerMeter.
   * @return the resulting instance of the requested power meter.
   */
  def loadModule(modules: PowerModule*): PowerMeter = {
    new PowerMeter(modules, system)
  }
}

/**
 * A PowerModule groups a sets of tightly coupled elements that need to be deployed together.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 */
trait PowerModule {
  import org.powerapi.core.APIComponent

  // Underlying classes of a power module, used to create the actors.
  def underlyingSensorsClasses: Seq[(Class[_ <: APIComponent], Seq[Any])]
  def underlyingFormulaeClasses: Seq[(Class[_ <: APIComponent], Seq[Any])]

  protected var eventBus: Option[MessageBus] = None
  private var sensors: List[ActorRef]  = List()
{'fraction_non_alphanumeric': 0.0981420953036298, 'fraction_numerical': 0.0022363667641493207, 'mean_word_length': 3.8445833333333335, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7579843', 'n_tokens_mistral': 3375, 'n_tokens_neox': 3302, 'n_words': 1084}