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

com.twitter.finagle.redis.naggati.codec.MemcacheCodec.scala Maven / Gradle / Ivy

There is a newer version: 21.2.0
Show newest version
/*
 * Copyright 2010 Twitter, Inc.
 *
 * 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 com.twitter.finagle.redis.naggati
package codec

import java.nio.ByteBuffer
import org.jboss.netty.buffer.{ChannelBuffer, ChannelBuffers}

case class MemcacheRequest(line: List[String], data: Option[ByteBuffer], bytesRead: Int) {
  override def toString = {
    " ""
      case Some(x) => " data=" + x.remaining
    }) + " read=" + bytesRead + ">"
  }
}

case class MemcacheResponse(
  line: String,
  data: Option[ByteBuffer] = None
) extends Codec.Signalling {
  override def toString = {
    " ""
      case Some(x) => " data=" + x.remaining
    }) + ">"
  }

  val lineData = line.getBytes("ISO-8859-1")

  def writeAscii(): Option[ChannelBuffer] = {
    if (lineData.size > 0) {
      val dataSize = if (data.isDefined) (data.get.remaining + MemcacheCodec.END.size) else 0
      val size = lineData.size + MemcacheCodec.CRLF.size + dataSize
      val buffer = ChannelBuffers.buffer(size)
      buffer.writeBytes(lineData)
      buffer.writeBytes(MemcacheCodec.CRLF)
      data.foreach { x =>
        buffer.writeBytes(x)
        buffer.writeBytes(MemcacheCodec.END)
      }
      Some(buffer)
    } else {
      None
    }
  }
}

object MemcacheCodec {
  import Stages._

  val STORAGE_COMMANDS = List("set", "add", "replace", "append", "prepend", "cas")
  val END = "\r\nEND\r\n".getBytes
  val CRLF = "\r\n".getBytes

  def asciiCodec(bytesReadCounter: Int => Unit, bytesWrittenCounter: Int => Unit) =
    new Codec(readAscii, writeAscii, bytesReadCounter, bytesWrittenCounter)

  def asciiCodec() = new Codec(readAscii, writeAscii)

  val readAscii = readLine(true, "ISO-8859-1") { line =>
    val segments = line.split(" ")
    segments(0) = segments(0).toLowerCase

    val command = segments(0)
    if (STORAGE_COMMANDS contains command) {
      if (segments.length < 5) {
        throw new ProtocolError("Malformed request line")
      }
      val dataBytes = segments(4).toInt
      ensureBytes(dataBytes + 2) { buffer =>
        // final 2 bytes are just "\r\n" mandated by protocol.
        val bytes = ByteBuffer.allocate(dataBytes)
        buffer.readBytes(bytes)
        bytes.flip()
        buffer.skipBytes(2)
        emit(MemcacheRequest(segments.toList, Some(bytes), line.length + dataBytes + 4))
      }
    } else {
      emit(MemcacheRequest(segments.toList, None, line.length + 2))
    }
  }

  val writeAscii = new Encoder[MemcacheResponse] {
    def encode(obj: MemcacheResponse) = obj.writeAscii()
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy