in finagle-memcached/src/main/scala/com/twitter/finagle/memcached/Interpreter.scala [19:150]
def apply(command: Command): Response = {
command match {
case Set(key, flags, expiry, value) =>
map.lock(key) { data =>
data(key) = Entry(value, expiry, flags)
Stored
}
case Add(key, flags, expiry, value) =>
map.lock(key) { data =>
val existing = data.get(key)
existing match {
case Some(entry) if entry.valid =>
NotStored
case _ =>
data(key) = Entry(value, expiry, flags)
Stored
}
}
case Replace(key, flags, expiry, value) =>
map.lock(key) { data =>
val existing = data.get(key)
existing match {
case Some(entry) if entry.valid =>
data(key) = Entry(value, expiry, flags)
Stored
case Some(_) =>
data.remove(key) // expired
NotStored
case _ =>
NotStored
}
}
case Append(key, flags, expiry, value: Buf) =>
map.lock(key) { data =>
val existing = data.get(key)
existing match {
case Some(entry) if entry.valid =>
data(key) = Entry(entry.value.concat(value), expiry, flags)
Stored
case Some(_) =>
data.remove(key) // expired
NotStored
case _ =>
NotStored
}
}
case Cas(key, flags, expiry, value, casUnique) =>
map.lock(key) { data =>
val existing = data.get(key)
existing match {
case Some(entry) if entry.valid =>
val currentValue = entry.value
if (casUnique.equals(generateCasUnique(currentValue))) {
data(key) = Entry(value, expiry, flags)
Stored
} else {
Exists
}
case _ =>
NotStored
}
}
case Prepend(key, flags, expiry, value) =>
map.lock(key) { data =>
val existing = data.get(key)
existing match {
case Some(entry) if entry.valid =>
data(key) = Entry(value.concat(entry.value), expiry, flags)
Stored
case Some(_) =>
data.remove(key) // expired
NotStored
case _ =>
NotStored
}
}
case Get(keys) =>
Values(
keys.flatMap { key =>
map.lock(key) { data =>
data
.get(key).filter { entry =>
if (!entry.valid)
data.remove(key) // expired
entry.valid
}.map { entry =>
Value(key, entry.value, flags = Some(Buf.Utf8(entry.flags.toString)))
}
}
}
)
case Gets(keys) =>
getByKeys(keys)
case Delete(key) =>
map.lock(key) { data =>
if (data.remove(key).isDefined)
Deleted
else
NotFound
}
case Incr(key, delta) =>
map.lock(key) { data =>
val existing = data.get(key)
existing match {
case Some(entry) if entry.valid =>
val Buf.Utf8(existingString) = entry.value
if (!existingString.isEmpty && !ParserUtils.isDigits(entry.value)) {
Error(new ClientError("cannot increment or decrement non-numeric value"))
} else {
val existingValue: Long =
if (existingString.isEmpty) 0L
else existingString.toLong
val result: Long = existingValue + delta
data(key) = Entry(Buf.Utf8(result.toString), entry.expiry, 0)
Number(result)
}
case Some(_) =>
data.remove(key) // expired
NotFound
case _ =>
NotFound
}
}
case Decr(key, value) =>
map.lock(key) { data => apply(Incr(key, -value)) }
case _ =>
NoOp
}
}