123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package sortutil
- import (
- "bytes"
- "fmt"
- "sort"
- )
- /*
- VectorClock implements a vector clock object. The clock can record actions
- of actors. Each action produces a new version which can be queried.
- */
- type VectorClock struct {
- versionVector map[string]uint64 // Data for the cache
- }
- /*
- NewVectorClock creates a new vector clock datastructure.
- */
- func NewVectorClock() *VectorClock {
- return &VectorClock{make(map[string]uint64)}
- }
- /*
- CloneVectorClock clones an existing vector clock.
- */
- func CloneVectorClock(vc *VectorClock) *VectorClock {
- newVC := NewVectorClock()
- for actor, version := range vc.versionVector {
- newVC.versionVector[actor] = version
- }
- return newVC
- }
- /*
- NewDescendant creates a vector clock which is a descendant of all given vector clocks.
- */
- func NewDescendant(otherVCs ...*VectorClock) *VectorClock {
- newVC := NewVectorClock()
- for _, otherVC := range otherVCs {
- for actor, version := range otherVC.versionVector {
- if newVC.Version(actor) < version {
- newVC.versionVector[actor] = version
- }
- }
- }
- return newVC
- }
- /*
- Act records an action of an actor.
- */
- func (vc *VectorClock) Act(actor string) {
- if _, ok := vc.versionVector[actor]; ok {
- vc.versionVector[actor]++
- } else {
- vc.versionVector[actor] = 1
- }
- }
- /*
- Version returns the current version for a given actor.
- */
- func (vc *VectorClock) Version(actor string) uint64 {
- if v, ok := vc.versionVector[actor]; ok {
- return v
- }
- return 0
- }
- /*
- IsDescendent determines if another vector clock is a descendent of this vector clock.
- */
- func (vc *VectorClock) IsDescendent(otherVC *VectorClock) bool {
- // In order for vc to be considered a descendant of otherVC, each marker
- // in otherVC must have a corresponding marker in vc that has a revision
- // number greater than or equal to the marker in otherVC.
- for actor, version := range otherVC.versionVector {
- if vc.Version(actor) < version {
- return false
- }
- }
- return true
- }
- /*
- IsConflicting determines if another vector clock is conflicting with this vector clock.
- */
- func (vc *VectorClock) IsConflicting(otherVC *VectorClock) bool {
- return !(vc.IsDescendent(otherVC) || otherVC.IsDescendent(vc))
- }
- /*
- String returns a string representation of this vector clock.
- */
- func (vc *VectorClock) String() string {
- var actors []string
- for actor := range vc.versionVector {
- actors = append(actors, actor)
- }
- sort.Strings(actors)
- buf := &bytes.Buffer{}
- for _, actor := range actors {
- version := vc.versionVector[actor]
- buf.WriteString(fmt.Sprint(actor, ":", version, "\n"))
- }
- return buf.String()
- }
|