Skip to main content

ri/java/classes/
cache.rs

1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//!     http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18//! # Cache Module JNI Bindings
19//!
20//! JNI bindings for Ri cache classes.
21
22use jni::JNIEnv;
23use jni::objects::{JClass, JString};
24use jni::sys::{jlong, jboolean, jint, jstring};
25use crate::cache::{RiCacheModule, RiCacheConfig, RiCacheBackendType, RiCacheStats, RiCachePolicy, RiCachedValue, RiCacheManager};
26use crate::java::exception::check_not_null;
27use crate::java::runtime::{block_on_jni, ttl_from_jlong};
28
29// =============================================================================
30// RiCacheModule JNI Bindings
31// =============================================================================
32
33#[no_mangle]
34pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheModule_new0(
35    _env: JNIEnv,
36    _class: JClass,
37    config_ptr: jlong,
38) -> jlong {
39    if config_ptr == 0 {
40        return 0;
41    }
42    let config = unsafe { &*(config_ptr as *const RiCacheConfig) };
43    let module = Box::new(RiCacheModule::with_config(config.clone()));
44    Box::into_raw(module) as jlong
45}
46
47#[no_mangle]
48pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheModule_set0(
49    mut env: JNIEnv,
50    _class: JClass,
51    ptr: jlong,
52    key: JString,
53    value: JString,
54    ttl_secs: jlong,
55) {
56    if !check_not_null(&mut env, ptr, "RiCacheModule") {
57        return;
58    }
59    let key_str: String = match env.get_string(&key) {
60        Ok(s) => s.into(),
61        Err(_) => return,
62    };
63    let value_str: String = match env.get_string(&value) {
64        Ok(s) => s.into(),
65        Err(_) => return,
66    };
67
68    let module = unsafe { &*(ptr as *const RiCacheModule) };
69    let manager = module.cache_manager();
70    let ttl = ttl_from_jlong(ttl_secs);
71    if let Some(_) = block_on_jni(&mut env, "RiCacheModule::set", async move {
72        let mgr = manager.read().await;
73        mgr.set::<String>(&key_str, &value_str, ttl).await
74    }) {
75        // Ok(()) -> success; Err was already converted to a Java exception.
76    }
77}
78
79#[no_mangle]
80pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheModule_get0(
81    mut env: JNIEnv,
82    _class: JClass,
83    ptr: jlong,
84    key: JString,
85) -> jstring {
86    if !check_not_null(&mut env, ptr, "RiCacheModule") {
87        return std::ptr::null_mut();
88    }
89    let key_str: String = match env.get_string(&key) {
90        Ok(s) => s.into(),
91        Err(_) => return std::ptr::null_mut(),
92    };
93
94    let module = unsafe { &*(ptr as *const RiCacheModule) };
95    let manager = module.cache_manager();
96    let result = block_on_jni(&mut env, "RiCacheModule::get", async move {
97        let mgr = manager.read().await;
98        mgr.get::<String>(&key_str).await
99    });
100
101    match result {
102        Some(Ok(Some(value))) => match env.new_string(value) {
103            Ok(s) => s.into_raw(),
104            Err(_) => std::ptr::null_mut(),
105        },
106        Some(Ok(None)) => std::ptr::null_mut(),
107        Some(Err(_)) => {
108            // Error already surfaced as a Java exception.
109            std::ptr::null_mut()
110        }
111        None => std::ptr::null_mut(),
112    }
113}
114
115#[no_mangle]
116pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheModule_delete0(
117    mut env: JNIEnv,
118    _class: JClass,
119    ptr: jlong,
120    key: JString,
121) {
122    if !check_not_null(&mut env, ptr, "RiCacheModule") {
123        return;
124    }
125    let key_str: String = match env.get_string(&key) {
126        Ok(s) => s.into(),
127        Err(_) => return,
128    };
129
130    let module = unsafe { &*(ptr as *const RiCacheModule) };
131    let manager = module.cache_manager();
132    if let Some(result) = block_on_jni(&mut env, "RiCacheModule::delete", async move {
133        let mgr = manager.read().await;
134        mgr.delete(&key_str).await
135    }) {
136        let _ = result;
137    }
138}
139
140#[no_mangle]
141pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheModule_exists0(
142    mut env: JNIEnv,
143    _class: JClass,
144    ptr: jlong,
145    key: JString,
146) -> jboolean {
147    if !check_not_null(&mut env, ptr, "RiCacheModule") {
148        return 0;
149    }
150    let key_str: String = match env.get_string(&key) {
151        Ok(s) => s.into(),
152        Err(_) => return 0,
153    };
154
155    let module = unsafe { &*(ptr as *const RiCacheModule) };
156    let manager = module.cache_manager();
157    match block_on_jni(&mut env, "RiCacheModule::exists", async move {
158        let mgr = manager.read().await;
159        mgr.exists(&key_str).await
160    }) {
161        Some(exists) => if exists { 1 } else { 0 },
162        None => 0,
163    }
164}
165
166#[no_mangle]
167pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheModule_getStats0(
168    mut env: JNIEnv,
169    _class: JClass,
170    ptr: jlong,
171) -> jlong {
172    if !check_not_null(&mut env, ptr, "RiCacheModule") {
173        return 0;
174    }
175
176    let module = unsafe { &*(ptr as *const RiCacheModule) };
177    let manager = module.cache_manager();
178    match block_on_jni(&mut env, "RiCacheModule::getStats", async move {
179        let mgr = manager.read().await;
180        mgr.stats().await
181    }) {
182        Some(stats) => Box::into_raw(Box::new(stats)) as jlong,
183        None => 0,
184    }
185}
186
187#[no_mangle]
188pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheModule_free0(
189    _env: JNIEnv,
190    _class: JClass,
191    ptr: jlong,
192) {
193    if ptr != 0 {
194        unsafe {
195            let _ = Box::from_raw(ptr as *mut RiCacheModule);
196        }
197    }
198}
199
200// =============================================================================
201// RiCacheConfig JNI Bindings
202// =============================================================================
203
204#[no_mangle]
205pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheConfig_new0(
206    _env: JNIEnv,
207    _class: JClass,
208) -> jlong {
209    let config = Box::new(RiCacheConfig::default());
210    Box::into_raw(config) as jlong
211}
212
213#[no_mangle]
214pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheConfig_setEnabled0(
215    mut env: JNIEnv,
216    _class: JClass,
217    ptr: jlong,
218    enabled: jboolean,
219) {
220    if !check_not_null(&mut env, ptr, "RiCacheConfig") {
221        return;
222    }
223    
224    let config = unsafe { &mut *(ptr as *mut RiCacheConfig) };
225    config.enabled = enabled != 0;
226}
227
228#[no_mangle]
229pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheConfig_setDefaultTtlSecs0(
230    mut env: JNIEnv,
231    _class: JClass,
232    ptr: jlong,
233    ttl: jlong,
234) {
235    if !check_not_null(&mut env, ptr, "RiCacheConfig") {
236        return;
237    }
238
239    let config = unsafe { &mut *(ptr as *mut RiCacheConfig) };
240    config.default_ttl_secs = if ttl >= 0 { ttl as u64 } else { 0 };
241}
242
243#[no_mangle]
244pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheConfig_setBackendType0(
245    mut env: JNIEnv,
246    _class: JClass,
247    ptr: jlong,
248    backend_type: jint,
249) {
250    if !check_not_null(&mut env, ptr, "RiCacheConfig") {
251        return;
252    }
253    
254    let config = unsafe { &mut *(ptr as *mut RiCacheConfig) };
255    config.backend_type = match backend_type {
256        0 => RiCacheBackendType::Memory,
257        1 => RiCacheBackendType::Redis,
258        2 => RiCacheBackendType::Hybrid,
259        _ => RiCacheBackendType::Memory,
260    };
261}
262
263#[no_mangle]
264pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheConfig_setRedisUrl0(
265    mut env: JNIEnv,
266    _class: JClass,
267    ptr: jlong,
268    url: JString,
269) {
270    if !check_not_null(&mut env, ptr, "RiCacheConfig") {
271        return;
272    }
273
274    let url_str: String = match env.get_string(&url) {
275        Ok(s) => s.into(),
276        Err(_) => return,
277    };
278
279    let config = unsafe { &mut *(ptr as *mut RiCacheConfig) };
280    config.redis_url = url_str;
281}
282
283#[no_mangle]
284pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheConfig_free0(
285    _env: JNIEnv,
286    _class: JClass,
287    ptr: jlong,
288) {
289    if ptr != 0 {
290        unsafe {
291            let _ = Box::from_raw(ptr as *mut RiCacheConfig);
292        }
293    }
294}
295
296// =============================================================================
297// RiCacheStats JNI Bindings
298// =============================================================================
299
300#[no_mangle]
301pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheStats_getHits0(
302    mut env: JNIEnv,
303    _class: JClass,
304    ptr: jlong,
305) -> jlong {
306    if !check_not_null(&mut env, ptr, "RiCacheStats") {
307        return 0;
308    }
309    
310    let stats = unsafe { &*(ptr as *const RiCacheStats) };
311    stats.hits as jlong
312}
313
314#[no_mangle]
315pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheStats_getMisses0(
316    mut env: JNIEnv,
317    _class: JClass,
318    ptr: jlong,
319) -> jlong {
320    if !check_not_null(&mut env, ptr, "RiCacheStats") {
321        return 0;
322    }
323    
324    let stats = unsafe { &*(ptr as *const RiCacheStats) };
325    stats.misses as jlong
326}
327
328#[no_mangle]
329pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheStats_free0(
330    _env: JNIEnv,
331    _class: JClass,
332    ptr: jlong,
333) {
334    if ptr != 0 {
335        unsafe {
336            let _ = Box::from_raw(ptr as *mut RiCacheStats);
337        }
338    }
339}
340
341// =============================================================================
342// RiCachePolicy JNI Bindings
343// =============================================================================
344
345#[no_mangle]
346pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_new0(
347    _env: JNIEnv,
348    _class: JClass,
349) -> jlong {
350    let policy = Box::new(RiCachePolicy::default());
351    Box::into_raw(policy) as jlong
352}
353
354#[no_mangle]
355pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_setTtlSecs0(
356    mut env: JNIEnv,
357    _class: JClass,
358    ptr: jlong,
359    ttl_secs: jlong,
360) {
361    if !check_not_null(&mut env, ptr, "RiCachePolicy") {
362        return;
363    }
364    
365    let policy = unsafe { &mut *(ptr as *mut RiCachePolicy) };
366    policy.ttl = if ttl_secs >= 0 {
367        Some(std::time::Duration::from_secs(ttl_secs as u64))
368    } else {
369        None
370    };
371}
372
373#[no_mangle]
374pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_getTtlSecs0(
375    mut env: JNIEnv,
376    _class: JClass,
377    ptr: jlong,
378) -> jlong {
379    if !check_not_null(&mut env, ptr, "RiCachePolicy") {
380        return -1;
381    }
382    
383    let policy = unsafe { &*(ptr as *const RiCachePolicy) };
384    policy.ttl.map(|d| d.as_secs() as jlong).unwrap_or(-1)
385}
386
387#[no_mangle]
388pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_setRefreshOnAccess0(
389    mut env: JNIEnv,
390    _class: JClass,
391    ptr: jlong,
392    refresh_on_access: jboolean,
393) {
394    if !check_not_null(&mut env, ptr, "RiCachePolicy") {
395        return;
396    }
397    
398    let policy = unsafe { &mut *(ptr as *mut RiCachePolicy) };
399    policy.refresh_on_access = refresh_on_access != 0;
400}
401
402#[no_mangle]
403pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_getRefreshOnAccess0(
404    mut env: JNIEnv,
405    _class: JClass,
406    ptr: jlong,
407) -> jboolean {
408    if !check_not_null(&mut env, ptr, "RiCachePolicy") {
409        return 0;
410    }
411    
412    let policy = unsafe { &*(ptr as *const RiCachePolicy) };
413    if policy.refresh_on_access { 1 } else { 0 }
414}
415
416#[no_mangle]
417pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_setMaxSize0(
418    mut env: JNIEnv,
419    _class: JClass,
420    ptr: jlong,
421    max_size: jlong,
422) {
423    if !check_not_null(&mut env, ptr, "RiCachePolicy") {
424        return;
425    }
426    
427    let policy = unsafe { &mut *(ptr as *mut RiCachePolicy) };
428    policy.max_size = if max_size >= 0 {
429        Some(max_size as usize)
430    } else {
431        None
432    };
433}
434
435#[no_mangle]
436pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_getMaxSize0(
437    mut env: JNIEnv,
438    _class: JClass,
439    ptr: jlong,
440) -> jlong {
441    if !check_not_null(&mut env, ptr, "RiCachePolicy") {
442        return -1;
443    }
444    
445    let policy = unsafe { &*(ptr as *const RiCachePolicy) };
446    policy.max_size.map(|s| s as jlong).unwrap_or(-1)
447}
448
449#[no_mangle]
450pub extern "system" fn Java_com_dunimd_ri_cache_RiCachePolicy_free0(
451    _env: JNIEnv,
452    _class: JClass,
453    ptr: jlong,
454) {
455    if ptr != 0 {
456        unsafe {
457            let _ = Box::from_raw(ptr as *mut RiCachePolicy);
458        }
459    }
460}
461
462// =============================================================================
463// RiCachedValue JNI Bindings
464// =============================================================================
465
466#[no_mangle]
467pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_new0(
468    mut env: JNIEnv,
469    _class: JClass,
470    value: JString,
471    ttl_secs: jlong,
472) -> jlong {
473    let value_str: String = match env.get_string(&value) {
474        Ok(s) => s.into(),
475        Err(_) => {
476            crate::java::exception::throw_ri_error(&mut env, "Failed to get value");
477            return 0;
478        }
479    };
480    
481    let ttl = if ttl_secs >= 0 { Some(ttl_secs as u64) } else { None };
482    let cached_value = Box::new(RiCachedValue::new(value_str, ttl));
483    Box::into_raw(cached_value) as jlong
484}
485
486#[no_mangle]
487pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_getValue0(
488    mut env: JNIEnv,
489    _class: JClass,
490    ptr: jlong,
491) -> jstring {
492    if !check_not_null(&mut env, ptr, "RiCachedValue") {
493        return std::ptr::null_mut();
494    }
495    
496    let cached_value = unsafe { &*(ptr as *const RiCachedValue) };
497    match env.new_string(&cached_value.value) {
498            Ok(s) => s.into_raw(),
499            Err(_) => std::ptr::null_mut(),
500        }
501}
502
503#[no_mangle]
504pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_getExpiresAt0(
505    mut env: JNIEnv,
506    _class: JClass,
507    ptr: jlong,
508) -> jlong {
509    if !check_not_null(&mut env, ptr, "RiCachedValue") {
510        return -1;
511    }
512    
513    let cached_value = unsafe { &*(ptr as *const RiCachedValue) };
514    cached_value.expires_at.unwrap_or(0) as jlong
515}
516
517#[no_mangle]
518pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_getLastAccessed0(
519    mut env: JNIEnv,
520    _class: JClass,
521    ptr: jlong,
522) -> jlong {
523    if !check_not_null(&mut env, ptr, "RiCachedValue") {
524        return -1;
525    }
526    
527    let cached_value = unsafe { &*(ptr as *const RiCachedValue) };
528    cached_value.last_accessed.unwrap_or(0) as jlong
529}
530
531#[no_mangle]
532pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_isExpired0(
533    mut env: JNIEnv,
534    _class: JClass,
535    ptr: jlong,
536) -> jboolean {
537    if !check_not_null(&mut env, ptr, "RiCachedValue") {
538        return 0;
539    }
540    
541    let cached_value = unsafe { &*(ptr as *const RiCachedValue) };
542    if cached_value.is_expired() { 1 } else { 0 }
543}
544
545#[no_mangle]
546pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_touch0(
547    mut env: JNIEnv,
548    _class: JClass,
549    ptr: jlong,
550) {
551    if !check_not_null(&mut env, ptr, "RiCachedValue") {
552        return;
553    }
554    
555    let cached_value = unsafe { &mut *(ptr as *mut RiCachedValue) };
556    cached_value.touch();
557}
558
559#[no_mangle]
560pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_isStale0(
561    mut env: JNIEnv,
562    _class: JClass,
563    ptr: jlong,
564    max_idle_secs: jlong,
565) -> jboolean {
566    if !check_not_null(&mut env, ptr, "RiCachedValue") {
567        return 0;
568    }
569    
570    let cached_value = unsafe { &*(ptr as *const RiCachedValue) };
571    if cached_value.is_stale(max_idle_secs as u64) { 1 } else { 0 }
572}
573
574#[no_mangle]
575pub extern "system" fn Java_com_dunimd_ri_cache_RiCachedValue_free0(
576    _env: JNIEnv,
577    _class: JClass,
578    ptr: jlong,
579) {
580    if ptr != 0 {
581        unsafe {
582            let _ = Box::from_raw(ptr as *mut RiCachedValue);
583        }
584    }
585}
586
587// =============================================================================
588// RiCacheManager JNI Bindings
589// =============================================================================
590
591#[no_mangle]
592pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_new0(
593    _env: JNIEnv,
594    _class: JClass,
595) -> jlong {
596    use crate::cache::RiMemoryCache;
597    use std::sync::Arc;
598    
599    let backend = Arc::new(RiMemoryCache::new());
600    let manager = Box::new(RiCacheManager::new(backend));
601    Box::into_raw(manager) as jlong
602}
603
604#[no_mangle]
605pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_get0(
606    mut env: JNIEnv,
607    _class: JClass,
608    ptr: jlong,
609    key: JString,
610) -> jstring {
611    if !check_not_null(&mut env, ptr, "RiCacheManager") {
612        return std::ptr::null_mut();
613    }
614    
615    let manager = unsafe { &*(ptr as *const RiCacheManager) };
616    let key_str: String = match env.get_string(&key) {
617        Ok(s) => s.into(),
618        Err(_) => return std::ptr::null_mut(),
619    };
620
621    let result = block_on_jni(&mut env, "RiCacheManager::get", async move {
622        manager.get::<String>(&key_str).await
623    });
624
625    match result {
626        Some(Ok(Some(value))) => match env.new_string(value) {
627            Ok(s) => s.into_raw(),
628            Err(_) => std::ptr::null_mut(),
629        },
630        _ => std::ptr::null_mut(),
631    }
632}
633
634#[no_mangle]
635pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_set0(
636    mut env: JNIEnv,
637    _class: JClass,
638    ptr: jlong,
639    key: JString,
640    value: JString,
641    ttl_secs: jlong,
642) {
643    if !check_not_null(&mut env, ptr, "RiCacheManager") {
644        return;
645    }
646    
647    let manager = unsafe { &*(ptr as *const RiCacheManager) };
648    let key_str: String = match env.get_string(&key) {
649        Ok(s) => s.into(),
650        Err(_) => return,
651    };
652    let value_str: String = match env.get_string(&value) {
653        Ok(s) => s.into(),
654        Err(_) => return,
655    };
656    let ttl = ttl_from_jlong(ttl_secs);
657
658    let result = block_on_jni(&mut env, "RiCacheManager::set", async move {
659        manager.set(&key_str, &value_str, ttl).await
660    });
661    let _ = result;
662}
663
664#[no_mangle]
665pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_delete0(
666    mut env: JNIEnv,
667    _class: JClass,
668    ptr: jlong,
669    key: JString,
670) -> jboolean {
671    if !check_not_null(&mut env, ptr, "RiCacheManager") {
672        return 0;
673    }
674    
675    let manager = unsafe { &*(ptr as *const RiCacheManager) };
676    let key_str: String = match env.get_string(&key) {
677        Ok(s) => s.into(),
678        Err(_) => return 0,
679    };
680
681    match block_on_jni(&mut env, "RiCacheManager::delete", async move {
682        manager.delete(&key_str).await
683    }) {
684        Some(Ok(deleted)) => if deleted { 1 } else { 0 },
685        Some(Err(_)) => 0,
686        None => 0,
687    }
688}
689
690#[no_mangle]
691pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_exists0(
692    mut env: JNIEnv,
693    _class: JClass,
694    ptr: jlong,
695    key: JString,
696) -> jboolean {
697    if !check_not_null(&mut env, ptr, "RiCacheManager") {
698        return 0;
699    }
700    
701    let manager = unsafe { &*(ptr as *const RiCacheManager) };
702    let key_str: String = match env.get_string(&key) {
703        Ok(s) => s.into(),
704        Err(_) => return 0,
705    };
706
707    match block_on_jni(&mut env, "RiCacheManager::exists", async move {
708        manager.exists(&key_str).await
709    }) {
710        Some(exists) => if exists { 1 } else { 0 },
711        None => 0,
712    }
713}
714
715#[no_mangle]
716pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_clear0(
717    mut env: JNIEnv,
718    _class: JClass,
719    ptr: jlong,
720) {
721    if !check_not_null(&mut env, ptr, "RiCacheManager") {
722        return;
723    }
724    
725    let manager = unsafe { &*(ptr as *const RiCacheManager) };
726
727    let result = block_on_jni(&mut env, "RiCacheManager::clear", async move {
728        manager.clear().await
729    });
730    let _ = result;
731}
732
733#[no_mangle]
734pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_stats0(
735    mut env: JNIEnv,
736    _class: JClass,
737    ptr: jlong,
738) -> jlong {
739    if !check_not_null(&mut env, ptr, "RiCacheManager") {
740        return 0;
741    }
742    
743    let manager = unsafe { &*(ptr as *const RiCacheManager) };
744
745    match block_on_jni(&mut env, "RiCacheManager::stats", async move {
746        manager.stats().await
747    }) {
748        Some(stats) => Box::into_raw(Box::new(stats)) as jlong,
749        None => 0,
750    }
751}
752
753#[no_mangle]
754pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_cleanupExpired0(
755    mut env: JNIEnv,
756    _class: JClass,
757    ptr: jlong,
758) -> jlong {
759    if !check_not_null(&mut env, ptr, "RiCacheManager") {
760        return 0;
761    }
762    
763    let manager = unsafe { &*(ptr as *const RiCacheManager) };
764
765    match block_on_jni(&mut env, "RiCacheManager::cleanupExpired", async move {
766        manager.cleanup_expired().await
767    }) {
768        Some(Ok(count)) => count as jlong,
769        Some(Err(_)) => 0,
770        None => 0,
771    }
772}
773
774#[no_mangle]
775pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_invalidatePattern0(
776    mut env: JNIEnv,
777    _class: JClass,
778    ptr: jlong,
779    pattern: JString,
780) {
781    if !check_not_null(&mut env, ptr, "RiCacheManager") {
782        return;
783    }
784    
785    let manager = unsafe { &*(ptr as *const RiCacheManager) };
786    let pattern_str: String = match env.get_string(&pattern) {
787        Ok(s) => s.into(),
788        Err(_) => return,
789    };
790
791    let result = block_on_jni(&mut env, "RiCacheManager::invalidatePattern", async move {
792        manager.invalidate_pattern(&pattern_str).await
793    });
794    let _ = result;
795}
796
797#[no_mangle]
798pub extern "system" fn Java_com_dunimd_ri_cache_RiCacheManager_free0(
799    _env: JNIEnv,
800    _class: JClass,
801    ptr: jlong,
802) {
803    if ptr != 0 {
804        unsafe {
805            let _ = Box::from_raw(ptr as *mut RiCacheManager);
806        }
807    }
808}