memcache クライアントを実装してみた その2

目的

  • 前回 methaneさんにコメントで指摘された部分の修正


ソース

  • 修正した関数は以下の2つなので今回はその部分のソースのみ載せます
    • set
    • get
 21   def set(self, key, value, exptime=0, flags=0):
 22     # translate value to binary
 23     pickled_value = pickle.dumps(value, 2)
 24     length = len(pickled_value)
 25     totalsent = 0
 26 
 27     # request
 28     sendmsg  = "set %s %d %s %d" % (key, flags, exptime, length)
 29     sendmsg += "\r\n"
 30     sendmsg += pickled_value
 31     sendmsg += "\r\n"
 32 
 33     while totalsent < length:
 34       sent = self.__sock.send(sendmsg[totalsent:])
 35       totalsent += sent
 36 
 37     # response
 38     recvmsg = ''
 39 
 40     while True:
 41       chunk = self.__sock.recv(BUFSIZE)
 42       recvmsg += chunk
 43 
 44       if recvmsg.find("\r\n") != -1:
 45         break
 46 
 47     # return
 48     if recvmsg == "STORED\r\n":
 49       return True
 50     else:
 51       return False
 52 
 53 
 54   def get(self, key):
 55     # request
 56     sendmsg = "get %s\r\n" % key
 57     length = len(sendmsg)
 58     totalsent = 0
 59 
 60     while totalsent < length:
 61       sent = self.__sock.send(sendmsg[totalsent:])
 62       totalsent += sent
 63 
 64     # response
 65     recvmsg = ''
 66 
 67     ## header
 68     header = ''
 69 
 70     while True:
 71       chunk = self.__sock.recv(BUFSIZE)
 72       recvmsg += chunk
 73 
 74       if header == '' and recvmsg.find("\r\n") != -1:
 75         [header, dummy] = recvmsg.split("\r\n", 1)
 76         break
 77 
 78     [dummy1, dummy2, dummy3, length] = header.split()
 79 
 80     ## body
 81     body = ''
 82     length = len(header) + len("\r\n") + int(length) + len("\r\n") + len("END\r\n")
 83 
 84     totalrecv = len(recvmsg)
 85 
 86     while totalrecv < length:
 87       chunk = self.__sock.recv(BUFSIZE)
 88       recvmsg += chunk
 89       totalrecv += len(chunk)
 90 
 91     [header, body] = recvmsg.split("\r\n", 1)
 92     [pickled_value, dummy1, dummy2] = body.rsplit("\r\n", 2)
 93 
 94     # return
 95     return pickle.loads(pickled_value)


修正点

  • set
    • value をバイナリに変換
    • メッセージを確実に全て送信
    • メッセージを少なくとも必要な分は全て受信
  • get
    • メッセージを確実に全て送信
    • メッセージの一つ目の改行文字"\r\n"で分割して header とする
      • header から set した value の長さを取得
    • メッセージの全ての長さを計算
      • header + "\r\n" + value + "\r\n" + "END\r\n"
    • メッセージを少なくとも必要な分は全て受信
    • バイナリから value へ変換

結果

  • BUFSIZE = 2 (recv が一度に受信する最大バイト数) として実行したが、前回と同様の結果が得られた