1pub mod pool;
38pub mod sharded;
39pub use pool::{Pool, PoolConfig};
40pub use sharded::{ShardedClient, ShardedConfig};
41
42use std::cell::Cell;
43use std::collections::VecDeque;
44use std::io;
45use std::time::Instant;
46
47use bytes::Bytes;
48use memcache_proto::{Request as McRequest, ResponseBytes as McResponseBytes};
49use ringline::{ConnCtx, GuardBox, ParseResult, SendGuard};
50
51type ResultCallback = Box<dyn Fn(&CommandResult)>;
53
54#[derive(Debug, thiserror::Error)]
58pub enum Error {
59 #[error("connection closed")]
61 ConnectionClosed,
62
63 #[error("memcache error: {0}")]
65 Memcache(String),
66
67 #[error("unexpected response")]
69 UnexpectedResponse,
70
71 #[error("protocol error: {0}")]
73 Protocol(#[from] memcache_proto::ParseError),
74
75 #[error("io error: {0}")]
77 Io(#[from] io::Error),
78
79 #[error("all connections failed")]
81 AllConnectionsFailed,
82
83 #[error("no pending operations")]
85 NoPending,
86}
87
88#[derive(Debug, Clone)]
92pub struct Value {
93 pub data: Bytes,
95 pub flags: u32,
97}
98
99#[derive(Debug, Clone)]
101pub struct GetValue {
102 pub key: Bytes,
104 pub data: Bytes,
106 pub flags: u32,
108 pub cas: Option<u64>,
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq)]
116pub enum CommandType {
117 Get,
118 Set,
119 Delete,
120 Other,
121}
122
123#[derive(Debug, Clone)]
125pub struct CommandResult {
126 pub command: CommandType,
128 pub latency_ns: u64,
130 pub hit: Option<bool>,
132 pub success: bool,
134 pub ttfb_ns: Option<u64>,
136 pub tx_bytes: u32,
138 pub rx_bytes: u32,
140}
141
142#[cfg(feature = "metrics")]
147pub struct ClientMetrics {
148 pub latency: histogram::Histogram,
150 pub get_latency: histogram::Histogram,
152 pub set_latency: histogram::Histogram,
154 pub del_latency: histogram::Histogram,
156 pub requests: u64,
158 pub errors: u64,
160 pub hits: u64,
162 pub misses: u64,
164}
165
166#[cfg(feature = "metrics")]
167impl ClientMetrics {
168 fn new() -> Self {
169 Self {
170 latency: histogram::Histogram::new(7, 64).unwrap(),
171 get_latency: histogram::Histogram::new(7, 64).unwrap(),
172 set_latency: histogram::Histogram::new(7, 64).unwrap(),
173 del_latency: histogram::Histogram::new(7, 64).unwrap(),
174 requests: 0,
175 errors: 0,
176 hits: 0,
177 misses: 0,
178 }
179 }
180
181 fn record(&mut self, result: &CommandResult) {
182 self.requests += 1;
183 let _ = self.latency.increment(result.latency_ns);
184
185 if !result.success {
186 self.errors += 1;
187 }
188
189 match result.command {
190 CommandType::Get => {
191 let _ = self.get_latency.increment(result.latency_ns);
192 match result.hit {
193 Some(true) => self.hits += 1,
194 Some(false) => self.misses += 1,
195 None => {}
196 }
197 }
198 CommandType::Set => {
199 let _ = self.set_latency.increment(result.latency_ns);
200 }
201 CommandType::Delete => {
202 let _ = self.del_latency.increment(result.latency_ns);
203 }
204 _ => {}
205 }
206 }
207}
208
209enum PendingOpKind {
212 Get,
213 Set,
214 Delete,
215}
216
217struct PendingOp {
218 kind: PendingOpKind,
219 send_ts: u64,
220 start: Option<Instant>,
221 user_data: u64,
222 tx_bytes: u32,
223}
224
225pub enum CompletedOp {
227 Get {
229 result: Result<Option<Value>, Error>,
230 user_data: u64,
231 latency_ns: u64,
232 },
233 Set {
235 result: Result<(), Error>,
236 user_data: u64,
237 latency_ns: u64,
238 },
239 Delete {
241 result: Result<bool, Error>,
242 user_data: u64,
243 latency_ns: u64,
244 },
245}
246
247pub struct ClientBuilder {
251 conn: ConnCtx,
252 on_result: Option<ResultCallback>,
253 #[cfg(feature = "timestamps")]
254 use_kernel_ts: bool,
255 #[cfg(feature = "metrics")]
256 with_metrics: bool,
257}
258
259impl ClientBuilder {
260 pub(crate) fn new(conn: ConnCtx) -> Self {
261 Self {
262 conn,
263 on_result: None,
264 #[cfg(feature = "timestamps")]
265 use_kernel_ts: false,
266 #[cfg(feature = "metrics")]
267 with_metrics: false,
268 }
269 }
270
271 pub fn on_result<F: Fn(&CommandResult) + 'static>(mut self, f: F) -> Self {
273 self.on_result = Some(Box::new(f));
274 self
275 }
276
277 #[cfg(feature = "timestamps")]
279 pub fn kernel_timestamps(mut self, enabled: bool) -> Self {
280 self.use_kernel_ts = enabled;
281 self
282 }
283
284 #[cfg(feature = "metrics")]
286 pub fn with_metrics(mut self) -> Self {
287 self.with_metrics = true;
288 self
289 }
290
291 pub fn build(self) -> Client {
293 Client {
294 conn: self.conn,
295 on_result: self.on_result,
296 pending: VecDeque::new(),
297 last_rx_bytes: Cell::new(0),
298 #[cfg(feature = "timestamps")]
299 use_kernel_ts: self.use_kernel_ts,
300 #[cfg(feature = "metrics")]
301 metrics: if self.with_metrics {
302 Some(ClientMetrics::new())
303 } else {
304 None
305 },
306 }
307 }
308}
309
310pub struct Client {
318 conn: ConnCtx,
319 on_result: Option<ResultCallback>,
320 pending: VecDeque<PendingOp>,
321 last_rx_bytes: Cell<u32>,
322 #[cfg(feature = "timestamps")]
323 use_kernel_ts: bool,
324 #[cfg(feature = "metrics")]
325 metrics: Option<ClientMetrics>,
326}
327
328impl Client {
329 pub fn new(conn: ConnCtx) -> Self {
333 Self {
334 conn,
335 on_result: None,
336 pending: VecDeque::new(),
337 last_rx_bytes: Cell::new(0),
338 #[cfg(feature = "timestamps")]
339 use_kernel_ts: false,
340 #[cfg(feature = "metrics")]
341 metrics: None,
342 }
343 }
344
345 pub fn builder(conn: ConnCtx) -> ClientBuilder {
347 ClientBuilder::new(conn)
348 }
349
350 pub fn conn(&self) -> ConnCtx {
352 self.conn
353 }
354
355 #[cfg(feature = "metrics")]
357 pub fn metrics(&self) -> Option<&ClientMetrics> {
358 self.metrics.as_ref()
359 }
360
361 #[cfg(feature = "metrics")]
363 pub fn metrics_mut(&mut self) -> Option<&mut ClientMetrics> {
364 self.metrics.as_mut()
365 }
366
367 #[inline]
370 fn is_instrumented(&self) -> bool {
371 if self.on_result.is_some() {
372 return true;
373 }
374 #[cfg(feature = "metrics")]
375 if self.metrics.is_some() {
376 return true;
377 }
378 false
379 }
380
381 #[cfg(feature = "timestamps")]
382 #[inline]
383 fn send_timestamp(&self) -> u64 {
384 if self.use_kernel_ts {
385 now_realtime_ns()
386 } else {
387 0
388 }
389 }
390
391 #[cfg(not(feature = "timestamps"))]
392 #[inline]
393 fn send_timestamp(&self) -> u64 {
394 0
395 }
396
397 #[cfg(feature = "timestamps")]
398 #[inline]
399 fn finish_timing(&self, send_ts: u64, start: Instant) -> u64 {
400 if self.use_kernel_ts {
401 let recv_ts = self.conn.recv_timestamp();
402 if recv_ts > 0 && recv_ts > send_ts {
403 return recv_ts - send_ts;
404 }
405 }
406 start.elapsed().as_nanos() as u64
407 }
408
409 #[cfg(not(feature = "timestamps"))]
410 #[inline]
411 fn finish_timing(&self, _send_ts: u64, start: Instant) -> u64 {
412 start.elapsed().as_nanos() as u64
413 }
414
415 fn record(&mut self, result: &CommandResult) {
416 if let Some(ref cb) = self.on_result {
417 cb(result);
418 }
419 #[cfg(feature = "metrics")]
420 if let Some(ref mut m) = self.metrics {
421 m.record(result);
422 }
423 }
424
425 #[inline]
428 fn timing_start(&self) -> (u64, Option<Instant>) {
429 if self.is_instrumented() {
430 (self.send_timestamp(), Some(Instant::now()))
431 } else {
432 (0, None)
433 }
434 }
435
436 #[cfg(feature = "timestamps")]
437 #[inline]
438 fn compute_ttfb(&self, send_ts: u64) -> Option<u64> {
439 if self.use_kernel_ts {
440 let recv_ts = self.conn.recv_timestamp();
441 if recv_ts > 0 && recv_ts > send_ts {
442 return Some(recv_ts - send_ts);
443 }
444 }
445 None
446 }
447
448 #[cfg(not(feature = "timestamps"))]
449 #[inline]
450 fn compute_ttfb(&self, _send_ts: u64) -> Option<u64> {
451 None
452 }
453
454 pub fn pending_count(&self) -> usize {
456 self.pending.len()
457 }
458
459 pub fn fire_get(&mut self, key: &[u8], user_data: u64) -> Result<(), Error> {
461 let encoded = encode_request(&McRequest::get(key));
462 let tx_bytes = encoded.len() as u32;
463 self.conn.send_nowait(&encoded)?;
464 let (send_ts, start) = self.timing_start();
465 self.pending.push_back(PendingOp {
466 kind: PendingOpKind::Get,
467 send_ts,
468 start,
469 user_data,
470 tx_bytes,
471 });
472 Ok(())
473 }
474
475 pub fn fire_set(
477 &mut self,
478 key: &[u8],
479 value: &[u8],
480 flags: u32,
481 exptime: u32,
482 user_data: u64,
483 ) -> Result<(), Error> {
484 let encoded = encode_set(key, value, flags, exptime);
485 let tx_bytes = encoded.len() as u32;
486 self.conn.send_nowait(&encoded)?;
487 let (send_ts, start) = self.timing_start();
488 self.pending.push_back(PendingOp {
489 kind: PendingOpKind::Set,
490 send_ts,
491 start,
492 user_data,
493 tx_bytes,
494 });
495 Ok(())
496 }
497
498 pub fn fire_set_with_guard<G: SendGuard>(
500 &mut self,
501 key: &[u8],
502 guard: G,
503 flags: u32,
504 exptime: u32,
505 user_data: u64,
506 ) -> Result<(), Error> {
507 let (_, value_len) = guard.as_ptr_len();
508 let prefix = encode_set_guard_prefix(key, value_len as usize, flags, exptime);
509 let tx_bytes = (prefix.len() + value_len as usize + 2) as u32;
510 self.conn.send_parts().build(move |b| {
511 b.copy(&prefix)
512 .guard(GuardBox::new(guard))
513 .copy(b"\r\n")
514 .submit()
515 })?;
516 let (send_ts, start) = self.timing_start();
517 self.pending.push_back(PendingOp {
518 kind: PendingOpKind::Set,
519 send_ts,
520 start,
521 user_data,
522 tx_bytes,
523 });
524 Ok(())
525 }
526
527 pub fn fire_delete(&mut self, key: &[u8], user_data: u64) -> Result<(), Error> {
529 let encoded = encode_request(&McRequest::delete(key));
530 let tx_bytes = encoded.len() as u32;
531 self.conn.send_nowait(&encoded)?;
532 let (send_ts, start) = self.timing_start();
533 self.pending.push_back(PendingOp {
534 kind: PendingOpKind::Delete,
535 send_ts,
536 start,
537 user_data,
538 tx_bytes,
539 });
540 Ok(())
541 }
542
543 pub async fn recv(&mut self) -> Result<CompletedOp, Error> {
547 let pending = self.pending.pop_front().ok_or(Error::NoPending)?;
548
549 let ttfb_ns = self.compute_ttfb(pending.send_ts);
551
552 let response = match self.read_response().await {
553 Ok(v) => v,
554 Err(e) => {
555 self.pending.clear();
559 return Err(e);
560 }
561 };
562 let latency_ns = match pending.start {
563 Some(start) => self.finish_timing(pending.send_ts, start),
564 None => 0,
565 };
566 let rx_bytes = self.last_rx_bytes.get();
567 let tx_bytes = pending.tx_bytes;
568
569 let op = match pending.kind {
570 PendingOpKind::Get => {
571 let result = match check_error_bytes(&response) {
573 Err(e) => Err(e),
574 Ok(()) => match response {
575 McResponseBytes::Values(mut values) => {
576 if values.is_empty() {
577 Ok(None)
578 } else {
579 let v = values.swap_remove(0);
580 Ok(Some(Value {
581 data: v.data,
582 flags: v.flags,
583 }))
584 }
585 }
586 _ => Err(Error::UnexpectedResponse),
587 },
588 };
589 let (success, hit) = match &result {
590 Ok(Some(_)) => (true, Some(true)),
591 Ok(None) => (true, Some(false)),
592 Err(_) => (false, None),
593 };
594 self.record(&CommandResult {
595 command: CommandType::Get,
596 latency_ns,
597 hit,
598 success,
599 ttfb_ns,
600 tx_bytes,
601 rx_bytes,
602 });
603 CompletedOp::Get {
604 result,
605 user_data: pending.user_data,
606 latency_ns,
607 }
608 }
609 PendingOpKind::Set => {
610 let result = match check_error_bytes(&response) {
611 Err(e) => Err(e),
612 Ok(()) => match response {
613 McResponseBytes::Stored => Ok(()),
614 _ => Err(Error::UnexpectedResponse),
615 },
616 };
617 self.record(&CommandResult {
618 command: CommandType::Set,
619 latency_ns,
620 hit: None,
621 success: result.is_ok(),
622 ttfb_ns,
623 tx_bytes,
624 rx_bytes,
625 });
626 CompletedOp::Set {
627 result,
628 user_data: pending.user_data,
629 latency_ns,
630 }
631 }
632 PendingOpKind::Delete => {
633 let result = match check_error_bytes(&response) {
634 Err(e) => Err(e),
635 Ok(()) => match response {
636 McResponseBytes::Deleted => Ok(true),
637 McResponseBytes::NotFound => Ok(false),
638 _ => Err(Error::UnexpectedResponse),
639 },
640 };
641 self.record(&CommandResult {
642 command: CommandType::Delete,
643 latency_ns,
644 hit: None,
645 success: result.is_ok(),
646 ttfb_ns,
647 tx_bytes,
648 rx_bytes,
649 });
650 CompletedOp::Delete {
651 result,
652 user_data: pending.user_data,
653 latency_ns,
654 }
655 }
656 };
657
658 Ok(op)
659 }
660
661 pub(crate) async fn read_response(&self) -> Result<McResponseBytes, Error> {
669 let mut result: Option<Result<McResponseBytes, Error>> = None;
670 let n = self
671 .conn
672 .with_bytes(|bytes| {
673 let len = bytes.len();
674 match McResponseBytes::parse(bytes) {
675 Ok((response, consumed)) => {
676 result = Some(Ok(response));
677 ParseResult::Consumed(consumed)
678 }
679 Err(e) if e.is_incomplete() => ParseResult::Consumed(0),
680 Err(e) => {
681 result = Some(Err(Error::Protocol(e)));
682 ParseResult::Consumed(len)
683 }
684 }
685 })
686 .await;
687 self.last_rx_bytes.set(n as u32);
688 if n == 0 {
689 return result.unwrap_or(Err(Error::ConnectionClosed));
690 }
691 result.unwrap()
692 }
693
694 async fn execute(&self, encoded: &[u8]) -> Result<McResponseBytes, Error> {
697 self.conn.send(encoded)?;
698 let response = self.read_response().await?;
699 check_error_bytes(&response)?;
700 Ok(response)
701 }
702
703 pub async fn get(&mut self, key: impl AsRef<[u8]>) -> Result<Option<Value>, Error> {
707 let key = key.as_ref();
708 let encoded = encode_request(&McRequest::get(key));
709
710 if !self.is_instrumented() {
711 let response = self.execute(&encoded).await?;
712 return match response {
713 McResponseBytes::Values(mut values) => {
714 if values.is_empty() {
715 Ok(None)
716 } else {
717 let v = values.swap_remove(0);
718 Ok(Some(Value {
719 data: v.data,
720 flags: v.flags,
721 }))
722 }
723 }
724 _ => Err(Error::UnexpectedResponse),
725 };
726 }
727
728 let tx_bytes = encoded.len() as u32;
729 let send_ts = self.send_timestamp();
730 let start = Instant::now();
731 let response = self.execute(&encoded).await;
732 let latency_ns = self.finish_timing(send_ts, start);
733 let rx_bytes = self.last_rx_bytes.get();
734
735 let result = match response {
736 Ok(McResponseBytes::Values(mut values)) => {
737 if values.is_empty() {
738 Ok(None)
739 } else {
740 let v = values.swap_remove(0);
741 Ok(Some(Value {
742 data: v.data,
743 flags: v.flags,
744 }))
745 }
746 }
747 Ok(_) => Err(Error::UnexpectedResponse),
748 Err(e) => Err(e),
749 };
750
751 let (success, hit) = match &result {
752 Ok(Some(_)) => (true, Some(true)),
753 Ok(None) => (true, Some(false)),
754 Err(_) => (false, None),
755 };
756 self.record(&CommandResult {
757 command: CommandType::Get,
758 latency_ns,
759 hit,
760 success,
761 ttfb_ns: None,
762 tx_bytes,
763 rx_bytes,
764 });
765 result
766 }
767
768 pub async fn gets(&mut self, keys: &[&[u8]]) -> Result<Vec<GetValue>, Error> {
770 if keys.is_empty() {
771 return Ok(Vec::new());
772 }
773 let encoded = encode_request(&McRequest::gets(keys));
774 let response = self.execute(&encoded).await?;
775 match response {
776 McResponseBytes::Values(values) => Ok(values
777 .into_iter()
778 .map(|v| GetValue {
779 key: v.key,
780 data: v.data,
781 flags: v.flags,
782 cas: v.cas,
783 })
784 .collect()),
785 _ => Err(Error::UnexpectedResponse),
786 }
787 }
788
789 pub async fn set(
791 &mut self,
792 key: impl AsRef<[u8]>,
793 value: impl AsRef<[u8]>,
794 ) -> Result<(), Error> {
795 self.set_with_options(key, value, 0, 0).await
796 }
797
798 pub async fn set_with_options(
800 &mut self,
801 key: impl AsRef<[u8]>,
802 value: impl AsRef<[u8]>,
803 flags: u32,
804 exptime: u32,
805 ) -> Result<(), Error> {
806 let key = key.as_ref();
807 let value = value.as_ref();
808 let encoded = encode_set(key, value, flags, exptime);
809
810 if !self.is_instrumented() {
811 let response = self.execute(&encoded).await?;
812 return match response {
813 McResponseBytes::Stored => Ok(()),
814 _ => Err(Error::UnexpectedResponse),
815 };
816 }
817
818 let tx_bytes = encoded.len() as u32;
819 let send_ts = self.send_timestamp();
820 let start = Instant::now();
821 let response = self.execute(&encoded).await;
822 let latency_ns = self.finish_timing(send_ts, start);
823 let rx_bytes = self.last_rx_bytes.get();
824
825 let result = match response {
826 Ok(McResponseBytes::Stored) => Ok(()),
827 Ok(_) => Err(Error::UnexpectedResponse),
828 Err(e) => Err(e),
829 };
830 self.record(&CommandResult {
831 command: CommandType::Set,
832 latency_ns,
833 hit: None,
834 success: result.is_ok(),
835 ttfb_ns: None,
836 tx_bytes,
837 rx_bytes,
838 });
839 result
840 }
841
842 pub async fn add(
845 &mut self,
846 key: impl AsRef<[u8]>,
847 value: impl AsRef<[u8]>,
848 ) -> Result<bool, Error> {
849 let key = key.as_ref();
850 let value = value.as_ref();
851 let encoded = encode_add(key, value);
852 let response = self.execute(&encoded).await?;
853 match response {
854 McResponseBytes::Stored => Ok(true),
855 McResponseBytes::NotStored => Ok(false),
856 _ => Err(Error::UnexpectedResponse),
857 }
858 }
859
860 pub async fn replace(
863 &mut self,
864 key: impl AsRef<[u8]>,
865 value: impl AsRef<[u8]>,
866 ) -> Result<bool, Error> {
867 let key = key.as_ref();
868 let value = value.as_ref();
869 let encoded = encode_request(&McRequest::Replace {
870 key,
871 value,
872 flags: 0,
873 exptime: 0,
874 });
875 let response = self.execute(&encoded).await?;
876 match response {
877 McResponseBytes::Stored => Ok(true),
878 McResponseBytes::NotStored => Ok(false),
879 _ => Err(Error::UnexpectedResponse),
880 }
881 }
882
883 pub async fn incr(&mut self, key: impl AsRef<[u8]>, delta: u64) -> Result<Option<u64>, Error> {
886 let key = key.as_ref();
887 let encoded = encode_request(&McRequest::incr(key, delta));
888 let response = self.execute(&encoded).await?;
889 match response {
890 McResponseBytes::Numeric(val) => Ok(Some(val)),
891 McResponseBytes::NotFound => Ok(None),
892 _ => Err(Error::UnexpectedResponse),
893 }
894 }
895
896 pub async fn decr(&mut self, key: impl AsRef<[u8]>, delta: u64) -> Result<Option<u64>, Error> {
899 let key = key.as_ref();
900 let encoded = encode_request(&McRequest::decr(key, delta));
901 let response = self.execute(&encoded).await?;
902 match response {
903 McResponseBytes::Numeric(val) => Ok(Some(val)),
904 McResponseBytes::NotFound => Ok(None),
905 _ => Err(Error::UnexpectedResponse),
906 }
907 }
908
909 pub async fn append(
912 &mut self,
913 key: impl AsRef<[u8]>,
914 value: impl AsRef<[u8]>,
915 ) -> Result<bool, Error> {
916 let key = key.as_ref();
917 let value = value.as_ref();
918 let encoded = encode_request(&McRequest::append(key, value));
919 let response = self.execute(&encoded).await?;
920 match response {
921 McResponseBytes::Stored => Ok(true),
922 McResponseBytes::NotStored => Ok(false),
923 _ => Err(Error::UnexpectedResponse),
924 }
925 }
926
927 pub async fn prepend(
930 &mut self,
931 key: impl AsRef<[u8]>,
932 value: impl AsRef<[u8]>,
933 ) -> Result<bool, Error> {
934 let key = key.as_ref();
935 let value = value.as_ref();
936 let encoded = encode_request(&McRequest::prepend(key, value));
937 let response = self.execute(&encoded).await?;
938 match response {
939 McResponseBytes::Stored => Ok(true),
940 McResponseBytes::NotStored => Ok(false),
941 _ => Err(Error::UnexpectedResponse),
942 }
943 }
944
945 pub async fn cas(
949 &mut self,
950 key: impl AsRef<[u8]>,
951 value: impl AsRef<[u8]>,
952 cas_unique: u64,
953 ) -> Result<bool, Error> {
954 let key = key.as_ref();
955 let value = value.as_ref();
956 let encoded = encode_request(&McRequest::cas(key, value, cas_unique));
957 let response = self.execute(&encoded).await?;
958 match response {
959 McResponseBytes::Stored => Ok(true),
960 McResponseBytes::Exists => Ok(false),
961 McResponseBytes::NotFound => Err(Error::Memcache("NOT_FOUND".into())),
962 _ => Err(Error::UnexpectedResponse),
963 }
964 }
965
966 pub async fn delete(&mut self, key: impl AsRef<[u8]>) -> Result<bool, Error> {
968 let key = key.as_ref();
969 let encoded = encode_request(&McRequest::delete(key));
970
971 if !self.is_instrumented() {
972 let response = self.execute(&encoded).await?;
973 return match response {
974 McResponseBytes::Deleted => Ok(true),
975 McResponseBytes::NotFound => Ok(false),
976 _ => Err(Error::UnexpectedResponse),
977 };
978 }
979
980 let tx_bytes = encoded.len() as u32;
981 let send_ts = self.send_timestamp();
982 let start = Instant::now();
983 let response = self.execute(&encoded).await;
984 let latency_ns = self.finish_timing(send_ts, start);
985 let rx_bytes = self.last_rx_bytes.get();
986
987 let result = match response {
988 Ok(McResponseBytes::Deleted) => Ok(true),
989 Ok(McResponseBytes::NotFound) => Ok(false),
990 Ok(_) => Err(Error::UnexpectedResponse),
991 Err(e) => Err(e),
992 };
993 self.record(&CommandResult {
994 command: CommandType::Delete,
995 latency_ns,
996 hit: None,
997 success: result.is_ok(),
998 ttfb_ns: None,
999 tx_bytes,
1000 rx_bytes,
1001 });
1002 result
1003 }
1004
1005 pub async fn flush_all(&mut self) -> Result<(), Error> {
1007 let encoded = encode_request(&McRequest::flush_all());
1008 let response = self.execute(&encoded).await?;
1009 match response {
1010 McResponseBytes::Ok => Ok(()),
1011 _ => Err(Error::UnexpectedResponse),
1012 }
1013 }
1014
1015 pub async fn version(&mut self) -> Result<String, Error> {
1017 let encoded = encode_request(&McRequest::version());
1018 let response = self.execute(&encoded).await?;
1019 match response {
1020 McResponseBytes::Version(v) => Ok(String::from_utf8_lossy(&v).into_owned()),
1021 _ => Err(Error::UnexpectedResponse),
1022 }
1023 }
1024
1025 pub async fn set_with_guard<G: SendGuard>(
1030 &mut self,
1031 key: &[u8],
1032 guard: G,
1033 flags: u32,
1034 exptime: u32,
1035 ) -> Result<(), Error> {
1036 if !self.is_instrumented() {
1037 let (_, value_len) = guard.as_ptr_len();
1038 let prefix = encode_set_guard_prefix(key, value_len as usize, flags, exptime);
1039
1040 self.conn.send_parts().build(move |b| {
1041 b.copy(&prefix)
1042 .guard(GuardBox::new(guard))
1043 .copy(b"\r\n")
1044 .submit()
1045 })?;
1046
1047 let response = self.read_response().await?;
1048 check_error_bytes(&response)?;
1049 return match response {
1050 McResponseBytes::Stored => Ok(()),
1051 _ => Err(Error::UnexpectedResponse),
1052 };
1053 }
1054
1055 let (_, value_len) = guard.as_ptr_len();
1056 let prefix = encode_set_guard_prefix(key, value_len as usize, flags, exptime);
1057 let tx_bytes = (prefix.len() + value_len as usize + 2) as u32;
1058
1059 let send_ts = self.send_timestamp();
1060 let start = Instant::now();
1061
1062 self.conn.send_parts().build(move |b| {
1063 b.copy(&prefix)
1064 .guard(GuardBox::new(guard))
1065 .copy(b"\r\n")
1066 .submit()
1067 })?;
1068
1069 let response = self.read_response().await;
1070 let latency_ns = self.finish_timing(send_ts, start);
1071 let rx_bytes = self.last_rx_bytes.get();
1072
1073 let result = match response {
1074 Ok(ref r) => {
1075 check_error_bytes(r)?;
1076 match r {
1077 McResponseBytes::Stored => Ok(()),
1078 _ => Err(Error::UnexpectedResponse),
1079 }
1080 }
1081 Err(e) => Err(e),
1082 };
1083 self.record(&CommandResult {
1084 command: CommandType::Set,
1085 latency_ns,
1086 hit: None,
1087 success: result.is_ok(),
1088 ttfb_ns: None,
1089 tx_bytes,
1090 rx_bytes,
1091 });
1092 result
1093 }
1094}
1095
1096fn encode_set_guard_prefix(key: &[u8], value_len: usize, flags: u32, exptime: u32) -> Vec<u8> {
1103 use std::io::Write;
1104 let mut buf = Vec::with_capacity(32 + key.len());
1105 buf.extend_from_slice(b"set ");
1106 buf.extend_from_slice(key);
1107 write!(buf, " {} {} {}\r\n", flags, exptime, value_len).unwrap();
1108 buf
1109}
1110
1111pub(crate) fn encode_request(req: &McRequest<'_>) -> Vec<u8> {
1115 let size = match req {
1116 McRequest::Get { key } => 6 + key.len(),
1117 McRequest::Gets { keys } => 6 + keys.iter().map(|k| 1 + k.len()).sum::<usize>(),
1118 McRequest::Set { key, value, .. } | McRequest::Add { key, value, .. } => {
1119 41 + key.len() + value.len()
1120 }
1121 McRequest::Replace { key, value, .. } => 45 + key.len() + value.len(),
1122 McRequest::Incr { key, .. } | McRequest::Decr { key, .. } => 27 + key.len(),
1123 McRequest::Append { key, value } => 44 + key.len() + value.len(),
1124 McRequest::Prepend { key, value } => 45 + key.len() + value.len(),
1125 McRequest::Cas { key, value, .. } => 61 + key.len() + value.len(),
1126 McRequest::Delete { key } => 9 + key.len(),
1127 McRequest::FlushAll => 11,
1128 McRequest::Version => 9,
1129 McRequest::Quit => 6,
1130 };
1131 let mut buf = vec![0u8; size];
1132 let len = req.encode(&mut buf);
1133 buf.truncate(len);
1134 buf
1135}
1136
1137pub(crate) fn encode_set(key: &[u8], value: &[u8], flags: u32, exptime: u32) -> Vec<u8> {
1139 encode_request(&McRequest::Set {
1140 key,
1141 value,
1142 flags,
1143 exptime,
1144 })
1145}
1146
1147pub(crate) fn encode_add(key: &[u8], value: &[u8]) -> Vec<u8> {
1149 encode_request(&McRequest::Add {
1150 key,
1151 value,
1152 flags: 0,
1153 exptime: 0,
1154 })
1155}
1156
1157pub(crate) fn check_error_bytes(response: &McResponseBytes) -> Result<(), Error> {
1159 match response {
1160 McResponseBytes::Error => Err(Error::Memcache("ERROR".into())),
1161 McResponseBytes::ClientError(msg) => Err(Error::Memcache(format!(
1162 "CLIENT_ERROR {}",
1163 String::from_utf8_lossy(msg)
1164 ))),
1165 McResponseBytes::ServerError(msg) => Err(Error::Memcache(format!(
1166 "SERVER_ERROR {}",
1167 String::from_utf8_lossy(msg)
1168 ))),
1169 _ => Ok(()),
1170 }
1171}
1172
1173#[cfg(feature = "timestamps")]
1176fn now_realtime_ns() -> u64 {
1177 let mut ts = libc::timespec {
1178 tv_sec: 0,
1179 tv_nsec: 0,
1180 };
1181 unsafe {
1182 libc::clock_gettime(libc::CLOCK_REALTIME, &mut ts);
1183 }
1184 ts.tv_sec as u64 * 1_000_000_000 + ts.tv_nsec as u64
1185}