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

com.twitter.finagle.kestrel.protocol.DecodingToCommand.scala Maven / Gradle / Ivy

package com.twitter.finagle.kestrel.protocol

import com.twitter.finagle.memcached.protocol.{ClientError, NonexistentCommand}
import com.twitter.conversions.time._
import com.twitter.finagle.memcached.protocol.text.server.AbstractDecodingToCommand
import com.twitter.finagle.memcached.util.Bufs.RichBuf
import com.twitter.io.Buf

private[kestrel] class DecodingToCommand extends AbstractDecodingToCommand[Command] {
  private[this] val TimestampPrefix = Buf.Utf8("t=")

  private[this] val GET         = Buf.Utf8("get")
  private[this] val SET         = Buf.Utf8("set")
  private[this] val DELETE      = Buf.Utf8("delete")
  private[this] val FLUSH       = Buf.Utf8("flush")
  private[this] val FLUSH_ALL   = Buf.Utf8("flush_all")
  private[this] val VERSION     = Buf.Utf8("version")
  private[this] val SHUTDOWN    = Buf.Utf8("shutdown")
  private[this] val STATS       = Buf.Utf8("stats")
  private[this] val DUMP_STATS  = Buf.Utf8("dump_stats")

  private[this] val OPEN        = Buf.Utf8("open")
  private[this] val CLOSE       = Buf.Utf8("close")
  private[this] val ABORT       = Buf.Utf8("abort")
  private[this] val PEEK        = Buf.Utf8("peek")

  protected val storageCommands = collection.Set(SET)

  def parseStorageCommand(tokens: Seq[Buf], data: Buf, casUnique: Option[Buf] = None) = {
    val commandName = tokens.head
    val args = tokens.tail
    commandName match {
      case SET       =>
        val (name, _, expiry, _) = validateStorageCommand(args, data)
        Set(name, expiry, data)
      case _         => throw new NonexistentCommand(commandName.toString)
    }
  }

  def parseNonStorageCommand(tokens: Seq[Buf]) = {
    val commandName = tokens.head
    val args = tokens.tail
    commandName match {
      case GET        => validateGetCommand(args)
      case DELETE     => Delete(validateDeleteCommand(args))
      case FLUSH      => Flush(validateDeleteCommand(args))
      case FLUSH_ALL  => FlushAll()
      case VERSION    => Version()
      case SHUTDOWN   => ShutDown()
      case STATS      => Stats()
      case DUMP_STATS => DumpStats()
      case _          => throw new NonexistentCommand(commandName.toString)
    }
  }

  private[this] def validateGetCommand(tokens: Seq[Buf]): GetCommand = {
    if (tokens.size < 1) throw new ClientError("Key missing")
    if (tokens.size > 1) throw new ClientError("Too many arguments")

    val splitAll = tokens.head.split('/')

    val (splitTimeout, split) = splitAll partition { (value: Buf) => value.startsWith(TimestampPrefix) }

    val queueName = split.head

    val timeout = splitTimeout.lastOption.map {
      case Buf.Utf8(s) => s.drop(2).toInt.milliseconds
    }

    split.tail match {
      case Seq()           => Get(queueName, timeout)
      case Seq(OPEN)       => Open(queueName, timeout)
      case Seq(CLOSE)      => Close(queueName, timeout)
      case Seq(CLOSE,OPEN) => CloseAndOpen(queueName, timeout)
      case Seq(ABORT)      => Abort(queueName, timeout)
      case Seq(PEEK)       => Peek(queueName, timeout)
      case _               => throw new NonexistentCommand(tokens.map { case Buf.Utf8(s) => s }.mkString)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy