Repository: aisk/rust-memcache (language: rust)

Issue:
support stats function



Discussion / hints:

Fix patch:
diff --git a/.travis.yml b/.travis.yml
index f542a56..2be1d96 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,6 +24,9 @@ addons:
 
 services: memcache
 
+env:
+  - RUST_TEST_THREADS=1
+
 before_script:
   - memcached -p 12345 -d
   - memcached -p 12346 -d
diff --git a/src/client.rs b/src/client.rs
index a0ed8fd..4cd00b3 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -532,6 +532,30 @@ impl<'a> Client {
         self.get_connection(key).flush()?;
         return packet::parse_touch_response(self.get_connection(key));
     }
+
+    /// Get all servers' statistics.
+    ///
+    /// Example:
+    /// ```rust
+    /// let mut client = memcache::Client::new("memcache://localhost:12345").unwrap();
+    /// let stats = client.stats().unwrap();
+    /// ```
+    pub fn stats(&mut self) -> Result<Vec<(String, HashMap<String, String>)>, MemcacheError> {
+        let mut result: Vec<(String, HashMap<String, String>)> = vec![];
+        for connection in &mut self.connections {
+            let request_header = PacketHeader {
+                magic: Magic::Request as u8,
+                opcode: Opcode::Stat as u8,
+                ..Default::default()
+            };
+            request_header.write(connection)?;
+            connection.flush()?;
+            let stats_info = packet::parse_stats_response(connection)?;
+            let url = connection.url.clone();
+            result.push((url, stats_info));
+        }
+        return Ok(result);
+    }
 }
 
 #[cfg(test)]
diff --git a/src/packet.rs b/src/packet.rs
index e17d804..24b5456 100644
--- a/src/packet.rs
+++ b/src/packet.rs
@@ -14,6 +14,7 @@ pub enum Opcode {
     Increment = 0x05,
     Decrement = 0x06,
     Flush = 0x08,
+    Stat = 0x10,
     Noop = 0x0a,
     Version = 0x0b,
     GetKQ = 0x0d,
@@ -202,3 +203,27 @@ pub fn parse_touch_response<R: io::Read>(reader: &mut R) -> Result<bool, Memcach
     }
     return Ok(true);
 }
+
+pub fn parse_stats_response<R: io::Read>(reader: &mut R) -> Result<HashMap<String, String>, MemcacheError> {
+    let mut result = HashMap::new();
+    loop {
+        let header = PacketHeader::read(reader)?;
+        if header.vbucket_id_or_status != ResponseStatus::NoError as u16 {
+            return Err(MemcacheError::from(header.vbucket_id_or_status));
+        }
+        let key_length = header.key_length;
+        let value_length = header.total_body_length - u32::from(key_length) -
+            u32::from(header.extras_length);
+        let mut key_buffer = vec![0; key_length as usize];
+        reader.read_exact(key_buffer.as_mut_slice())?;
+        let key = String::from_utf8(key_buffer)?;
+        let mut value_buffer = vec![0; value_length as usize];
+        reader.read_exact(value_buffer.as_mut_slice())?;
+        let value = String::from_utf8(value_buffer)?;
+        if key == "" && value == "" {
+            break;
+        }
+        result.insert(key, value);
+    }
+    return Ok(result);
+}


Test patch: