Skip to content

Commit

Permalink
Merge pull request powerapi-ng#31 from Spirals-Team/feature/procfs-mo…
Browse files Browse the repository at this point in the history
…dule

Feature/procfs module
  • Loading branch information
rouvoy committed Nov 29, 2014
2 parents cf573ce + f8f93ed commit 8fb0b97
Show file tree
Hide file tree
Showing 48 changed files with 1,980 additions and 117 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ When submitting code, please make every effort to follow existing conventions an
We all stand on the shoulders of giants and get by with a little help from our friends. PowerAPI is written in [Scala](http://www.scala-lang.org) (version 2.11.4 under [3-clause BSD license](http://www.scala-lang.org/license.html)) and built on top of:
* [Akka](http://akka.io) (version 2.3.6 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for asynchronous processing
* [Typesage Config](https://github.com/typesafehub/config) (version 1.2.1 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for reading configuration files.
* [Apache log4j2](http://logging.apache.org/log4j/2.x/) (version 2.1 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for logging outside actors.

# Licence
This software is licensed under the *GNU Affero General Public License*, quoted below.
Expand Down
2 changes: 2 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ scalaVersion := "2.11.4"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % "2.3.6",
"com.typesafe" % "config" % "1.2.1",
"org.apache.logging.log4j" % "log4j-api" % "2.1",
"org.apache.logging.log4j" % "log4j-core" % "2.1",
"com.typesafe.akka" %% "akka-testkit" % "2.3.6" % "test",
"org.scalatest" %% "scalatest" % "2.2.2" % "test"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* This software is licensed under the GNU Affero General Public License, quoted below.
*
* This file is a part of PowerAPI.
*
* Copyright (C) 2011-2014 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.configuration

import org.powerapi.core.Configuration

/**
* Number of logical cores / Configuration.
*
* @author Maxime Colmant <[email protected]>
*/
trait LogicalCoresConfiguration {
self: Configuration =>

import org.powerapi.core.ConfigValue

lazy val cores = load { _.getInt("powerapi.hardware.cores") } match {
case ConfigValue(nbCores) => nbCores
case _ => 0
}
}
17 changes: 10 additions & 7 deletions src/main/scala/org/powerapi/core/ClockActors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ package org.powerapi.core
import akka.actor.SupervisorStrategy.{Directive, Resume}
import akka.actor.{Actor, Cancellable, PoisonPill, Props}
import akka.event.LoggingReceive

import scala.concurrent.duration.{Duration, FiniteDuration}

/**
* One child clock is created per frequency.
* Allows to publish a message in the right topics for a given frequency.
*
* @author Maxime Colmant <[email protected]>
*/
class ClockChild(eventBus: MessageBus, frequency: FiniteDuration) extends Component {
import org.powerapi.core.ClockChannel.{ClockStart, ClockStop, ClockStopAll, publishTick}
class ClockChild(eventBus: MessageBus, frequency: FiniteDuration) extends ActorComponent {
import org.powerapi.core.ClockChannel.{ClockStart, ClockStop, ClockStopAll, publishClockTick}

def receive: PartialFunction[Any, Unit] = LoggingReceive {
case ClockStart(_, freq) if frequency == freq => start()
Expand All @@ -60,7 +61,7 @@ class ClockChild(eventBus: MessageBus, frequency: FiniteDuration) extends Compon
*/
def start(): Unit = {
val timer = context.system.scheduler.schedule(Duration.Zero, frequency) {
publishTick(frequency)(eventBus)
publishClockTick(frequency)(eventBus)
} (context.system.dispatcher)

log.info("clock started, reference: {}", frequency.toNanos)
Expand Down Expand Up @@ -89,12 +90,14 @@ class ClockChild(eventBus: MessageBus, frequency: FiniteDuration) extends Compon
/**
* This clock listens the bus on a given topic and reacts on the received message.
* It is responsible to handle a pool of clocks for the monitored frequencies.
*
* @author Maxime Colmant <[email protected]>
*/
class Clocks(eventBus: MessageBus) extends Component with Supervisor {
import org.powerapi.core.ClockChannel.{ClockStart, ClockStop, ClockStopAll, formatClockChildName, stopAllClock, subscribeTickSubscription}
class Clocks(eventBus: MessageBus) extends Supervisor {
import org.powerapi.core.ClockChannel.{ClockStart, ClockStop, ClockStopAll, formatClockChildName, stopAllClock, subscribeClockChannel}

override def preStart(): Unit = {
subscribeTickSubscription(eventBus)(self)
subscribeClockChannel(eventBus)(self)
}

override def postStop(): Unit = {
Expand Down
24 changes: 7 additions & 17 deletions src/main/scala/org/powerapi/core/ClockChannel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,15 @@
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/

package org.powerapi.core

import akka.actor.ActorRef

import scala.concurrent.duration.FiniteDuration


/**
* Clock channel and messages.
*
* @author Maxime Colmant <[email protected]>
*/
object ClockChannel extends Channel {

Expand All @@ -47,15 +46,6 @@ object ClockChannel extends Channel {
frequency: FiniteDuration,
timestamp: Long = System.currentTimeMillis) extends ClockMessage

/**
* ClockTickSubscription is represented as a dedicated type of message.
*
* @param topic: subject used for routing the message.
* @param frequency: clock frequency.
*/
case class ClockTickSubscription(topic: String,
frequency: FiniteDuration) extends ClockMessage

/**
* ClockStart is represented as a dedicated type of message.
*
Expand All @@ -82,17 +72,17 @@ object ClockChannel extends Channel {
/**
* Topic for communicating with the Clock.
*/
private val topic = "tick:subscription"
private val topic = "clock:handling"

/**
* External methods used by the Monitor actors to subscribe/unsubscribe,
* start/stop a clock which runs at a frequency.
*/
def subscribeClock(frequency: FiniteDuration): (MessageBus => ActorRef => Unit) = {
def subscribeClockTick(frequency: FiniteDuration): MessageBus => ActorRef => Unit = {
subscribe(clockTickTopic(frequency))
}

def unsubscribeClock(frequency: FiniteDuration): MessageBus => ActorRef => Unit = {
def unsubscribeClockTick(frequency: FiniteDuration): MessageBus => ActorRef => Unit = {
unsubscribe(clockTickTopic(frequency))
}

Expand All @@ -107,7 +97,7 @@ object ClockChannel extends Channel {
/**
* Internal methods used by the Clocks actor for interacting with the bus.
*/
def subscribeTickSubscription: MessageBus => ActorRef => Unit = {
def subscribeClockChannel: MessageBus => ActorRef => Unit = {
subscribe(topic)
}

Expand All @@ -116,7 +106,7 @@ object ClockChannel extends Channel {
/**
* Internal methods used by the ClockChild actors for interacting with the bus.
*/
def publishTick(frequency: FiniteDuration): MessageBus => Unit = {
def publishClockTick(frequency: FiniteDuration): MessageBus => Unit = {
publish(ClockTick(clockTickTopic(frequency), frequency))
}

Expand Down
22 changes: 17 additions & 5 deletions src/main/scala/org/powerapi/core/Component.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/

package org.powerapi.core

import akka.actor.{OneForOneStrategy, SupervisorStrategy, SupervisorStrategyConfigurator, ActorLogging, Actor}
import akka.actor.SupervisorStrategy.{Directive, Resume}
import akka.actor.{Actor, ActorLogging, OneForOneStrategy, SupervisorStrategy, SupervisorStrategyConfigurator}

import akka.event.LoggingReceive
import scala.concurrent.duration.DurationInt

/**
* Base trait for components which use Actor.
*
* @author Maxime Colmant <[email protected]>
*/
trait Component extends Actor with ActorLogging {
trait ActorComponent extends Actor with ActorLogging {
/**
* Default behavior when a received message is unknown.
*/
Expand All @@ -40,10 +41,19 @@ trait Component extends Actor with ActorLogging {
}
}

/**
* Base trait for API component.
*
* @author Maxime Colmant <[email protected]>
*/
trait APIComponent extends ActorComponent

/**
* Supervisor strategy.
*
* @author Maxime Colmant <[email protected]>
*/
trait Supervisor extends Component {
trait Supervisor extends ActorComponent {
def handleFailure: PartialFunction[Throwable, Directive]

override def supervisorStrategy: SupervisorStrategy =
Expand All @@ -53,6 +63,8 @@ trait Supervisor extends Component {
/**
* This class is used for defining a default supervisor strategy for the Guardian Actor.
* The Guardian Actor is the main actor used when system.actorOf(...) is used.
*
* @author Maxime Colmant <[email protected]>
*/
class GuardianFailureStrategy extends SupervisorStrategyConfigurator {
def handleFailure: PartialFunction[Throwable, Directive] = {
Expand Down
7 changes: 5 additions & 2 deletions src/main/scala/org/powerapi/core/Configuration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,23 @@ package org.powerapi.core

import com.typesafe.config.{Config, ConfigException, ConfigFactory}


/**
* Base trait for configuration result.
*/
trait ConfigResult[T]

/**
* Subtypes to specify the different types of result.
*
* @author Maxime Colmant <[email protected]>
*/
case class ConfigValue[T](value: T) extends ConfigResult[T]
case class ConfigError[T](exception: Throwable) extends ConfigResult[T]

/**
* Base trait for dealing with configuration files.
*
* @author Maxime Colmant <[email protected]>
*/
trait Configuration {
private lazy val conf = ConfigFactory.load()
Expand All @@ -47,7 +50,7 @@ trait Configuration {
*
* @param request: request for getting information.
*/
def load[T](request: Config => T): ConfigResult[T] = {
protected def load[T](request: Config => T): ConfigResult[T] = {
try {
ConfigValue(request(conf))
}
Expand Down
41 changes: 41 additions & 0 deletions src/main/scala/org/powerapi/core/FileHelper.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* This software is licensed under the GNU Affero General Public License, quoted below.
*
* This file is a part of PowerAPI.
*
* Copyright (C) 2011-2014 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.core

/**
* Implement the Loan's pattern for closing automatically a resource.
*
* @see https://wiki.scala-lang.org/display/SYGN/Loan
*
* @author Maxime Colmant <[email protected]>
*/
object FileHelper {
def using[A <: { def close(): Unit }, B](resource: A)(f: A => B): B = {
try {
f(resource)
}
finally {
resource.close()
}
}
}
30 changes: 15 additions & 15 deletions src/main/scala/org/powerapi/core/MessageBus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,16 @@
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/

package org.powerapi.core

import java.util.UUID

import akka.actor.ActorRef
import akka.event.LookupClassification


/**
* Messages are the messages used to route the messages in the bus.
*
* @author Romain Rouvoy <[email protected]>
* @author Maxime Colmant <[email protected]>
*/
trait Message {
/**
Expand All @@ -40,15 +39,10 @@ trait Message {
}

/**
* Reports are the base messages exchanged between PowerAPI components.
* Main types definition.
*
* @author Maxime Colmant <[email protected]>
*/
trait Report extends Message {
/**
* A report is associated with a monitor unique identifier (MUID), which is at the origin of the report flow.
*/
def muid: UUID
}

trait EventBus extends akka.event.EventBus {
type Event = Message
type Classifier = String
Expand All @@ -57,6 +51,9 @@ trait EventBus extends akka.event.EventBus {

/**
* Common event bus used by PowerAPI components to communicate.
*
* @author Loic Huertas <[email protected]>
* @author Maxime Colmant <[email protected]>
*/
class MessageBus extends EventBus with LookupClassification {
// is used for extracting the classifier from the incoming events
Expand All @@ -80,19 +77,22 @@ class MessageBus extends EventBus with LookupClassification {

/**
* Used to specify the channels used by the components.
*
* @author Romain Rouvoy <[email protected]>
* @author Maxime Colmant <[email protected]>
*/
class Channel {
type M <: Message

def subscribe(topic: String)(bus: EventBus)(subscriber: ActorRef): Unit = {
protected def subscribe(topic: String)(bus: EventBus)(subscriber: ActorRef): Unit = {
bus.subscribe(subscriber, topic)
}

def unsubscribe(topic: String)(bus: EventBus)(subscriber: ActorRef): Unit = {
protected def unsubscribe(topic: String)(bus: EventBus)(subscriber: ActorRef): Unit = {
bus.unsubscribe(subscriber, topic)
}

def publish(message: M)(bus: EventBus): Unit = {
protected def publish(message: M)(bus: EventBus): Unit = {
bus.publish(message)
}
}
Loading

0 comments on commit 8fb0b97

Please sign in to comment.