Permalink
Switch branches/tags
2.5.12_2.13.0-M3 2.5.13-release-2.13.0-M3 2.5.14_2.13.0-M3 2.5.15_2.13.0-M3 2.5.16_2.13.0-M3 2.5.17_2.13.0-M3 25047/simplify-test actorRefWithAckDocTest akka-typed-javadsl-behaviour-build-higherorder arteryTests asyncDnsRetryOverTcpWhenTruncated camel-java9 convertedReference doc-remove-tracking-2 findFreeUdpPort fixLagomLink integrate-docs-scala-java issue-23926-remote-watch javaAndScalaUnidoc jdk9-build jr/w/gce-benchmark-setup jr/26104-fix-SSLEngine-IllegalStateException-in-TlsActor ktoso-patch-1 leavingClusterEventLogs master mavenUpperCase multiJvmShardingLogTest must raboof-patch-1 release-1.1.3 release-1.1.4 release-1.2 release-1.3 release-1.3.1 release-2.0 release-2.1 release-2.2 release-2.3 release-2.4-http release-2.4 releaseFromTravis releaseWithJdk9ForJdk8 releasing-2.4.11.2 removeAkkaSslConfig removeCallerSensitive revert-21064-wip-http-javadsl-package-alignment-johanandren revert-24689-unidoc-cluster-richard sbtWhitesourceIssue20 scala-2.13.0-M4 scala-2.13.0-M5 scalafix stream-http-2.0 streamReference tcp-stream-termination-22163 testPrValidation typedPersistentStashingActor unidoc2 v2.5.6-preparations v2.5.7-preparations v2.5.8-preparations v2.5.19-scala-2.13.0-M5 wip-19623-subsource-cannot-push-twice-johanandren wip-19964-broken-link-WebSocket-example-RK wip-20984-typed-reliable-delivery-poc-patriknw wip-21624-SendQueue-debug-patriknw wip-23207-log-artery-dropped-patriknw wip-23593-RestartSpec-patriknw wip-23770-req-resp-patriknw wip-24113-cs-cs-chbatey wip-24155-jackson-patriknw wip-24980-debug-patriknw wip-25072-optimized-recovery-patriknw wip-25072-recovery-first-patriknw wip-25482-then-reply-patriknw wip-25484-enclosing-class-patriknw wip-25485-raffle-sample-patriknw wip-25717-persistence-stash-patriknw wip-25950-allObservers-patriknw wip-26012-rebalance-patriknw wip-ThisActorSystemQuarantinedEvent-patriknw wip-Typed-Session-RK wip-auto-confirmation-patriknw wip-conflate-example wip-connection-issue-patriknw wip-debug-LargeMessageClusterSpec-patriknw wip-debug-tests wip-experiments-√ wip-gcloud-faninout-2m wip-jdk-9-release-8-2m wip-jdk9-build-2m wip-lanes-debug-patriknw wip-managed-blocking-for-tpe-√ wip-misc-doc-fixes-RK wip-persistence-typed-impl-patriknw wip-persistenceId-patriknw wip-rm-ActorRef-Future-patriknw wip-rolling-artery-patriknw wip-rp-docs wip-scala-2.13-2m wip-streams-improvements-√ wip-tol-latest-api-mappings-plugin-2m wip-tol-latest-api-mappings-plugin wip-tol-no-tests-2m wip-typed-Java8-∂π wip-validate-pull-request-sbt-1.0-2m
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
89 lines (67 sloc) 2.42 KB
/*
* Copyright (C) 2015-2018 Lightbend Inc. <https://www.lightbend.com>
*/
package akka.stream.impl.io
import java.io.InputStream
import akka.Done
import akka.actor.{ ActorLogging, DeadLetterSuppression, Deploy, Props }
import akka.annotation.InternalApi
import akka.stream.actor.ActorPublisherMessage
import akka.stream.IOResult
import akka.util.ByteString
import scala.concurrent.Promise
import scala.util.{ Failure, Success }
/** INTERNAL API */
@InternalApi private[akka] object InputStreamPublisher {
def props(is: InputStream, completionPromise: Promise[IOResult], chunkSize: Int): Props = {
require(chunkSize > 0, s"chunkSize must be > 0 (was $chunkSize)")
Props(classOf[InputStreamPublisher], is, completionPromise, chunkSize).withDeploy(Deploy.local)
}
private final case object Continue extends DeadLetterSuppression
}
/** INTERNAL API */
@InternalApi private[akka] class InputStreamPublisher(is: InputStream, completionPromise: Promise[IOResult], chunkSize: Int)
extends akka.stream.actor.ActorPublisher[ByteString]
with ActorLogging {
// TODO possibly de-duplicate with FilePublisher?
import InputStreamPublisher._
val arr = new Array[Byte](chunkSize)
var readBytesTotal = 0L
def receive = {
case ActorPublisherMessage.Request(elements) readAndSignal()
case Continue readAndSignal()
case ActorPublisherMessage.Cancel context.stop(self)
}
def readAndSignal(): Unit =
if (isActive) {
readAndEmit()
if (totalDemand > 0 && isActive) self ! Continue
}
def readAndEmit(): Unit = if (totalDemand > 0) try {
// blocking read
val readBytes = is.read(arr)
readBytes match {
case -1
// had nothing to read into this chunk
log.debug("No more bytes available to read (got `-1` from `read`)")
onCompleteThenStop()
case _
readBytesTotal += readBytes
// emit immediately, as this is the only chance to do it before we might block again
onNext(ByteString.fromArray(arr, 0, readBytes))
}
} catch {
case ex: Exception
onErrorThenStop(ex)
}
override def postStop(): Unit = {
super.postStop()
try {
if (is ne null) is.close()
} catch {
case ex: Exception
completionPromise.success(IOResult(readBytesTotal, Failure(ex)))
}
completionPromise.trySuccess(IOResult(readBytesTotal, Success(Done)))
}
}