1+ /* *
2+ * @file CompatibilityBridge.cpp
3+ * @brief C++ bridge for model compatibility checks.
4+ *
5+ * Uses DeviceBridge for RAM and POSIX statvfs for disk space,
6+ * then calls rac_model_check_compatibility() from runanywhere-commons.
7+ */
8+
9+ #include " CompatibilityBridge.hpp"
10+ #include " DeviceBridge.hpp"
11+
12+ #include < sys/statvfs.h> // POSIX filesystem statistics
13+
14+ // Platform-specific logging
15+ #if defined(ANDROID) || defined(__ANDROID__)
16+ #include < android/log.h>
17+ #define LOG_TAG " CompatibilityBridge"
18+ #define LOGI (...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
19+ #define LOGD (...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
20+ #define LOGE (...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
21+ #else
22+ #include < cstdio>
23+ #define LOGI (...) printf(" [CompatibilityBridge] " ); printf(__VA_ARGS__); printf(" \n " )
24+ #define LOGD (...) printf(" [CompatibilityBridge DEBUG] " ); printf(__VA_ARGS__); printf(" \n " )
25+ #define LOGE (...) printf(" [CompatibilityBridge ERROR] " ); printf(__VA_ARGS__); printf(" \n " )
26+ #endif
27+
28+ namespace runanywhere {
29+ namespace bridges {
30+
31+ CompatibilityResult CompatibilityBridge::checkCompatibility (
32+ const std::string& modelId,
33+ rac_model_registry_handle_t registryHandle) {
34+
35+ CompatibilityResult result;
36+
37+ if (!registryHandle) {
38+ LOGE (" Model registry handle is null" );
39+ return result;
40+ }
41+
42+ // Get available RAM from DeviceBridge
43+ int64_t availableRAM = 0 ;
44+ if (DeviceBridge::shared ().isCallbacksRegistered ()) {
45+ auto deviceInfo = DeviceBridge::shared ().getDeviceInfo ();
46+ availableRAM = deviceInfo.availableMemory ;
47+ LOGD (" Available RAM from DeviceBridge: %lld bytes" ,
48+ static_cast <long long >(availableRAM));
49+ } else {
50+ LOGD (" DeviceBridge not initialized, RAM check will be skipped" );
51+ }
52+
53+ // Get available storage using POSIX statvfs
54+ // This queries the filesystem directly - same as what FileManager/StatFs use underneath
55+ int64_t availableStorage = 0 ;
56+ {
57+ struct statvfs stat;
58+ // Query root filesystem - works on both iOS and Android
59+ if (statvfs (" /" , &stat) == 0 ) {
60+ // f_bavail = available blocks for unprivileged users
61+ // f_frsize = fragment size (fundamental block size)
62+ availableStorage = static_cast <int64_t >(stat.f_bavail ) * static_cast <int64_t >(stat.f_frsize );
63+
64+ LOGD (" Available storage from statvfs: %lld bytes (%.2f GB)" ,
65+ static_cast <long long >(availableStorage),
66+ static_cast <double >(availableStorage) / (1024.0 * 1024.0 * 1024.0 ));
67+ } else {
68+ LOGE (" statvfs failed (errno=%d), storage check will be skipped" , errno);
69+ }
70+ }
71+
72+ // Call the RACommons C API
73+ rac_model_compatibility_result_t cResult;
74+ rac_result_t rc = rac_model_check_compatibility (
75+ registryHandle,
76+ modelId.c_str (),
77+ availableRAM,
78+ availableStorage,
79+ &cResult);
80+
81+ if (rc == RAC_SUCCESS) {
82+ result.isCompatible = cResult.is_compatible == RAC_TRUE;
83+ result.canRun = cResult.can_run == RAC_TRUE;
84+ result.canFit = cResult.can_fit == RAC_TRUE;
85+ result.requiredMemory = cResult.required_memory ;
86+ result.availableMemory = cResult.available_memory ;
87+ result.requiredStorage = cResult.required_storage ;
88+ result.availableStorage = cResult.available_storage ;
89+
90+ LOGI (" Compatibility check for %s: compatible=%d, canRun=%d, canFit=%d, RAM=%lld/%lld, Storage=%lld/%lld" ,
91+ modelId.c_str (),
92+ result.isCompatible ,
93+ result.canRun ,
94+ result.canFit ,
95+ static_cast <long long >(result.availableMemory ),
96+ static_cast <long long >(result.requiredMemory ),
97+ static_cast <long long >(result.availableStorage ),
98+ static_cast <long long >(result.requiredStorage ));
99+ } else {
100+ LOGE (" Compatibility check failed for %s: error %d" , modelId.c_str (), rc);
101+ }
102+
103+ return result;
104+ }
105+
106+ } // namespace bridges
107+ } // namespace runanywhere
0 commit comments