varnish_sys/vcl/backend/
backend_ref.rs1use std::ffi::CStr;
2use std::ptr::null;
3use std::time::SystemTime;
4
5use crate::ffi;
6use crate::ffi::{VCL_BACKEND, VCL_TIME};
7
8#[derive(Debug, Clone, Copy)]
12pub struct ProbeResult {
13 pub healthy: bool,
14 pub last_changed: SystemTime,
15}
16
17#[derive(Debug)]
22pub struct BackendRef {
23 refcounted: bool,
24 bep: VCL_BACKEND,
25}
26
27impl BackendRef {
28 pub unsafe fn new(bep: VCL_BACKEND) -> Option<Self> {
30 if bep.0.is_null() {
31 return None;
32 }
33 unsafe {
34 let dir = bep.0.as_ref()?;
35 assert_eq!(dir.magic, ffi::DIRECTOR_MAGIC);
36 let vdir = dir.vdir.as_mut().expect("vdir can't be null");
37 assert_eq!(vdir.magic, ffi::VCLDIR_MAGIC);
38 if vdir.flags & ffi::VDIR_FLG_NOREFCNT == 0 {
39 ffi::Lck__Lock(
40 &raw mut vdir.dlck,
41 c"BackendRef::new".as_ptr(),
42 line!() as i32,
43 );
44 assert!(vdir.refcnt > 0);
45 vdir.refcnt += 1;
46 ffi::Lck__Unlock(
47 &raw mut vdir.dlck,
48 c"BackendRef::new".as_ptr(),
49 line!() as i32,
50 );
51 }
52 }
53 Some(BackendRef {
54 bep,
55 refcounted: true,
56 })
57 }
58
59 pub(super) unsafe fn new_without_refcount(bep: VCL_BACKEND) -> Option<Self> {
62 if bep.0.is_null() {
63 return None;
64 }
65 Some(BackendRef {
66 bep,
67 refcounted: false,
68 })
69 }
70
71 pub fn probe(&self, ctx: &crate::vcl::Ctx) -> ProbeResult {
73 let mut changed = VCL_TIME::default();
74 let healthy = unsafe { ffi::VRT_Healthy(ctx.raw, self.bep, &raw mut changed).into() };
75 let last_changed = <VCL_TIME as Into<SystemTime>>::into(changed);
76 ProbeResult {
77 healthy,
78 last_changed,
79 }
80 }
81
82 pub fn name(&self) -> &CStr {
84 assert!(!self.bep.0.is_null());
85 unsafe {
86 let dir = *self.bep.0;
87 assert_eq!(dir.magic, ffi::DIRECTOR_MAGIC);
88 CStr::from_ptr(dir.vcl_name)
89 }
90 }
91
92 pub unsafe fn vcl_ptr(&self) -> VCL_BACKEND {
94 self.bep
95 }
96}
97
98impl Clone for BackendRef {
99 fn clone(&self) -> BackendRef {
100 unsafe { BackendRef::new(self.vcl_ptr()).expect("BackendRef vcl_ptr must not be null") }
102 }
103}
104
105impl Drop for BackendRef {
106 fn drop(&mut self) {
107 assert!(!self.bep.0.is_null());
108 if self.refcounted {
109 unsafe {
110 ffi::VRT_Assign_Backend(&raw mut self.bep, VCL_BACKEND(null()));
111 }
112 }
113 }
114}