| // 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 |
| |
| public struct VersionedSpec { |
| public let spec: SyncgroupSpec |
| public let version: String |
| |
| public init(spec: SyncgroupSpec, version: String) { |
| self.spec = spec |
| self.version = version |
| } |
| } |
| |
| public class Syncgroup { |
| let encodedDatabaseName: String |
| public let syncgroupId: Identifier |
| |
| init(encodedDatabaseName: String, syncgroupId: Identifier) { |
| self.encodedDatabaseName = encodedDatabaseName |
| self.syncgroupId = syncgroupId |
| } |
| |
| /// Create creates a new syncgroup with the given spec. |
| /// |
| /// Requires: Client must have at least Read access on the Database; all |
| /// Collections specified in prefixes must exist; Client must have at least |
| /// Read access on each of the Collection ACLs. |
| public func create(spec: SyncgroupSpec, myInfo: SyncgroupMemberInfo) throws { |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbCreateSyncgroup( |
| try encodedDatabaseName.toCgoString(), |
| try v23_syncbase_Id(syncgroupId), |
| try v23_syncbase_SyncgroupSpec(spec), |
| v23_syncbase_SyncgroupMemberInfo(myInfo), |
| errPtr) |
| } |
| } |
| |
| /// Join joins a syncgroup. |
| /// |
| /// - Parameter remoteSyncbaseName: This is the remote address, analagous to a git remote repo. |
| /// The value will be provided via discovery; you'll never |
| /// automatically know this. |
| /// |
| /// - Parameter expectedSyncbaseBlessings: The blessings you believe the remote side will have, |
| /// to make sure we are talking to who we expect. |
| /// |
| /// - Parameter myInfo: The sync priority and blob device type. |
| /// |
| /// Requires: Client must have at least Read access on the Database and on the |
| /// syncgroup ACL. |
| public func join(remoteSyncbaseName: String, expectedSyncbaseBlessings: [String], myInfo: SyncgroupMemberInfo) throws -> SyncgroupSpec { |
| var spec = v23_syncbase_SyncgroupSpec() |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbJoinSyncgroup( |
| try encodedDatabaseName.toCgoString(), |
| try remoteSyncbaseName.toCgoString(), |
| try v23_syncbase_Strings(expectedSyncbaseBlessings), |
| try v23_syncbase_Id(syncgroupId), |
| v23_syncbase_SyncgroupMemberInfo(myInfo), |
| &spec, |
| errPtr) |
| } |
| return try spec.extract() |
| } |
| |
| /// Leave leaves the syncgroup. Previously synced data will continue |
| /// to be available. |
| /// |
| /// Requires: Client must have at least Read access on the Database. |
| public func leave() throws { |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbLeaveSyncgroup( |
| try encodedDatabaseName.toCgoString(), |
| try v23_syncbase_Id(syncgroupId), |
| errPtr) |
| } |
| } |
| |
| /// Destroy destroys the syncgroup. Previously synced data will |
| /// continue to be available to all members. |
| /// |
| /// Requires: Client must have at least Read access on the Database, and must |
| /// have Admin access on the syncgroup ACL. |
| public func destroy() throws { |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbDestroySyncgroup( |
| try encodedDatabaseName.toCgoString(), |
| try v23_syncbase_Id(syncgroupId), |
| errPtr) |
| } |
| } |
| |
| /// Eject ejects a member from the syncgroup. The ejected member |
| /// will not be able to sync further, but will retain any data it has already |
| /// synced. |
| /// |
| /// Requires: Client must have at least Read access on the Database, and must |
| /// have Admin access on the syncgroup ACL. |
| public func eject(member: String) throws { |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbEjectFromSyncgroup( |
| try encodedDatabaseName.toCgoString(), |
| try v23_syncbase_Id(syncgroupId), |
| try member.toCgoString(), |
| errPtr) |
| } |
| } |
| |
| /// GetSpec gets the syncgroup spec. version allows for atomic |
| /// read-modify-write of the spec - see comment for SetSpec. |
| /// |
| /// Requires: Client must have at least Read access on the Database and on the |
| /// syncgroup ACL. |
| public func getSpec() throws -> VersionedSpec { |
| var spec = v23_syncbase_SyncgroupSpec() |
| var version = v23_syncbase_String() |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbGetSyncgroupSpec( |
| try encodedDatabaseName.toCgoString(), |
| try v23_syncbase_Id(syncgroupId), |
| &spec, |
| &version, |
| errPtr) |
| } |
| return VersionedSpec( |
| spec: try spec.extract(), |
| version: version.extract()!) |
| } |
| |
| /// SetSpec sets the syncgroup spec. version may be either empty or |
| /// the value from a previous Get. If not empty, Set will only succeed if the |
| /// current version matches the specified one. |
| /// |
| /// Requires: Client must have at least Read access on the Database, and must |
| /// have Admin access on the syncgroup ACL. |
| public func setSpec(versionedSpec: VersionedSpec) throws { |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbSetSyncgroupSpec( |
| try encodedDatabaseName.toCgoString(), |
| try v23_syncbase_Id(syncgroupId), |
| try v23_syncbase_SyncgroupSpec(versionedSpec.spec), |
| try versionedSpec.version.toCgoString(), |
| errPtr) |
| } |
| } |
| |
| /// GetMembers gets the info objects for members of the syncgroup. |
| /// |
| /// Requires: Client must have at least Read access on the Database and on the |
| /// syncgroup ACL. |
| public func getMembers() throws -> [String: SyncgroupMemberInfo] { |
| var members = v23_syncbase_SyncgroupMemberInfoMap() |
| try VError.maybeThrow { errPtr in |
| v23_syncbase_DbGetSyncgroupMembers( |
| try encodedDatabaseName.toCgoString(), |
| try v23_syncbase_Id(syncgroupId), |
| &members, |
| errPtr) |
| } |
| return members.extract() |
| } |
| } |
| |
| public struct SyncgroupInvite { |
| public let syncgroupId: Identifier |
| public let addresses: [String] |
| public let blessingNames: [String] |
| } |
| |
| /// SyncgroupMemberInfo contains per-member metadata. |
| public struct SyncgroupMemberInfo { |
| public let syncPriority: UInt8 |
| public let blobDevType: BlobDevType /// See BlobDevType* constants. |
| |
| public init(syncPriority: UInt8 = 0, blobDevType: BlobDevType = .Leaf) { |
| self.syncPriority = syncPriority |
| self.blobDevType = blobDevType |
| } |
| } |
| |
| public struct SyncgroupSpec: CustomDebugStringConvertible { |
| /// Human-readable description of this syncgroup. |
| public let description: String |
| |
| // Data (set of collectionIds) covered by this syncgroup. |
| public let collections: [Identifier] |
| |
| /// Permissions governing access to this syncgroup. |
| public let permissions: Permissions |
| |
| // Optional. If present then any syncbase that is the admin of this syncgroup |
| // is responsible for ensuring that the syncgroup is published to this syncbase instance. |
| public let publishSyncbaseName: String? |
| |
| /// Mount tables at which to advertise this syncgroup, for rendezvous purposes. |
| /// (Note that in addition to these mount tables, Syncbase also uses |
| /// network-neighborhood-based discovery for rendezvous.) |
| /// We expect most clients to specify a single mount table, but we accept an |
| /// array of mount tables to permit the mount table to be changed over time |
| /// without disruption. |
| public let mountTables: [String] |
| |
| /// Specifies the privacy of this syncgroup. More specifically, specifies |
| /// whether blobs in this syncgroup can be served to clients presenting |
| /// blobrefs obtained from other syncgroups. |
| public let isPrivate: Bool |
| |
| public init( |
| description: String, |
| collections: [Identifier], |
| permissions: Permissions, |
| publishSyncbaseName: String?, |
| mountTables: [String], |
| isPrivate: Bool) { |
| self.description = description |
| self.collections = collections |
| self.permissions = permissions |
| self.publishSyncbaseName = publishSyncbaseName |
| self.mountTables = mountTables |
| self.isPrivate = isPrivate |
| } |
| |
| public var debugDescription: String { |
| return "SyncgroupSpec[\n" + |
| "Description: \(description)\n" + |
| "Collections: \(collections)\n" + |
| "Permissions: \(permissions)\n" + |
| "PublicSyncbaseName: \(publishSyncbaseName)\n" + |
| "MountTables: \(mountTables)\n" + |
| "IsPrivate: \(isPrivate)]" |
| } |
| } |