| 127 | } |
| 128 | |
| 129 | void BackupSizeCache::compute(u64 cacheKey, std::u16string rootPath) |
| 130 | { |
| 131 | const std::string root = StringUtils::UTF16toUTF8(rootPath); |
| 132 | u64 total = 0; |
| 133 | std::vector<std::pair<std::u16string, u64>> perBackup; |
| 134 | |
| 135 | DIR* dir = opendir(root.c_str()); |
| 136 | if (dir) { |
| 137 | struct dirent* ent; |
| 138 | while (!mAbort.load() && (ent = readdir(dir)) != nullptr) { |
| 139 | if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { |
| 140 | continue; |
| 141 | } |
| 142 | std::string full = root + "/" + ent->d_name; |
| 143 | struct stat st; |
| 144 | if (stat(full.c_str(), &st) != 0) { |
| 145 | continue; |
| 146 | } |
| 147 | if (S_ISDIR(st.st_mode)) { |
| 148 | u64 sz = walk(full); |
| 149 | total += sz; |
| 150 | perBackup.emplace_back(rootPath + u"/" + StringUtils::UTF8toUTF16(ent->d_name), sz); |
| 151 | } |
| 152 | else { |
| 153 | total += (u64)st.st_size; |
| 154 | } |
| 155 | } |
| 156 | closedir(dir); |
| 157 | } |
| 158 | |
| 159 | std::lock_guard<std::mutex> lock(mMutex); |
| 160 | mPending.erase(cacheKey); |
| 161 | // Discard a partial result produced while shutting down. |
| 162 | if (mAbort.load()) { |
| 163 | return; |
| 164 | } |
| 165 | mTotals[cacheKey] = total; |
| 166 | for (auto& pb : perBackup) { |
| 167 | mBackupSizes[pb.first] = pb.second; |
| 168 | } |
| 169 | mGeneration.fetch_add(1); |
| 170 | } |
no test coverage detected