| 3040 | } |
| 3041 | |
| 3042 | std::vector<uint32_t> SyncAllFromCloud(uint32_t accountId) { |
| 3043 | std::vector<uint32_t> syncedApps; |
| 3044 | if (g_shuttingDown.load(std::memory_order_seq_cst)) return syncedApps; |
| 3045 | |
| 3046 | // Same inflight gate as SyncFromCloud; both List/IsAuthenticated and the |
| 3047 | // per-app calls below dereference g_provider. |
| 3048 | g_inflightSyncCount.fetch_add(1, std::memory_order_seq_cst); |
| 3049 | struct InflightGuard { |
| 3050 | ~InflightGuard() { g_inflightSyncCount.fetch_sub(1, std::memory_order_seq_cst); } |
| 3051 | } inflightGuard; |
| 3052 | if (g_shuttingDown.load(std::memory_order_seq_cst)) return syncedApps; |
| 3053 | |
| 3054 | if (!g_provider || !g_provider->IsAuthenticated()) return syncedApps; |
| 3055 | |
| 3056 | if (!WaitForForegroundSyncIdle("SyncAllFromCloud (pre-List)")) return syncedApps; |
| 3057 | |
| 3058 | PruneStaleCloudStaging(accountId); |
| 3059 | |
| 3060 | LOG("[CloudStorage] SyncAllFromCloud: scanning for apps belonging to account %u...", accountId); |
| 3061 | |
| 3062 | std::unordered_set<uint32_t> appIds; |
| 3063 | |
| 3064 | // List all items under the account prefix to discover apps |
| 3065 | std::string prefix = std::to_string(accountId) + "/"; |
| 3066 | auto items = g_provider->List(prefix); |
| 3067 | |
| 3068 | // Extract unique app IDs from paths like "54303850/1229490/cn.dat" |
| 3069 | for (auto& fi : items) { |
| 3070 | // path: "{accountId}/{appId}/..." |
| 3071 | auto firstSlash = fi.path.find('/'); |
| 3072 | if (firstSlash == std::string::npos) continue; |
| 3073 | auto secondSlash = fi.path.find('/', firstSlash + 1); |
| 3074 | if (secondSlash == std::string::npos) continue; |
| 3075 | std::string appStr = fi.path.substr(firstSlash + 1, secondSlash - firstSlash - 1); |
| 3076 | uint32_t parsed = 0; |
| 3077 | if (ParseU32(appStr, parsed)) { |
| 3078 | if (parsed == CloudIntercept::kAccountScopeAppId) { |
| 3079 | uint32_t metadataAppId = 0; |
| 3080 | if (TryExtractAccountMetadataAppId(fi.path, accountId, metadataAppId)) { |
| 3081 | appIds.insert(metadataAppId); |
| 3082 | } |
| 3083 | continue; |
| 3084 | } |
| 3085 | appIds.insert(parsed); |
| 3086 | } |
| 3087 | } |
| 3088 | |
| 3089 | if (appIds.empty()) { |
| 3090 | auto localAppIds = EnumerateLocalAppIds(accountId); |
| 3091 | if (!localAppIds.empty()) { |
| 3092 | LOG("[CloudStorage] SyncAllFromCloud: provider returned 0 apps, falling back to %zu local app(s)", |
| 3093 | localAppIds.size()); |
| 3094 | appIds.insert(localAppIds.begin(), localAppIds.end()); |
| 3095 | } |
| 3096 | } |
| 3097 | |
| 3098 | LOG("[CloudStorage] SyncAllFromCloud: found %zu apps in cloud", appIds.size()); |
| 3099 | for (uint32_t appId : appIds) { |
no test coverage detected