1pub mod pool;
38pub mod sharded;
39pub use pool::{Pool, PoolConfig};
40pub use sharded::{ShardedClient, ShardedConfig};
41
42use std::collections::VecDeque;
43use std::io;
44use std::time::Instant;
45
46use bytes::Bytes;
47use memcache_proto::{Request as McRequest, ResponseBytes as McResponseBytes};
48use ringline::{ConnCtx, GuardBox, ParseResult, SendGuard};
49
50type ResultCallback = Box<dyn Fn(&CommandResult)>;
52
53#[derive(Debug, thiserror::Error)]
57pub enum Error {
58 #[error("connection closed")]
60 ConnectionClosed,
61
62 #[error("memcache error: {0}")]
64 Memcache(String),
65
66 #[error("unexpected response")]
68 UnexpectedResponse,
69
70 #[error("protocol error: {0}")]
72 Protocol(#[from] memcache_proto::ParseError),
73
74 #[error("io error: {0}")]
76 Io(#[from] io::Error),
77
78 #[error("all connections failed")]
80 AllConnectionsFailed,
81
82 #[error("no pending operations")]
84 NoPending,
85}
86
87#[derive(Debug, Clone)]
91pub struct Value {
92 pub data: Bytes,
94 pub flags: u32,
96}
97
98#[derive(Debug, Clone)]
100pub struct GetValue {
101 pub key: Bytes,
103 pub data: Bytes,
105 pub flags: u32,
107 pub cas: Option<u64>,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum CommandType {
116 Get,
117 Set,
118 Delete,
119 Other,
120}
121
122#[derive(Debug, Clone)]
124pub struct CommandResult {
125 pub command: CommandType,
127 pub latency_ns: u64,
129 pub hit: Option<bool>,
131 pub success: bool,
133 pub ttfb_ns: Option<u64>,
135}
136
137#[cfg(feature = "metrics")]
142pub struct ClientMetrics {
143 pub latency: histogram::Histogram,
145 pub get_latency: histogram::Histogram,
147 pub set_latency: histogram::Histogram,
149 pub del_latency: histogram::Histogram,
151 pub requests: u64,
153 pub errors: u64,
155 pub hits: u64,
157 pub misses: u64,
159}
160
161#[cfg(feature = "metrics")]
162impl ClientMetrics {
163 fn new() -> Self {
164 Self {
165 latency: histogram::Histogram::new(7, 64).unwrap(),
166 get_latency: histogram::Histogram::new(7, 64).unwrap(),
167 set_latency: histogram::Histogram::new(7, 64).unwrap(),
168 del_latency: histogram::Histogram::new(7, 64).unwrap(),
169 requests: 0,
170 errors: 0,
171 hits: 0,
172 misses: 0,
173 }
174 }
175
176 fn record(&mut self, result: &CommandResult) {
177 self.requests += 1;
178 let _ = self.latency.increment(result.latency_ns);
179
180 if !result.success {
181 self.errors += 1;
182 }
183
184 match result.command {
185 CommandType::Get => {
186 let _ = self.get_latency.increment(result.latency_ns);
187 match result.hit {
188 Some(true) => self.hits += 1,
189 Some(false) => self.misses += 1,
190 None => {}
191 }
192 }
193 CommandType::Set => {
194 let _ = self.set_latency.increment(result.latency_ns);
195 }
196 CommandType::Delete => {
197 let _ = self.del_latency.increment(result.latency_ns);
198 }
199 _ => {}
200 }
201 }
202}
203
204enum PendingOpKind {
207 Get,
208 Set,
209 Delete,
210}
211
212struct PendingOp {
213 kind: PendingOpKind,
214 send_ts: u64,
215 start: Option<Instant>,
216 user_data: u64,
217}
218
219pub enum CompletedOp {
221 Get {
223 result: Result<Option<Value>, Error>,
224 user_data: u64,
225 },
226 Set {
228 result: Result<(), Error>,
229 user_data: u64,
230 },
231 Delete {
233 result: Result<bool, Error>,
234 user_data: u64,
235 },
236}
237
238pub struct ClientBuilder {
242 conn: ConnCtx,
243 on_result: Option<ResultCallback>,
244 #[cfg(feature = "timestamps")]
245 use_kernel_ts: bool,
246 #[cfg(feature = "metrics")]
247 with_metrics: bool,
248}
249
250impl ClientBuilder {
251 pub(crate) fn new(conn: ConnCtx) -> Self {
252 Self {
253 conn,
254 on_result: None,
255 #[cfg(feature = "timestamps")]
256 use_kernel_ts: false,
257 #[cfg(feature = "metrics")]
258 with_metrics: false,
259 }
260 }
261
262 pub fn on_result<F: Fn(&CommandResult) + 'static>(mut self, f: F) -> Self {
264 self.on_result = Some(Box::new(f));
265 self
266 }
267
268 #[cfg(feature = "timestamps")]
270 pub fn kernel_timestamps(mut self, enabled: bool) -> Self {
271 self.use_kernel_ts = enabled;
272 self
273 }
274
275 #[cfg(feature = "metrics")]
277 pub fn with_metrics(mut self) -> Self {
278 self.with_metrics = true;
279 self
280 }
281
282 pub fn build(self) -> Client {
284 Client {
285 conn: self.conn,
286 on_result: self.on_result,
287 pending: VecDeque::new(),
288 #[cfg(feature = "timestamps")]
289 use_kernel_ts: self.use_kernel_ts,
290 #[cfg(feature = "metrics")]
291 metrics: if self.with_metrics {
292 Some(ClientMetrics::new())
293 } else {
294 None
295 },
296 }
297 }
298}
299
300pub struct Client {
308 conn: ConnCtx,
309 on_result: Option<ResultCallback>,
310 pending: VecDeque<PendingOp>,
311 #[cfg(feature = "timestamps")]
312 use_kernel_ts: bool,
313 #[cfg(feature = "metrics")]
314 metrics: Option<ClientMetrics>,
315}
316
317impl Client {
318 pub fn new(conn: ConnCtx) -> Self {
322 Self {
323 conn,
324 on_result: None,
325 pending: VecDeque::new(),
326 #[cfg(feature = "timestamps")]
327 use_kernel_ts: false,
328 #[cfg(feature = "metrics")]
329 metrics: None,
330 }
331 }
332
333 pub fn builder(conn: ConnCtx) -> ClientBuilder {
335 ClientBuilder::new(conn)
336 }
337
338 pub fn conn(&self) -> ConnCtx {
340 self.conn
341 }
342
343 #[cfg(feature = "metrics")]
345 pub fn metrics(&self) -> Option<&ClientMetrics> {
346 self.metrics.as_ref()
347 }
348
349 #[cfg(feature = "metrics")]
351 pub fn metrics_mut(&mut self) -> Option<&mut ClientMetrics> {
352 self.metrics.as_mut()
353 }
354
355 #[inline]
358 fn is_instrumented(&self) -> bool {
359 if self.on_result.is_some() {
360 return true;
361 }
362 #[cfg(feature = "metrics")]
363 if self.metrics.is_some() {
364 return true;
365 }
366 false
367 }
368
369 #[cfg(feature = "timestamps")]
370 #[inline]
371 fn send_timestamp(&self) -> u64 {
372 if self.use_kernel_ts {
373 now_realtime_ns()
374 } else {
375 0
376 }
377 }
378
379 #[cfg(not(feature = "timestamps"))]
380 #[inline]
381 fn send_timestamp(&self) -> u64 {
382 0
383 }
384
385 #[cfg(feature = "timestamps")]
386 #[inline]
387 fn finish_timing(&self, send_ts: u64, start: Instant) -> u64 {
388 if self.use_kernel_ts {
389 let recv_ts = self.conn.recv_timestamp();
390 if recv_ts > 0 && recv_ts > send_ts {
391 return recv_ts - send_ts;
392 }
393 }
394 start.elapsed().as_nanos() as u64
395 }
396
397 #[cfg(not(feature = "timestamps"))]
398 #[inline]
399 fn finish_timing(&self, _send_ts: u64, start: Instant) -> u64 {
400 start.elapsed().as_nanos() as u64
401 }
402
403 fn record(&mut self, result: &CommandResult) {
404 if let Some(ref cb) = self.on_result {
405 cb(result);
406 }
407 #[cfg(feature = "metrics")]
408 if let Some(ref mut m) = self.metrics {
409 m.record(result);
410 }
411 }
412
413 #[inline]
416 fn timing_start(&self) -> (u64, Option<Instant>) {
417 if self.is_instrumented() {
418 (self.send_timestamp(), Some(Instant::now()))
419 } else {
420 (0, None)
421 }
422 }
423
424 pub fn pending_count(&self) -> usize {
426 self.pending.len()
427 }
428
429 pub fn fire_get(&mut self, key: &[u8], user_data: u64) -> Result<(), Error> {
431 let encoded = encode_request(&McRequest::get(key));
432 self.conn.send_nowait(&encoded)?;
433 let (send_ts, start) = self.timing_start();
434 self.pending.push_back(PendingOp {
435 kind: PendingOpKind::Get,
436 send_ts,
437 start,
438 user_data,
439 });
440 Ok(())
441 }
442
443 pub fn fire_set(
445 &mut self,
446 key: &[u8],
447 value: &[u8],
448 flags: u32,
449 exptime: u32,
450 user_data: u64,
451 ) -> Result<(), Error> {
452 let encoded = encode_set(key, value, flags, exptime);
453 self.conn.send_nowait(&encoded)?;
454 let (send_ts, start) = self.timing_start();
455 self.pending.push_back(PendingOp {
456 kind: PendingOpKind::Set,
457 send_ts,
458 start,
459 user_data,
460 });
461 Ok(())
462 }
463
464 pub fn fire_set_with_guard<G: SendGuard>(
466 &mut self,
467 key: &[u8],
468 guard: G,
469 flags: u32,
470 exptime: u32,
471 user_data: u64,
472 ) -> Result<(), Error> {
473 let (_, value_len) = guard.as_ptr_len();
474 let prefix = encode_set_guard_prefix(key, value_len as usize, flags, exptime);
475 self.conn.send_parts().build(move |b| {
476 b.copy(&prefix)
477 .guard(GuardBox::new(guard))
478 .copy(b"\r\n")
479 .submit()
480 })?;
481 let (send_ts, start) = self.timing_start();
482 self.pending.push_back(PendingOp {
483 kind: PendingOpKind::Set,
484 send_ts,
485 start,
486 user_data,
487 });
488 Ok(())
489 }
490
491 pub fn fire_delete(&mut self, key: &[u8], user_data: u64) -> Result<(), Error> {
493 let encoded = encode_request(&McRequest::delete(key));
494 self.conn.send_nowait(&encoded)?;
495 let (send_ts, start) = self.timing_start();
496 self.pending.push_back(PendingOp {
497 kind: PendingOpKind::Delete,
498 send_ts,
499 start,
500 user_data,
501 });
502 Ok(())
503 }
504
505 pub async fn recv(&mut self) -> Result<CompletedOp, Error> {
509 let pending = self.pending.pop_front().ok_or(Error::NoPending)?;
510
511 let response = match self.read_response().await {
512 Ok(v) => v,
513 Err(e) => {
514 self.pending.clear();
518 return Err(e);
519 }
520 };
521 let latency_ns = match pending.start {
522 Some(start) => self.finish_timing(pending.send_ts, start),
523 None => 0,
524 };
525
526 let op = match pending.kind {
527 PendingOpKind::Get => {
528 let result = match check_error_bytes(&response) {
530 Err(e) => Err(e),
531 Ok(()) => match response {
532 McResponseBytes::Values(mut values) => {
533 if values.is_empty() {
534 Ok(None)
535 } else {
536 let v = values.swap_remove(0);
537 Ok(Some(Value {
538 data: v.data,
539 flags: v.flags,
540 }))
541 }
542 }
543 _ => Err(Error::UnexpectedResponse),
544 },
545 };
546 let (success, hit) = match &result {
547 Ok(Some(_)) => (true, Some(true)),
548 Ok(None) => (true, Some(false)),
549 Err(_) => (false, None),
550 };
551 self.record(&CommandResult {
552 command: CommandType::Get,
553 latency_ns,
554 hit,
555 success,
556 ttfb_ns: None,
557 });
558 CompletedOp::Get {
559 result,
560 user_data: pending.user_data,
561 }
562 }
563 PendingOpKind::Set => {
564 let result = match check_error_bytes(&response) {
565 Err(e) => Err(e),
566 Ok(()) => match response {
567 McResponseBytes::Stored => Ok(()),
568 _ => Err(Error::UnexpectedResponse),
569 },
570 };
571 self.record(&CommandResult {
572 command: CommandType::Set,
573 latency_ns,
574 hit: None,
575 success: result.is_ok(),
576 ttfb_ns: None,
577 });
578 CompletedOp::Set {
579 result,
580 user_data: pending.user_data,
581 }
582 }
583 PendingOpKind::Delete => {
584 let result = match check_error_bytes(&response) {
585 Err(e) => Err(e),
586 Ok(()) => match response {
587 McResponseBytes::Deleted => Ok(true),
588 McResponseBytes::NotFound => Ok(false),
589 _ => Err(Error::UnexpectedResponse),
590 },
591 };
592 self.record(&CommandResult {
593 command: CommandType::Delete,
594 latency_ns,
595 hit: None,
596 success: result.is_ok(),
597 ttfb_ns: None,
598 });
599 CompletedOp::Delete {
600 result,
601 user_data: pending.user_data,
602 }
603 }
604 };
605
606 Ok(op)
607 }
608
609 pub(crate) async fn read_response(&self) -> Result<McResponseBytes, Error> {
617 let mut result: Option<Result<McResponseBytes, Error>> = None;
618 let n = self
619 .conn
620 .with_bytes(|bytes| {
621 let len = bytes.len();
622 match McResponseBytes::parse(bytes) {
623 Ok((response, consumed)) => {
624 result = Some(Ok(response));
625 ParseResult::Consumed(consumed)
626 }
627 Err(e) if e.is_incomplete() => ParseResult::Consumed(0),
628 Err(e) => {
629 result = Some(Err(Error::Protocol(e)));
630 ParseResult::Consumed(len)
631 }
632 }
633 })
634 .await;
635 if n == 0 {
636 return result.unwrap_or(Err(Error::ConnectionClosed));
637 }
638 result.unwrap()
639 }
640
641 async fn execute(&self, encoded: &[u8]) -> Result<McResponseBytes, Error> {
644 self.conn.send(encoded)?;
645 let response = self.read_response().await?;
646 check_error_bytes(&response)?;
647 Ok(response)
648 }
649
650 pub async fn get(&mut self, key: impl AsRef<[u8]>) -> Result<Option<Value>, Error> {
654 let key = key.as_ref();
655 let encoded = encode_request(&McRequest::get(key));
656
657 if !self.is_instrumented() {
658 let response = self.execute(&encoded).await?;
659 return match response {
660 McResponseBytes::Values(mut values) => {
661 if values.is_empty() {
662 Ok(None)
663 } else {
664 let v = values.swap_remove(0);
665 Ok(Some(Value {
666 data: v.data,
667 flags: v.flags,
668 }))
669 }
670 }
671 _ => Err(Error::UnexpectedResponse),
672 };
673 }
674
675 let send_ts = self.send_timestamp();
676 let start = Instant::now();
677 let response = self.execute(&encoded).await;
678 let latency_ns = self.finish_timing(send_ts, start);
679
680 let result = match response {
681 Ok(McResponseBytes::Values(mut values)) => {
682 if values.is_empty() {
683 Ok(None)
684 } else {
685 let v = values.swap_remove(0);
686 Ok(Some(Value {
687 data: v.data,
688 flags: v.flags,
689 }))
690 }
691 }
692 Ok(_) => Err(Error::UnexpectedResponse),
693 Err(e) => Err(e),
694 };
695
696 let (success, hit) = match &result {
697 Ok(Some(_)) => (true, Some(true)),
698 Ok(None) => (true, Some(false)),
699 Err(_) => (false, None),
700 };
701 self.record(&CommandResult {
702 command: CommandType::Get,
703 latency_ns,
704 hit,
705 success,
706 ttfb_ns: None,
707 });
708 result
709 }
710
711 pub async fn gets(&mut self, keys: &[&[u8]]) -> Result<Vec<GetValue>, Error> {
713 if keys.is_empty() {
714 return Ok(Vec::new());
715 }
716 let encoded = encode_request(&McRequest::gets(keys));
717 let response = self.execute(&encoded).await?;
718 match response {
719 McResponseBytes::Values(values) => Ok(values
720 .into_iter()
721 .map(|v| GetValue {
722 key: v.key,
723 data: v.data,
724 flags: v.flags,
725 cas: v.cas,
726 })
727 .collect()),
728 _ => Err(Error::UnexpectedResponse),
729 }
730 }
731
732 pub async fn set(
734 &mut self,
735 key: impl AsRef<[u8]>,
736 value: impl AsRef<[u8]>,
737 ) -> Result<(), Error> {
738 self.set_with_options(key, value, 0, 0).await
739 }
740
741 pub async fn set_with_options(
743 &mut self,
744 key: impl AsRef<[u8]>,
745 value: impl AsRef<[u8]>,
746 flags: u32,
747 exptime: u32,
748 ) -> Result<(), Error> {
749 let key = key.as_ref();
750 let value = value.as_ref();
751 let encoded = encode_set(key, value, flags, exptime);
752
753 if !self.is_instrumented() {
754 let response = self.execute(&encoded).await?;
755 return match response {
756 McResponseBytes::Stored => Ok(()),
757 _ => Err(Error::UnexpectedResponse),
758 };
759 }
760
761 let send_ts = self.send_timestamp();
762 let start = Instant::now();
763 let response = self.execute(&encoded).await;
764 let latency_ns = self.finish_timing(send_ts, start);
765
766 let result = match response {
767 Ok(McResponseBytes::Stored) => Ok(()),
768 Ok(_) => Err(Error::UnexpectedResponse),
769 Err(e) => Err(e),
770 };
771 self.record(&CommandResult {
772 command: CommandType::Set,
773 latency_ns,
774 hit: None,
775 success: result.is_ok(),
776 ttfb_ns: None,
777 });
778 result
779 }
780
781 pub async fn add(
784 &mut self,
785 key: impl AsRef<[u8]>,
786 value: impl AsRef<[u8]>,
787 ) -> Result<bool, Error> {
788 let key = key.as_ref();
789 let value = value.as_ref();
790 let encoded = encode_add(key, value);
791 let response = self.execute(&encoded).await?;
792 match response {
793 McResponseBytes::Stored => Ok(true),
794 McResponseBytes::NotStored => Ok(false),
795 _ => Err(Error::UnexpectedResponse),
796 }
797 }
798
799 pub async fn replace(
802 &mut self,
803 key: impl AsRef<[u8]>,
804 value: impl AsRef<[u8]>,
805 ) -> Result<bool, Error> {
806 let key = key.as_ref();
807 let value = value.as_ref();
808 let encoded = encode_request(&McRequest::Replace {
809 key,
810 value,
811 flags: 0,
812 exptime: 0,
813 });
814 let response = self.execute(&encoded).await?;
815 match response {
816 McResponseBytes::Stored => Ok(true),
817 McResponseBytes::NotStored => Ok(false),
818 _ => Err(Error::UnexpectedResponse),
819 }
820 }
821
822 pub async fn incr(&mut self, key: impl AsRef<[u8]>, delta: u64) -> Result<Option<u64>, Error> {
825 let key = key.as_ref();
826 let encoded = encode_request(&McRequest::incr(key, delta));
827 let response = self.execute(&encoded).await?;
828 match response {
829 McResponseBytes::Numeric(val) => Ok(Some(val)),
830 McResponseBytes::NotFound => Ok(None),
831 _ => Err(Error::UnexpectedResponse),
832 }
833 }
834
835 pub async fn decr(&mut self, key: impl AsRef<[u8]>, delta: u64) -> Result<Option<u64>, Error> {
838 let key = key.as_ref();
839 let encoded = encode_request(&McRequest::decr(key, delta));
840 let response = self.execute(&encoded).await?;
841 match response {
842 McResponseBytes::Numeric(val) => Ok(Some(val)),
843 McResponseBytes::NotFound => Ok(None),
844 _ => Err(Error::UnexpectedResponse),
845 }
846 }
847
848 pub async fn append(
851 &mut self,
852 key: impl AsRef<[u8]>,
853 value: impl AsRef<[u8]>,
854 ) -> Result<bool, Error> {
855 let key = key.as_ref();
856 let value = value.as_ref();
857 let encoded = encode_request(&McRequest::append(key, value));
858 let response = self.execute(&encoded).await?;
859 match response {
860 McResponseBytes::Stored => Ok(true),
861 McResponseBytes::NotStored => Ok(false),
862 _ => Err(Error::UnexpectedResponse),
863 }
864 }
865
866 pub async fn prepend(
869 &mut self,
870 key: impl AsRef<[u8]>,
871 value: impl AsRef<[u8]>,
872 ) -> Result<bool, Error> {
873 let key = key.as_ref();
874 let value = value.as_ref();
875 let encoded = encode_request(&McRequest::prepend(key, value));
876 let response = self.execute(&encoded).await?;
877 match response {
878 McResponseBytes::Stored => Ok(true),
879 McResponseBytes::NotStored => Ok(false),
880 _ => Err(Error::UnexpectedResponse),
881 }
882 }
883
884 pub async fn cas(
888 &mut self,
889 key: impl AsRef<[u8]>,
890 value: impl AsRef<[u8]>,
891 cas_unique: u64,
892 ) -> Result<bool, Error> {
893 let key = key.as_ref();
894 let value = value.as_ref();
895 let encoded = encode_request(&McRequest::cas(key, value, cas_unique));
896 let response = self.execute(&encoded).await?;
897 match response {
898 McResponseBytes::Stored => Ok(true),
899 McResponseBytes::Exists => Ok(false),
900 McResponseBytes::NotFound => Err(Error::Memcache("NOT_FOUND".into())),
901 _ => Err(Error::UnexpectedResponse),
902 }
903 }
904
905 pub async fn delete(&mut self, key: impl AsRef<[u8]>) -> Result<bool, Error> {
907 let key = key.as_ref();
908 let encoded = encode_request(&McRequest::delete(key));
909
910 if !self.is_instrumented() {
911 let response = self.execute(&encoded).await?;
912 return match response {
913 McResponseBytes::Deleted => Ok(true),
914 McResponseBytes::NotFound => Ok(false),
915 _ => Err(Error::UnexpectedResponse),
916 };
917 }
918
919 let send_ts = self.send_timestamp();
920 let start = Instant::now();
921 let response = self.execute(&encoded).await;
922 let latency_ns = self.finish_timing(send_ts, start);
923
924 let result = match response {
925 Ok(McResponseBytes::Deleted) => Ok(true),
926 Ok(McResponseBytes::NotFound) => Ok(false),
927 Ok(_) => Err(Error::UnexpectedResponse),
928 Err(e) => Err(e),
929 };
930 self.record(&CommandResult {
931 command: CommandType::Delete,
932 latency_ns,
933 hit: None,
934 success: result.is_ok(),
935 ttfb_ns: None,
936 });
937 result
938 }
939
940 pub async fn flush_all(&mut self) -> Result<(), Error> {
942 let encoded = encode_request(&McRequest::flush_all());
943 let response = self.execute(&encoded).await?;
944 match response {
945 McResponseBytes::Ok => Ok(()),
946 _ => Err(Error::UnexpectedResponse),
947 }
948 }
949
950 pub async fn version(&mut self) -> Result<String, Error> {
952 let encoded = encode_request(&McRequest::version());
953 let response = self.execute(&encoded).await?;
954 match response {
955 McResponseBytes::Version(v) => Ok(String::from_utf8_lossy(&v).into_owned()),
956 _ => Err(Error::UnexpectedResponse),
957 }
958 }
959
960 pub async fn set_with_guard<G: SendGuard>(
965 &mut self,
966 key: &[u8],
967 guard: G,
968 flags: u32,
969 exptime: u32,
970 ) -> Result<(), Error> {
971 if !self.is_instrumented() {
972 let (_, value_len) = guard.as_ptr_len();
973 let prefix = encode_set_guard_prefix(key, value_len as usize, flags, exptime);
974
975 self.conn.send_parts().build(move |b| {
976 b.copy(&prefix)
977 .guard(GuardBox::new(guard))
978 .copy(b"\r\n")
979 .submit()
980 })?;
981
982 let response = self.read_response().await?;
983 check_error_bytes(&response)?;
984 return match response {
985 McResponseBytes::Stored => Ok(()),
986 _ => Err(Error::UnexpectedResponse),
987 };
988 }
989
990 let send_ts = self.send_timestamp();
991 let start = Instant::now();
992
993 let (_, value_len) = guard.as_ptr_len();
994 let prefix = encode_set_guard_prefix(key, value_len as usize, flags, exptime);
995
996 self.conn.send_parts().build(move |b| {
997 b.copy(&prefix)
998 .guard(GuardBox::new(guard))
999 .copy(b"\r\n")
1000 .submit()
1001 })?;
1002
1003 let response = self.read_response().await;
1004 let latency_ns = self.finish_timing(send_ts, start);
1005
1006 let result = match response {
1007 Ok(ref r) => {
1008 check_error_bytes(r)?;
1009 match r {
1010 McResponseBytes::Stored => Ok(()),
1011 _ => Err(Error::UnexpectedResponse),
1012 }
1013 }
1014 Err(e) => Err(e),
1015 };
1016 self.record(&CommandResult {
1017 command: CommandType::Set,
1018 latency_ns,
1019 hit: None,
1020 success: result.is_ok(),
1021 ttfb_ns: None,
1022 });
1023 result
1024 }
1025}
1026
1027fn encode_set_guard_prefix(key: &[u8], value_len: usize, flags: u32, exptime: u32) -> Vec<u8> {
1034 use std::io::Write;
1035 let mut buf = Vec::with_capacity(32 + key.len());
1036 buf.extend_from_slice(b"set ");
1037 buf.extend_from_slice(key);
1038 write!(buf, " {} {} {}\r\n", flags, exptime, value_len).unwrap();
1039 buf
1040}
1041
1042pub(crate) fn encode_request(req: &McRequest<'_>) -> Vec<u8> {
1046 let size = match req {
1047 McRequest::Get { key } => 6 + key.len(),
1048 McRequest::Gets { keys } => 6 + keys.iter().map(|k| 1 + k.len()).sum::<usize>(),
1049 McRequest::Set { key, value, .. } | McRequest::Add { key, value, .. } => {
1050 41 + key.len() + value.len()
1051 }
1052 McRequest::Replace { key, value, .. } => 45 + key.len() + value.len(),
1053 McRequest::Incr { key, .. } | McRequest::Decr { key, .. } => 27 + key.len(),
1054 McRequest::Append { key, value } => 44 + key.len() + value.len(),
1055 McRequest::Prepend { key, value } => 45 + key.len() + value.len(),
1056 McRequest::Cas { key, value, .. } => 61 + key.len() + value.len(),
1057 McRequest::Delete { key } => 9 + key.len(),
1058 McRequest::FlushAll => 11,
1059 McRequest::Version => 9,
1060 McRequest::Quit => 6,
1061 };
1062 let mut buf = vec![0u8; size];
1063 let len = req.encode(&mut buf);
1064 buf.truncate(len);
1065 buf
1066}
1067
1068pub(crate) fn encode_set(key: &[u8], value: &[u8], flags: u32, exptime: u32) -> Vec<u8> {
1070 encode_request(&McRequest::Set {
1071 key,
1072 value,
1073 flags,
1074 exptime,
1075 })
1076}
1077
1078pub(crate) fn encode_add(key: &[u8], value: &[u8]) -> Vec<u8> {
1080 encode_request(&McRequest::Add {
1081 key,
1082 value,
1083 flags: 0,
1084 exptime: 0,
1085 })
1086}
1087
1088pub(crate) fn check_error_bytes(response: &McResponseBytes) -> Result<(), Error> {
1090 match response {
1091 McResponseBytes::Error => Err(Error::Memcache("ERROR".into())),
1092 McResponseBytes::ClientError(msg) => Err(Error::Memcache(format!(
1093 "CLIENT_ERROR {}",
1094 String::from_utf8_lossy(msg)
1095 ))),
1096 McResponseBytes::ServerError(msg) => Err(Error::Memcache(format!(
1097 "SERVER_ERROR {}",
1098 String::from_utf8_lossy(msg)
1099 ))),
1100 _ => Ok(()),
1101 }
1102}
1103
1104#[cfg(feature = "timestamps")]
1107fn now_realtime_ns() -> u64 {
1108 let mut ts = libc::timespec {
1109 tv_sec: 0,
1110 tv_nsec: 0,
1111 };
1112 unsafe {
1113 libc::clock_gettime(libc::CLOCK_REALTIME, &mut ts);
1114 }
1115 ts.tv_sec as u64 * 1_000_000_000 + ts.tv_nsec as u64
1116}