deduplicate logic for IODispatcher #24604 (#24619)

* deduplicate logic for IODispatcher #24604
 * introduce a resolveDispatcher helper in ActorAttributes
 * mention akka.stream.materializer.blocking-io-dispatcher instead of akka.stream.blocking-io-dispatcher in scaladocs
 * fix a flaky test
 * cosmetic changes in the touched files

* move resolveDispather helper to the Dispatcher companion object under a new name resolve

* filter out mima warning

* fix mima excludes after the 2.5.11 release

* address review comments
 * update stream-io.md with the correct dispatcher config key
 * mark ActorAttributes.Dispatcher#resolve as internal API
 * use the dispatche config key in ActorMaterializer

* add private[akka] to the resolve methods
This commit is contained in:
Roman Filonenko 2018-03-07 15:12:34 +01:00 committed by Patrik Nordwall
parent a13f5cab00
commit 0ecadf7235
17 changed files with 127 additions and 111 deletions

View file

@ -4,7 +4,6 @@
package akka.stream.impl
import java.util
import java.util.ArrayList
import java.util.concurrent.atomic.AtomicBoolean
import akka.NotUsed
@ -12,10 +11,8 @@ import akka.actor.{ ActorContext, ActorRef, ActorRefFactory, ActorSystem, Cancel
import akka.annotation.{ DoNotInherit, InternalApi }
import akka.dispatch.Dispatchers
import akka.event.{ Logging, LoggingAdapter }
import akka.stream.ActorAttributes.Dispatcher
import akka.stream.Attributes.InputBuffer
import akka.stream._
import akka.stream.impl.Stages.DefaultAttributes.IODispatcher
import akka.stream.impl.StreamLayout.AtomicModule
import akka.stream.impl.fusing.ActorGraphInterpreter.{ ActorOutputBoundary, BatchingActorInputBoundary }
import akka.stream.impl.fusing.GraphInterpreter.Connection
@ -150,12 +147,12 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
private var currentIslandGlobalOffset = 0
// The number of slots that belong to segments of other islands encountered so far, from the
// beginning of the island
private var currentIslandSkippetSlots = 0
private var currentIslandSkippedSlots = 0
private var segments: java.util.ArrayList[SegmentInfo] = null
private var activePhases: java.util.ArrayList[PhaseIsland[Any]] = null
private var forwardWires: java.util.ArrayList[ForwardWire] = null
private var islandStateStack: java.util.ArrayList[SavedIslandData] = null
private var segments: java.util.ArrayList[SegmentInfo] = _
private var activePhases: java.util.ArrayList[PhaseIsland[Any]] = _
private var forwardWires: java.util.ArrayList[ForwardWire] = _
private var islandStateStack: java.util.ArrayList[SavedIslandData] = _
private var currentPhase: PhaseIsland[Any] = defaultPhase.apply(settings, attributes, materializer, nextIslandName())
@ -176,7 +173,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
globalislandOffset = currentIslandGlobalOffset,
length = currentGlobalOffset - currentSegmentGlobalOffset,
globalBaseOffset = currentSegmentGlobalOffset,
relativeBaseOffset = currentSegmentGlobalOffset - currentIslandGlobalOffset - currentIslandSkippetSlots,
relativeBaseOffset = currentSegmentGlobalOffset - currentIslandGlobalOffset - currentIslandSkippedSlots,
currentPhase)
// Segment tracking is by demand, we only allocate this list if it is used.
@ -193,7 +190,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
completeSegment()
val previousPhase = currentPhase
val previousIslandOffset = currentIslandGlobalOffset
islandStateStack.add(SavedIslandData(previousIslandOffset, currentGlobalOffset, currentIslandSkippetSlots, previousPhase))
islandStateStack.add(SavedIslandData(previousIslandOffset, currentGlobalOffset, currentIslandSkippedSlots, previousPhase))
currentPhase = phases(tag)(settings, attributes, materializer, nextIslandName())
activePhases.add(currentPhase)
@ -203,7 +200,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
// The base offset of this segment is the current global offset
currentSegmentGlobalOffset = currentGlobalOffset
currentIslandSkippetSlots = 0
currentIslandSkippedSlots = 0
if (Debug) println(s"Entering island starting at offset = $currentIslandGlobalOffset phase = $currentPhase")
}
@ -217,7 +214,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
// We restore data for the island
currentIslandGlobalOffset = parentIsland.islandGlobalOffset
currentPhase = parentIsland.phase
currentIslandSkippetSlots = parentIsland.skippedSlots + (currentGlobalOffset - parentIsland.lastVisitedOffset)
currentIslandSkippedSlots = parentIsland.skippedSlots + (currentGlobalOffset - parentIsland.lastVisitedOffset)
if (Debug) println(s"Exited to island starting at offset = $currentIslandGlobalOffset phase = $currentPhase")
}
@ -225,7 +222,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
@InternalApi private[akka] def wireIn(in: InPort, logic: Any): Unit = {
// The slot for this InPort always belong to the current segment, so resolving its local
// offset/slot is simple
val localInSlot = currentGlobalOffset - currentIslandGlobalOffset - currentIslandSkippetSlots
val localInSlot = currentGlobalOffset - currentIslandGlobalOffset - currentIslandSkippedSlots
if (Debug) println(s" wiring port $in inOffs absolute = $currentGlobalOffset local = $localInSlot")
// Assign the logic belonging to the current port to its calculated local slot in the island
@ -278,8 +275,8 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
if (absoluteOffset >= currentSegmentGlobalOffset) {
// Wiring is in the same segment, no complex lookup needed
val localInSlot = absoluteOffset - currentIslandGlobalOffset - currentIslandSkippetSlots
if (Debug) println(s" in-segment wiring to local ($absoluteOffset - $currentIslandGlobalOffset - $currentIslandSkippetSlots) = $localInSlot")
val localInSlot = absoluteOffset - currentIslandGlobalOffset - currentIslandSkippedSlots
if (Debug) println(s" in-segment wiring to local ($absoluteOffset - $currentIslandGlobalOffset - $currentIslandSkippedSlots) = $localInSlot")
currentPhase.assignPort(out, localInSlot, logic)
} else {
// Wiring is cross-segment, but we don't know if it is cross-island or not yet
@ -383,7 +380,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
* When these attributes are needed later in the materialization process it is important that the
* they are gotten through the attributes and not through the [[ActorMaterializerSettings]]
*/
val defaultAttributes = {
val defaultAttributes: Attributes = {
Attributes(
Attributes.InputBuffer(settings.initialInputBufferSize, settings.maxInputBufferSize) ::
ActorAttributes.SupervisionStrategy(settings.supervisionDecider) ::
@ -609,7 +606,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
subflowFuser: OptionVal[GraphInterpreterShell ActorRef]) extends PhaseIsland[GraphStageLogic] {
// TODO: remove these
private val logicArrayType = Array.empty[GraphStageLogic]
private[this] val logics = new ArrayList[GraphStageLogic](16)
private[this] val logics = new util.ArrayList[GraphStageLogic](16)
private var connections = new Array[Connection](16)
private var maxConnections = 0
@ -734,18 +731,13 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
shell.logics = logics.toArray(logicArrayType)
subflowFuser match {
case OptionVal.Some(fuseIntoExistingInterperter)
fuseIntoExistingInterperter(shell)
case OptionVal.Some(fuseIntoExistingInterpreter)
fuseIntoExistingInterpreter(shell)
case _
val dispatcher =
effectiveAttributes.mandatoryAttribute[ActorAttributes.Dispatcher] match {
case ActorAttributes.IODispatcher settings.blockingIoDispatcher
case ActorAttributes.Dispatcher(dispatcher) dispatcher
}
val props = ActorGraphInterpreter.props(shell)
.withDispatcher(dispatcher)
val props = ActorGraphInterpreter.props(shell).withDispatcher(ActorAttributes.Dispatcher.resolve(effectiveAttributes, settings))
val actorName = fullIslandName match {
case OptionVal.Some(n) n
case OptionVal.None islandName
@ -887,10 +879,7 @@ private final case class SavedIslandData(islandGlobalOffset: Int, lastVisitedOff
def materializeAtomic(mod: AtomicModule[Shape, Any], attributes: Attributes): (NotUsed, Any) = {
val tls = mod.asInstanceOf[TlsModule]
val dispatcher = attributes.mandatoryAttribute[Dispatcher] match {
case IODispatcher materializer.settings.blockingIoDispatcher
case Dispatcher(name) name
}
val dispatcher = ActorAttributes.Dispatcher.resolve(attributes, materializer.settings)
val maxInputBuffer = attributes.mandatoryAttribute[Attributes.InputBuffer].max
val props =