///|
struct TemporaryWorkspace {
storage : SortStorage
maximum : UInt64
live : Map[Int, UInt64]
mut bytes : UInt64
mut peak : UInt64
}
///|
fn TemporaryWorkspace::create(
self : TemporaryWorkspace,
id : Int,
) -> WriteSink raise McapError {
if self.live.contains(id) {
raise Invalid("temporary identifier already exists")
}
self.live[id] = 0UL
let target = (self.storage.create)(id)
new_write_sink(fn(bytes) {
if bytes.length().to_uint64() > self.maximum - self.bytes {
raise Invalid("combined temporary disk budget exceeded")
}
target.write(bytes)
self.live[id] = self.live[id] + bytes.length().to_uint64()
self.bytes += bytes.length().to_uint64()
if self.bytes > self.peak {
self.peak = self.bytes
}
})
}
///|
fn TemporaryWorkspace::remove(
self : TemporaryWorkspace,
id : Int,
) -> Unit raise McapError {
if self.live.get(id) is Some(size) {
(self.storage.remove)(id)
self.live.remove(id)
self.bytes -= size
}
}
///|
fn TemporaryWorkspace::finish(
self : TemporaryWorkspace,
) -> Unit raise McapError {
let errors = []
for id in self.live.keys().to_array() {
self.remove(id) catch {
Invalid(reason) => errors.push(reason)
}
}
(self.storage.finish)() catch {
Invalid(reason) => errors.push(reason)
}
if !errors.is_empty() {
raise Invalid("temporary cleanup failed: \{errors[0]}")
}
}