blob: d968d48d7b5345acfad33804cd8f981264106633 [file] [log] [blame]
// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import Foundation
import SyncbaseCore
public typealias BatchOperation = BatchDatabase throws -> Void
/// Provides a way to perform a set of operations atomically on a database. See
/// `Database.beginBatch` for concurrency semantics.
public class BatchDatabase: DatabaseHandle {
private let coreBatchDatabase: SyncbaseCore.BatchDatabase
init(coreBatchDatabase: SyncbaseCore.BatchDatabase) {
self.coreBatchDatabase = coreBatchDatabase
}
public var databaseId: Identifier {
return Identifier(coreId: coreBatchDatabase.databaseId)
}
public func createCollection(prefix prefix: String = "cx", withoutSyncgroup: Bool = false) throws -> Collection {
if (!withoutSyncgroup) {
throw SyncbaseError.BatchError(detail: "Cannot create syncgroup in a batch")
}
// TODO(zinman): Remove the replacingOccurences once collections are no longer strict about
// their names.
let uuid = NSUUID().UUIDString.stringByReplacingOccurrencesOfString("-", withString: "")
let res = try collection(Identifier(name: prefix + "_" + uuid, blessing: personalBlessingString()))
try res.createIfMissing()
return res
}
public func collection(collectionId: Identifier) throws -> Collection {
// TODO(sadovsky): Consider throwing an exception or returning null if the collection does
// not exist. But note, a collection can get destroyed via sync after a client obtains a
// handle for it, so perhaps we should instead add an 'exists' method.
return try SyncbaseError.wrap {
return try Collection(
coreCollection: self.coreBatchDatabase.collection(collectionId.toCore()),
databaseHandle: self)
}
}
/// Returns all collections in the database.
public func collections() throws -> [Collection] {
return try SyncbaseError.wrap {
let coreIds = try self.coreBatchDatabase.listCollections()
return try coreIds.map { coreId in
return Collection(
coreCollection: try self.coreBatchDatabase.collection(coreId),
databaseHandle: self)
}
}
}
/// Persists the pending changes to Syncbase. If the batch is read-only, `commit` will
/// throw `ConcurrentBatchException`; abort should be used instead.
public func commit() throws {
// TODO(sadovsky): Throw ConcurrentBatchException where appropriate.
try SyncbaseError.wrap { try self.coreBatchDatabase.commit() }
}
/// Notifies Syncbase that any pending changes can be discarded. Calling `abort` is not
/// strictly required, but may allow Syncbase to release locks or other resources sooner than if
/// `abort` was not called.
public func abort() throws {
try SyncbaseError.wrap { try self.coreBatchDatabase.abort() }
}
}