12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- use std:: { num:: NonZeroUsize , sync:: RwLock as StdRwLock } ;
15
+ use std:: {
16
+ collections:: { hash_map:: Entry , HashMap } ,
17
+ num:: NonZeroUsize ,
18
+ sync:: RwLock as StdRwLock ,
19
+ time:: { Duration , Instant } ,
20
+ } ;
16
21
17
22
use async_trait:: async_trait;
18
23
use matrix_sdk_common:: ring_buffer:: RingBuffer ;
@@ -28,14 +33,18 @@ use crate::media::{MediaRequest, UniqueKey as _};
28
33
#[ derive( Debug ) ]
29
34
pub struct MemoryStore {
30
35
media : StdRwLock < RingBuffer < ( OwnedMxcUri , String /* unique key */ , Vec < u8 > ) > > ,
36
+ leases : StdRwLock < HashMap < String , ( String , Instant ) > > ,
31
37
}
32
38
33
39
// SAFETY: `new_unchecked` is safe because 20 is not zero.
34
40
const NUMBER_OF_MEDIAS : NonZeroUsize = unsafe { NonZeroUsize :: new_unchecked ( 20 ) } ;
35
41
36
42
impl Default for MemoryStore {
37
43
fn default ( ) -> Self {
38
- Self { media : StdRwLock :: new ( RingBuffer :: new ( NUMBER_OF_MEDIAS ) ) }
44
+ Self {
45
+ media : StdRwLock :: new ( RingBuffer :: new ( NUMBER_OF_MEDIAS ) ) ,
46
+ leases : Default :: default ( ) ,
47
+ }
39
48
}
40
49
}
41
50
@@ -57,7 +66,44 @@ impl EventCacheStore for MemoryStore {
57
66
key : & str ,
58
67
holder : & str ,
59
68
) -> Result < bool , Self :: Error > {
60
- todo ! ( )
69
+ let now = Instant :: now ( ) ;
70
+ let expiration = now + Duration :: from_millis ( lease_duration_ms. into ( ) ) ;
71
+
72
+ match self . leases . write ( ) . unwrap ( ) . entry ( key. to_owned ( ) ) {
73
+ // There is an existing holder.
74
+ Entry :: Occupied ( mut entry) => {
75
+ let ( current_holder, current_expiration) = entry. get_mut ( ) ;
76
+
77
+ if current_holder == holder {
78
+ // We had the lease before, extend it.
79
+ * current_expiration = expiration;
80
+
81
+ Ok ( true )
82
+ } else {
83
+ // We didn't have it.
84
+ if * current_expiration < now {
85
+ // Steal it!
86
+ * current_holder = holder. to_owned ( ) ;
87
+ * current_expiration = expiration;
88
+
89
+ Ok ( true )
90
+ } else {
91
+ // We tried our best.
92
+ Ok ( false )
93
+ }
94
+ }
95
+ }
96
+
97
+ // There is no holder, easy.
98
+ Entry :: Vacant ( entry) => {
99
+ entry. insert ( (
100
+ holder. to_owned ( ) ,
101
+ Instant :: now ( ) + Duration :: from_millis ( lease_duration_ms. into ( ) ) ,
102
+ ) ) ;
103
+
104
+ Ok ( true )
105
+ }
106
+ }
61
107
}
62
108
63
109
async fn add_media_content ( & self , request : & MediaRequest , data : Vec < u8 > ) -> Result < ( ) > {
0 commit comments