blob: bc821360ff0bd8ecf1b7eeaff96150056cb0145c [file] [log] [blame]
// Copyright 2015 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.
package interfaces
import (
wire "v.io/v23/services/syncbase"
)
// Sync defines methods for data exchange between Syncbases.
// TODO(hpucha): Flesh this out further.
type Sync interface {
// GetTime returns metadata related to the Syncbase virtual clock, including
// system clock values, last NTP timestamp, num reboots, etc.
//
// Requires: Always allowed.
// TODO(ivanpi): Consider adding an ACL or checking syncgroup ACLs.
GetTime(req TimeReq, initiator string) (TimeResp | error)
// GetDeltas returns the responder's current generation vectors and all
// the missing log records when compared to the initiator's generation
// vectors for one Database for either syncgroup metadata or data.
// The final result (in DeltaFinalResp) currently includes the
// syncgroup priorities for blob ownership for the server.
//
// Requires: Read on syncgroup.
// TODO(ivanpi): Consider rechecking Collection Read access.
// The caller should verify that all received changes (data, ACLs, spec) are
// signed by a blessing that had the appropriate permission (Write or Admin).
// TODO(ivanpi): Implement signatures and signature verification.
GetDeltas(req DeltaReq, initiator string) stream<_, DeltaResp> (DeltaFinalResp | error)
// Syncgroup-related methods.
// PublishSyncgroup is invoked on the syncgroup name (typically served
// by a "central" peer) to publish the syncgroup. It takes the name of
// Syncbase doing the publishing (the publisher) and returns the name
// of the Syncbase where the syncgroup is published (the publishee).
// This allows the publisher and the publishee to learn of each other.
// When a syncgroup is published, the publishee is given the syncgroup
// metadata, its current version at the publisher, and the current
// syncgroup generation vector. The generation vector serves as a
// checkpoint at the time of publishing. The publishing proceeds
// asynchronously, and the publishee learns the syncgroup history
// through the routine p2p sync process and determines when it has
// caught up to the level of knowledge at the time of publishing using
// the checkpointed generation vector. Until that point, the publishee
// locally deems the syncgroup to be in a pending state and does not
// mutate it. Thus it locally rejects syncgroup joins or updates to
// its spec until it is caught up on the syncgroup history.
//
// Requires: Always allowed.
// TODO(ivanpi): Add separate ACL for PublishSyncgroup and check it.
PublishSyncgroup(publisher string, sg Syncgroup, version string, genvec GenVector) (string | error)
// JoinSyncgroupAtAdmin is invoked by a prospective syncgroup member's
// Syncbase on a syncgroup admin. It checks whether the requestor is
// allowed to join the named syncgroup, and if so, adds the requestor to
// the syncgroup. It returns a copy of the updated syncgroup metadata,
// its version, and the syncgroup generation vector at the time of the
// join. Similar to the PublishSyncgroup scenario, the joiner at that
// point does not have the syncgroup history and locally deems it to be
// in a pending state and does not mutate it. This means it rejects
// local updates to the syncgroup spec or, if it were also an admin on
// the syncgroup, it would reject syncgroup joins until it is caught up
// on the syncgroup history through p2p sync.
//
// Requires: Read on syncgroup and on all Collections in the syncgroup spec.
JoinSyncgroupAtAdmin(dbId wire.Id, sgId wire.Id, joinerName string, myInfo wire.SyncgroupMemberInfo) (sg Syncgroup, version string, genvec GenVector | error)
// BlobSync methods.
// TODO(ivanpi): Document authorization policies.
// HaveBlob verifies that the peer has the requested blob, and if
// present, returns its size. Otherwise, it returns -1, and the location
// hints (the Signpost) that the peer has for the blob, filtered to
// include only data the caller is permitted to see:
// + Device D reveals a syncgroup SG to the caller C iff
// - D is in SG, and
// - SG is in the Signpost, and
// - at least one of:
// - SG is not private, or
// - C has permission to join SG.
// + Device D reveals a location hint L to caller C iff
// there is a syncgroup SG such that
// - D is in SG, and
// - SG is in the Signpost, and
// - L is in SG, and
// - at least one of:
// - SG is not private, or
// - C has permission to join SG, or
// - L is a blob server in SG.
HaveBlob(br wire.BlobRef) (size int64, signpost Signpost | error)
// FetchBlob fetches the requested blob.
// It returns a number of blob ownership shares that the server hopes
// the client will accept using the AcceptedBlobOwnership() call.
FetchBlob(br wire.BlobRef, mySgPriorities SgPriorities) stream<_, []byte> (shares BlobSharesBySyncgroup | error)
// Methods for incremental blob transfer. The transfer starts with the
// receiver making a FetchBlobRecipe call to the sender for a given
// BlobRef. The sender, in turn, sends the chunk hashes of all the
// chunks that make up the requested blob (blob recipe). The receiver
// looks up the chunk hashes in its local blob store, and identifies the
// missing ones. The receiver then fetches the missing chunks using a
// FetchChunks call from the sender. Finally, the receiver finishes the
// blob fetch by combining the chunks obtained over the network with the
// already available local chunks as per the blob recipe.
// callerName is the syncbase Id of the caller, expressed as a string.
// FetchBlobRecipe returns a number of blob ownership shares that the
// server hopes the client will accept for each syncgroup using the
// AcceptedBlobOwnership() call.
FetchBlobRecipe(br wire.BlobRef, callerName string, mySgPriorities SgPriorities) stream<_, ChunkHash> (shares BlobSharesBySyncgroup | error)
FetchChunks() stream<ChunkHash, ChunkData> error
// RequestTakeBlobs indicates that the caller wishes the server to take
// some blob ownership shares for various syncgroups for the specified blobs.
// If the server chooses to act on the request, it may call FetchBlob/FetchBlobRecipe,
// and ultimately AcceptedBlobOwnership().
// callerName is the syncbase Id of the caller, expressed as a string.
RequestTakeBlobs(callerName string, blobRefToShares map[wire.BlobRef]BlobSharesBySyncgroup) error
// AcceptedBlobOwnership tells the server that the client callerName (a
// syncbase Id expressed as a string) has accepted blob ownership of a
// specified number of shares for blob br. The server may decrement
// its share count by up to this number. It is safe for the server to
// decrement its share count by fewer than the number of shares another
// device has taken responsibility for, but unsafe to decrement it by
// more than that that number. It returns a hint as to whether the
// server is likely to keep the blob itself, plus its syncbase Id
// expressed as a string.
AcceptedBlobOwnership(br wire.BlobRef, callerName string, shares BlobSharesBySyncgroup) (serverName string, keepingBlob bool | error)
// GetBlobShares returns the number of ownership shares for the specified blob
// held by the server. It is used by the DevModeGetBlobShares() call in the
// service. It uses the "map[string]int32" type, rather than
// interfaces.BlobSharesBySyncgroup, so that the client of this call code doesn't
// need to reach into the sync service's type definitions.
GetBlobShares(br wire.BlobRef) (map[string]int32 | error)
}
// TODO(ivanpi): Some methods are missing additional parameter handling ({:_}).
error (
DupSyncgroupPublish(sgId wire.Id) {"en": "duplicate publish on syncgroup: {sgId}"}
ConnFail() {"en": "connection to peer failed{:_}"}
BrokenCrConnection() {"en": "CrConnection stream to client does not exist or is broken"}
DbOffline(dbId wire.Id) {"en": "database {dbId} is offline and cannot be synced{:_}"}
GetTimeFailed() {"en": "GetTime failed{:_}"}
NotAdmin() {"en": "not an admin of the syncgroup"}
)