Skip to content

Commit 35ebe36

Browse files
authored
Add calculateOrphanedBlobsSize() to calculate the size of orphaned blobs (#428)
Adds `calculateOrphanedBlobsSize()` to calculate the size of orphaned blobs, will need this to include them under size and reclaimable space for images in the `container system df` command so it matches up with what `container image prune` frees up on disk.
1 parent 836b699 commit 35ebe36

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

Sources/Containerization/Image/ImageStore/ImageStore.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ extension ImageStore {
141141
}
142142
}
143143

144+
/// Calculate the size of orphaned blobs without deleting them.
145+
///
146+
/// - Returns: The total size in bytes of blobs that are not referenced by any image.
147+
public func calculateOrphanedBlobsSize() async throws -> UInt64 {
148+
try await self.lock.withLock { lockCtx in
149+
try await self._calculateOrphanedBlobsSize(lockCtx)
150+
}
151+
}
152+
144153
@discardableResult
145154
private func _cleanupOrphanedBlobs(_ lock: AsyncLock.Context) async throws -> (deleted: [String], freed: UInt64) {
146155
let images = try await self.list()
@@ -152,6 +161,39 @@ extension ImageStore {
152161
return (deleted, size)
153162
}
154163

164+
private func _calculateOrphanedBlobsSize(_ lock: AsyncLock.Context) async throws -> UInt64 {
165+
let images = try await self.list()
166+
var referenced: [String] = []
167+
for image in images {
168+
try await referenced.append(contentsOf: image.referencedDigests().uniqued())
169+
}
170+
171+
// Calculate size of blobs not in the referenced list
172+
let referencedSet = Set(referenced.map { $0.trimmingDigestPrefix })
173+
let blobsPath = self.path.appendingPathComponent("content/blobs/sha256")
174+
175+
let fileManager = FileManager.default
176+
let allBlobs = try fileManager.contentsOfDirectory(
177+
at: blobsPath,
178+
includingPropertiesForKeys: [.fileSizeKey],
179+
options: [.skipsHiddenFiles]
180+
)
181+
182+
var orphanedSize: UInt64 = 0
183+
for blobURL in allBlobs {
184+
let digest = blobURL.lastPathComponent
185+
if !referencedSet.contains(digest) {
186+
if let resourceValues = try? blobURL.resourceValues(forKeys: [.fileSizeKey]),
187+
let size = resourceValues.fileSize
188+
{
189+
orphanedSize += UInt64(size)
190+
}
191+
}
192+
}
193+
194+
return orphanedSize
195+
}
196+
155197
/// Tag an existing image such that it can be referenced by another name.
156198
///
157199
/// - Parameters:

0 commit comments

Comments
 (0)