Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ libraryDependencies ++= Seq(
"ch.qos.logback" % "logback-core" % logbackVersion,
"com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test,
"org.scalatest" %% "scalatest" % "3.0.5" % Test,
"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test
"com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test,
"com.github.pathikrit" %% "better-files" % "3.6.0"
)

resolvers ++= Seq("Sonatype Releases" at "https://oss.sonatype.org/content/repositories/releases/",
Expand Down
Empty file added project/plugins.sbt
Empty file.
1 change: 1 addition & 0 deletions src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
httpHost = "0.0.0.0"
httpPort = 9151
timeout = 10000
enableStateDownload = false
}
influx {
host = "http://127.0.0.1:8086"
Expand Down
60 changes: 60 additions & 0 deletions src/main/scala/mvp2/actors/Downloader.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package mvp2.actors

import java.nio.file.Paths
import akka.pattern.pipe
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes}
import akka.stream.scaladsl.FileIO
import better.files.File
import better.files._
import scala.util.{Failure, Success}
import mvp2.MVP2._
import scala.concurrent.ExecutionContext.Implicits.global

class Downloader(downloadFrom: String) extends CommonActor {
override def specialBehavior: Receive = ???

override def preStart(): Unit = {
logger.info("Starting downloader")
self ! downloadFrom
}

override def receive: Receive = {
case address: String =>
pipe(Http(context.system).singleRequest(HttpRequest(uri = s"http://$address/download"))).to(self)
case HttpResponse(StatusCodes.OK, _, entity, _) =>
entity.dataBytes.runWith(FileIO.toPath(Paths.get(s"./state.zip"))).onComplete {
case Success(_) =>
unzip()
println(1)
context.parent ! DownloadComplete
case Failure(th) =>
th.printStackTrace()
context.parent ! DownloadComplete
context.stop(self)
}
case resp @ HttpResponse(code, _, _, _) =>
println(code)
resp.discardEntityBytes()
context.parent ! DownloadComplete
context.stop(self)
}

def unzip(): Unit = {
def moveAllFiles(from: File, dest: File): Unit = from.list.foreach(_.copyToDirectory(dest))
val zip: File = file"./encry.zip"
val unzipped: File = zip.unzipTo(file"./state")
zip.delete(true)
file"./leveldb/journal".delete(true)
file"./leveldb/snapshots".delete(true)
val unzippedJournal: File = file"./state/journal"
val unzippedSnapshots: File = file"./state/snapshots"
val journalDir: File = file"./leveldb/journal".createDirectories()
val snapshotsDir: File = file"./leveldb/snapshots".createDirectories()
moveAllFiles(unzippedJournal, journalDir)
moveAllFiles(unzippedSnapshots, snapshotsDir)
unzipped.delete(true)
}
}

case object DownloadComplete
6 changes: 5 additions & 1 deletion src/main/scala/mvp2/actors/Starter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ class Starter extends CommonActor {

override def preStart(): Unit = {
logger.info("Starting the Starter!")
bornKids()
settings.downloadStateFrom match {
case None => bornKids()
case Some(address) => context.actorOf(Props(classOf[Downloader], address), "downloader")
}
}

override def specialBehavior: Receive = {
case message: String => logger.info(message)
case DownloadComplete if settings.downloadStateFrom.nonEmpty => bornKids()
}

def bornKids(): Unit = {
Expand Down
34 changes: 30 additions & 4 deletions src/main/scala/mvp2/http/Routes.scala
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
package mvp2.http

import java.nio.file.Path
import akka.http.scaladsl.server.Directives.complete
import akka.actor.ActorSelection
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.model._
import mvp2.data.{LightKeyBlock, Transaction}
import mvp2.utils.Settings
import akka.actor.ActorRefFactory
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.StatusCodes.InternalServerError
import akka.http.scaladsl.server.Route
import io.circe.Json
import scala.concurrent.Future
import io.circe.generic.auto._
import io.circe.syntax._
import scala.concurrent.ExecutionContextExecutor
import scala.concurrent.duration._
import scala.concurrent.Future
import scala.language.postfixOps
import akka.http.scaladsl.server.Directives._
import akka.pattern.ask
import akka.util.{ByteString, Timeout}
import better.files.File
import better.files._
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import mvp2.data.InnerMessages.{CurrentBlockchainInfo, Get, GetLightChain}
import scala.util.{Failure, Success, Try}
import mvp2.utils.EncodingUtils._

case class Routes(settings: Settings, implicit val context: ActorRefFactory) extends FailFastCirceSupport {
Expand All @@ -29,7 +33,11 @@ case class Routes(settings: Settings, implicit val context: ActorRefFactory) ext
implicit val timeout: Timeout = Timeout(settings.apiSettings.timeout.millisecond)
implicit val ec: ExecutionContextExecutor = context.dispatcher

val route: Route = getTxs ~ apiInfo ~ chainInfo
val routes: Seq[Route] =
if (settings.apiSettings.enableStateDownload) Seq(getTxs, apiInfo, chainInfo, downloadState)
else Seq(getTxs, apiInfo, chainInfo)

val route: Route = routes.reduce(_ ~ _)
val publisher: ActorSelection = context.actorSelection("/user/starter/blockchainer/publisher")
val informator: ActorSelection = context.actorSelection("/user/starter/informator")

Expand Down Expand Up @@ -57,4 +65,22 @@ case class Routes(settings: Settings, implicit val context: ActorRefFactory) ext
def chainInfo: Route = path("chainInfo")(
toJsonResponse((informator ? GetLightChain).mapTo[List[LightKeyBlock]].map(_.asJson))
)

def downloadState: Route = (path("download") & get)(
createZip match {
case Success(path) => getFromFile(path.toFile, MediaTypes.`application/zip`)
case Failure(_) => complete(HttpResponse(InternalServerError))
}
)

private def createZip: Try[Path] = Try {
file"./state.zip".delete(true)
file"./tmp/".delete(true)
val dir: File = file"./tmp/".createDirectory()
File("./leveldb").list.map(_.copyToDirectory(dir))
val zip: File = file"./state.zip".deleteOnExit()
dir.zipTo(file"./state.zip").deleteOnExit()
zip.path
}

}
3 changes: 2 additions & 1 deletion src/main/scala/mvp2/utils/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ case class Settings(port: Int,
blockPeriod: Long,
biasForBlockPeriod: Long,
newBlockchain: Boolean,
downloadStateFrom: Option[String] = None,
apiSettings: ApiSettings,
ntp: NetworkTimeProviderSettings,
influx: InfluxSettings,
Expand All @@ -16,7 +17,7 @@ case class Settings(port: Int,

case class Node(host: String, port: Int)

case class ApiSettings(httpHost: String, httpPort: Int, timeout: Int)
case class ApiSettings(httpHost: String, httpPort: Int, timeout: Int, enableStateDownload: Boolean)

case class InfluxSettings(host: String, port: Int, login: String, password: String)

Expand Down