All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scassandra.server.actors.ExecuteHandler.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2016 Christopher Batey and Dogan Narinc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.scassandra.server.actors

import akka.actor.ActorRef
import akka.pattern.{ask, pipe}
import akka.util.Timeout
import org.scassandra.codec._
import org.scassandra.server.actors.ExecuteHandler.HandleExecute
import org.scassandra.server.actors.PrepareHandler.{PreparedStatementQuery, PreparedStatementResponse}
import org.scassandra.server.priming._
import org.scassandra.server.priming.prepared.PreparedStoreLookup
import org.scassandra.server.priming.query.Reply

import scala.concurrent.duration._
import scala.language.postfixOps

class ExecuteHandler(primePreparedStore: PreparedStoreLookup, activityLog: ActivityLog, prepareHandler: ActorRef) extends ProtocolActor {

  import context.dispatcher
  implicit val timeout: Timeout = 1 second

  def receive: Receive = {
    case ProtocolMessage(Frame(header, e: Execute)) =>
      val id = e.id.toInt()
      val recipient = sender
      // Lookup the associated prepared statement for this execute and on completion
      // send a message to self indicating to handle the request.
      val executeRequest = (prepareHandler ? PreparedStatementQuery(List(id)))
        .mapTo[PreparedStatementResponse]
        .map(res => HandleExecute(res.prepared.get(id), header, e, recipient))
      executeRequest.pipeTo(self)
    case HandleExecute(query, header, execute, connection) =>
      handleExecute(query, header, execute, connection)
  }

  def handleExecute(preparedStatement: Option[(String, Prepared)], header: FrameHeader, execute: Execute, connection: ActorRef) = {
    implicit val protocolVersion = header.version.version
    preparedStatement match {
      case Some((queryText, prepared)) =>
        val prime = primePreparedStore(queryText, execute)
        prime.foreach(p => log.info("Found prime {}", p))

        // Decode query parameters using the prepared statement metadata.
        val dataTypes = prepared.preparedMetadata.columnSpec.map(_.dataType)

        val values = extractQueryVariables(queryText, execute.parameters.values.map(_.map(_.value)), dataTypes)
        values match {
          case Some(v) =>
            activityLog.recordPreparedStatementExecution(queryText, execute.parameters.consistency,
              execute.parameters.serialConsistency, v, dataTypes, execute.parameters.timestamp)
          case None =>
            activityLog.recordPreparedStatementExecution(queryText, execute.parameters.consistency,
              execute.parameters.serialConsistency, Nil, Nil, execute.parameters.timestamp)
        }


        writePrime(execute, prime, header, Some(connection), alternative=Some(Reply(VoidResult)), consistency = Some(execute.parameters.consistency))
      case None =>
        val errMsg = s"Could not find prepared statement with id: 0x${execute.id.toHex}"
        activityLog.recordPreparedStatementExecution(errMsg, execute.parameters.consistency,
          execute.parameters.serialConsistency, Nil, Nil, execute.parameters.timestamp)
        val unprepared = Unprepared(errMsg, execute.id)
        write(unprepared, header, Some(connection))
    }
  }
}

object ExecuteHandler {
  case class HandleExecute(query: Option[(String, Prepared)], header: FrameHeader, execute: Execute, connection: ActorRef)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy