Last active
November 23, 2017 00:51
-
-
Save mattknox/56b90335d675b6e6b970e4d3937517bd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "socket" | |
class Memcached | |
attr_accessor :client | |
def initialize(store = {}) | |
@client = client | |
@store = store | |
end | |
def get(key) | |
if value = @store[key] | |
"VALUE #{key} #{value.length}\n#{value}\nEND\n" | |
else | |
"END\n" | |
end | |
end | |
def set(key, data) | |
@store[key] = data | |
"STORED" | |
end | |
def serve(client) | |
while !client.eof? do | |
execute_command(client) | |
end | |
rescue Exception => e | |
puts e.class | |
puts e.message | |
puts e.backtrace | |
end | |
def parse(line) | |
verb, *rest = line.split | |
if "get" == verb && rest.size == 1 && rest.first.match(/^[a-zA-Z_]+$/) | |
[:get, rest] | |
elsif "get" == verb && rest.size > 1 && rest.all? {|s| s.match(/^[a-zA-Z_]+$/) } | |
[:get_multi, rest] | |
elsif "set" == verb && rest.size == 2 && rest.first.match(/^[a-zA-Z_]+$/) && rest.last.match(/^[1-9]\d*$/) | |
[:set, [rest.first], rest.last.to_i] | |
else | |
raise ArgumentError.new("invalid command #{line}") | |
end | |
end | |
def execute_command(client) | |
verb, keys, data_len = parse(client.gets) | |
if :get == verb | |
client.puts get(keys.first) | |
elsif :get_multi == verb | |
keys.map { |key| client.puts(get(key)) } | |
elsif :set == verb | |
data = client.read(data_len.succ).chomp | |
raise ArgumentError.new("bad data_len #{data_len} for data '#{data}'") unless data_len == data.length | |
client.puts set(keys.first, data) | |
end | |
end | |
end | |
class Runner | |
def self.run(port) | |
server = TCPServer.new port | |
server.setsockopt(:SOCKET, :REUSEADDR, 1) | |
memcache = Memcached.new | |
loop do | |
Thread.start(server.accept) do |client| | |
puts "server.accept" | |
memcache.serve client #BufferedSocketClient.new(client) | |
end | |
end | |
end | |
end | |
class FakeClient | |
def eof? | |
false | |
end | |
def gets | |
Kernel.gets | |
end | |
def puts(s) | |
Kernel.puts s | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment