Commits

Alexey Kishkin committed 65079dd

operations

Comments (0)

Files changed (2)

          set_i8 buffer extralen;                                   (* 4 *)
          set_i8 buffer 0;                                          (* 5 *) (* RAW data type *)
          set_i16 buffer 0;                                         (*6 7*) (* RESERVED *)
-         set_i32 buffer (vllen+keylen+extralen);                   (*8 9 10 11*)
+         set_i32 buffer (vllen + keylen + extralen);                   (*8 9 10 11*)
          set_i32 buffer opaque;                                    (*12 13 14 15*)
          set_int64 buffer cas;                                     (*16 17 18 19 20 21 22 23*)
          if extralen > 0 then (Buffer.add_string buffer extras);
          if keylen > 0 then (Buffer.add_string buffer key);
          if vllen > 0 then (Buffer.add_string buffer vl);
          Buffer.contents buffer
-   method printhex pct = 
-       for i=0 to (String.length pct)-1 do
+   method printhex pct =
+      for i = 0 to (String.length pct) - 1 do
          Printf.printf " 0x%2x " (Char.code (pct.[i]));
-         if ((i+1) mod  4) == 0 then print_string "\n"
-       done;
-       print_string "\n"
-      
+         if ((i + 1) mod 4) == 0 then print_string "\n"
+      done;
+      print_string "\n"
+   
    method decode_header pct =
       try
          let magic = self#magic_code_decode (get_i8 pct 0) in        (* 0 *)
-         (*      let _ = get_i8 pct 1 in *)                          (* 1 *)
+         let op = get_i8 pct 1 in                                    (* 1 *)
          let keylength = get_i16 pct 2 in                            (*2 3*)
          let extralength = get_i8 pct 4 in                           (* 4 *)
          let datatype = get_i8 pct 5 in                              (* 5 *)
          let cas = get_int64 pct 16 in                               (*16 17 18 19 20 21 22 23*)
          if (datatype <> 0) then raise (Bad_memcache_format "datatype is not RAW");
          if (magic <> Response) then raise (Bad_memcache_format "magic is not response");
-         (keylength, extralength, status, total_body_length, opaque, cas)
+         (keylength, extralength, status, total_body_length, opaque, cas, op)
       with
       | Invalid_argument _ -> raise (Bad_memcache_format "packet too short")
    
    method read_answer =
       let hdr = String.make 24 ' ' in
       let () = really_input i_channel hdr 0 24 in
-      let (keylength, extralength, status, total_body_length, opaque, cas) = self#decode_header hdr in
+      let (keylength, extralength, status, total_body_length, opaque, cas, op) = self#decode_header hdr in
       let body = String.make total_body_length ' ' in
       let () = really_input i_channel body 0 total_body_length in
       let (key, extras, value) = self#decode_body body keylength extralength total_body_length in
-      (status, key, value, extras, opaque, cas)
+      (status, op, key, value, extras, opaque, cas)
    
    method set key v flags expiration =
       let buf = Buffer.create 8 in
-      let _ = set_i32 buf flags and _ = set_i32 buf expiration in  
+      let _ = set_i32 buf flags and _ = set_i32 buf expiration in
       let extras = Buffer.contents buf in
       let cargo = self#encode_packet Set key extras v 0 0L in
       begin
-        (* self#printhex cargo; *)
+         (* self#printhex cargo; *)
          output_string o_channel cargo;
          flush o_channel;
-         let (status, key, value, extras, opaque, cas) = self#read_answer in
-         (status, value)
+         let (status, op, ky, value, extras, opaque, cas) = self#read_answer in
+         (status, ky, value)
       end
    
-   method delete key  =
+   method setq key v flags expiration =
+      let buf = Buffer.create 8 in
+      let _ = set_i32 buf flags and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet SetQ key extras v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel
+      end
+   
+   method add key v flags expiration =
+      let buf = Buffer.create 8 in
+      let _ = set_i32 buf flags and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet Add key extras v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, ky, value, extras, opaque, cas) = self#read_answer in
+         (status, ky, value)
+      end
+   
+   method addq key v flags expiration =
+      let buf = Buffer.create 8 in
+      let _ = set_i32 buf flags and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet AddQ key extras v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method replace key v flags expiration =
+      let buf = Buffer.create 8 in
+      let _ = set_i32 buf flags and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet Replace key extras v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method replaceq key v flags expiration =
+      let buf = Buffer.create 8 in
+      let _ = set_i32 buf flags and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet ReplaceQ key extras v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method delete key =
       let cargo = self#encode_packet Delete key "" "" 0 0L in
       begin
          output_string o_channel cargo;
          flush o_channel;
-         let (status, key, value, extras, opaque, cas) = self#read_answer in
-         (status, value)
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
       end
- 
-   method get key  =
-      let cargo = self#encode_packet Get key "" "" 0 0L in
+   
+   method deleteq key =
+      let cargo = self#encode_packet DeleteQ key "" "" 0 0L in
       begin
          output_string o_channel cargo;
          flush o_channel;
-         let (status, key, value, extras, opaque, cas) = self#read_answer in
-         (status, value)
       end
-      
+   
+   method get key =
+      let cargo = self#encode_packet GetK key "" "" 0 0L in
+      begin
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method multiget keys =
+      List.iter (fun key ->
+                  let cargo = self#encode_packet GetKQ key "" "" 0 0L in
+                  let () = output_string o_channel cargo in
+                  flush o_channel) keys;
+      let cargo = self#encode_packet Noop "" "" "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let continue = ref true in
+         let answers = ref [] in
+         while !continue do
+            let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+            if op = 0x0a
+            then continue := false
+            else answers := ((status, key, value) :: !answers)
+         done;
+         !answers
+      end
+   
+   method incr key (value_to_add: int64) (initial_value: int64) expiration =
+      let buf = Buffer.create 20 in
+      let _ = set_int64 buf value_to_add
+      and _ = set_int64 buf initial_value
+      and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet Increment key extras "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method incrq key (value_to_add: int64) (initial_value: int64) expiration =
+      let buf = Buffer.create 20 in
+      let _ = set_int64 buf value_to_add
+      and _ = set_int64 buf initial_value
+      and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet IncrementQ key extras "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method decr key (value_to_sub: int64) (initial_value: int64) expiration =
+      let buf = Buffer.create 20 in
+      let _ = set_int64 buf value_to_sub
+      and _ = set_int64 buf initial_value
+      and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet Decrement key extras "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, (get_int64 value 0))
+      end
+   
+   method decrq key (value_to_sub: int64) (initial_value: int64) expiration =
+      let buf = Buffer.create 20 in
+      let _ = set_int64 buf value_to_sub
+      and _ = set_int64 buf initial_value
+      and _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet DecrementQ key extras "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method quit =
+      let cargo = self#encode_packet Quit "" "" "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method quitq =
+      let cargo = self#encode_packet QuitQ "" "" "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method flush expiration =
+      let buf = Buffer.create 4 in
+      let _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet Flush "" extras "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method flushq expiration =
+      let buf = Buffer.create 4 in
+      let _ = set_i32 buf expiration in
+      let extras = Buffer.contents buf in
+      let cargo = self#encode_packet FlushQ "" extras "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method noop =
+      let cargo = self#encode_packet Noop "" "" "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method version =
+      let cargo = self#encode_packet Version "" "" "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method append key v =
+      let cargo = self#encode_packet Append key "" v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method appendq key v =
+      let cargo = self#encode_packet AppendQ key "" v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method prepend key v =
+      let cargo = self#encode_packet Prepend key "" v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method prependq key v =
+      let cargo = self#encode_packet PrependQ key "" v 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+      end
+   
+   method stat key =
+      let cargo = self#encode_packet Stat key "" "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let (status, op, key, value, extras, opaque, cas) = self#read_answer in
+         (status, key, value)
+      end
+   
+   method stat_all =
+      let cargo = self#encode_packet Stat "" "" "" 0 0L in
+      begin
+         (* self#printhex cargo; *)
+         output_string o_channel cargo;
+         flush o_channel;
+         let collect = ref [] in
+         let continue = ref true in
+         while !continue do
+            let (status, op, ky, value, extras, opaque, cas) = self#read_answer in
+            if ((String.length ky) = 0) && ((String.length value) = 0)
+            then (continue := false)
+            else (collect := (status, ky, value) :: !collect)
+         done;
+         !collect
+      end
    
    initializer
    let i, o = Unix.open_connection (Unix.ADDR_INET ((Unix.inet_addr_of_string host), port)) in
    
 end;;
 
-
-let presult (status,value) = print_endline (match status with
-   | MC_Out_of_memory -> "out_of_memory"
-   | MC_No_error -> ("value "^value)
-   | MC_Key_not_found -> "notfound"
-   | MC_Key_exists -> "key exists"
-   | MC_Value_too_large -> "too large"
-   | MC_Invalid_argument -> "Invalid argument"
-   | MC_Item_not_stored -> "not stored"
-   | MC_Unknown_comamnd -> "unknown command")
+let presult (status, key, value) =
+   print_string (key^" :: ");
+   print_endline (match status with
+         | MC_Out_of_memory -> "out_of_memory"
+         | MC_No_error -> ("value "^value)
+         | MC_Key_not_found -> "notfound"
+         | MC_Key_exists -> "key exists"
+         | MC_Value_too_large -> "too large"
+         | MC_Invalid_argument -> "Invalid argument"
+         | MC_Item_not_stored -> "not stored"
+         | MC_Unknown_comamnd -> "unknown command")
 
 let c = new memcache_connector "127.0.0.1" 11211;;
-c#set "walrus" "Oi to ne veter to ne veter" 0 0;;
-presult (c#get "walrus");;
-presult (c#get "wax");;
-
-
-    
+c#set "walrus" "1963" 0 0;;
+c#set "wax" "1969" 0 0;;
+c#set "mumka" "1959" 0 0;;
+c#append "walrus" " year";;
+List.iter (fun x -> presult x) (c#multiget ["wax";"walrus"]);;
+List.iter (fun x -> presult x) (c#stat_all);;
-type operation =
-    Get
-  | Set
-  | Add
-  | Replace
-  | Delete
-  | Increment
-  | Decrement
-  | Quit
-  | Flush
-  | GetQ
-  | Noop
-  | Version
-  | GetK
-  | GetKQ
-  | Append
-  | Prepend
-  | Stat
-  | SetQ
-  | AddQ
-  | ReplaceQ
-  | DeleteQ
-  | IncrementQ
-  | DecrementQ
-  | QuitQ
-  | FlushQ
-  | AppendQ
-  | PrependQ
-type magic = Request | Response
-type response_status =
-    MC_No_error
-  | MC_Key_not_found
-  | MC_Key_exists
-  | MC_Value_too_large
-  | MC_Invalid_argument
-  | MC_Item_not_stored
-  | MC_Unknown_comamnd
-  | MC_Out_of_memory
-exception Bad_memcache_format of string
-val set_i8 : Buffer.t -> int -> unit
-val set_i16 : Buffer.t -> int -> unit
-val set_i32 : Buffer.t -> int -> unit
-val set_int32 : Buffer.t -> int32 -> unit
-val set_int64 : Buffer.t -> int64 -> unit
-val get_i8 : string -> int -> int
-val get_i16 : string -> int -> int
-val get_i32 : string -> int -> int
-val get_int32 : string -> int -> int32
-val get_int64 : string -> int -> int64
-class memcache_connector :
-  string ->
-  int ->
-  object
-    val host : string
-    val mutable i_channel : in_channel
-    val mutable o_channel : out_channel
-    val port : int
-    method decode_body :
-      string -> int -> int -> int -> string * string * string
-    method decode_header :
-      string -> int * int * response_status * int * int * int64
-    method delete : string -> response_status * string
-    method encode_packet :
-      operation -> string -> string -> string -> int -> int64 -> string
-    method get : string -> response_status * string
-    method magic_code_decode : int -> magic
-    method magic_code_encode : magic -> int
-    method operation_encode : operation -> int
-    method printhex : string -> unit
-    method read_answer :
-      response_status * string * string * string * int * int64
-    method response_status_decode : int -> response_status
-    method set : string -> string -> int -> int -> response_status * string
-  end
-val presult : response_status * string -> unit
-val c : memcache_connector