colog

package module
v0.0.0-...-e82235a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 28, 2016 License: MIT Imports: 6 Imported by: 1

README

go-ipfs-colog

colog is a concurrent log. In the JS version of Orbit it is currently called log, but in many contexts a log is a linear sequence of events. To avoid confusion, the Go version was named colog.

Installing

go get the package, including the deps for tests (-t):

go get -t github.com/keks/go-ipfs-colog

Test

Once successfully installed

go test github.com/keks/go-ipfs-colog

does the trick.

API documentation

You can find the API reference on godoc.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CoLog

type CoLog struct {
	// contains filtered or unexported fields
}

CoLog is a concurrent log

Example (ConcurrentAccess)
var wg sync.WaitGroup

l := New(ipfsdb)

n := 50

sum := 0

wg.Add(n)

for i := 0; i < n; i++ {
	go func(j int) {
		l.Add(j)
		wg.Done()
	}(i)
}

wg.Wait()

for _, e := range l.Items() {
	var j int
	err := json.Unmarshal(e.Value, &j)
	if err != nil {
		panic(err)
	}

	sum += j
}

// 1+2+3+4+...+n   = n*(n+1)/2
// 0+1+2+3+...+n-1 = (n-1)*n/2
//								 = n*(n-1)/2
if sum != n*(n-1)/2 {
	panic("wrong sum")
}

fmt.Println("ok")
Output:

ok

func New

func New(db immutabledb.ImmutableDB) *CoLog

New returns a concurrent log

func (*CoLog) Add

func (l *CoLog) Add(data interface{}) (*Entry, error)

Add adds data to the colog and returns the resulting entry

Example (One)
var log1 = New(ipfsdb)

one, err := log1.Add(value1)
if err != nil {
	panic(err)
}

fmt.Println(one.Hash)
fmt.Println(one.GetString())
fmt.Println(one.Prev)
Output:

QmbiruS6UMT6gT3JBHtZNWKitEssyUQzYu8k4gGd6rhzNc
Hello1
{ null }
Example (Three)
var log1 = New(ipfsdb)

log1.Add(value1)
log1.Add(value2)
log1.Add(value3)

items := log1.Items()
fmt.Println(len(items))
fmt.Println(string(items[0].GetString()))
fmt.Println(string(items[1].GetString()))
fmt.Println(string(items[2].GetString()))
fmt.Println(items[0].Prev)
e1, err := log1.Get(items[1].Prev.Sorted()[0])
if err != nil {
	panic(err)
}
fmt.Println(e1.Hash)
e2, err := log1.Get(items[2].Prev.Sorted()[0])
if err != nil {
	panic(err)
}
fmt.Println(e2.Hash)
Output:

3
Hello1
Hello2
Hello3
{ null }
QmbiruS6UMT6gT3JBHtZNWKitEssyUQzYu8k4gGd6rhzNc
QmdezppSoeGZmyYQZEuiUTU4cxTqyVfiwBct7D5iosY6zN
Example (Two)
var log1 = New(ipfsdb)

log1.Add(value1)
log1.Add(value2)

items := log1.Items()
fmt.Println(len(items))
fmt.Println(items[1].Hash)
fmt.Println(string(items[1].GetString()))
e, err := log1.Get(items[1].Prev.Sorted()[0])
if err != nil {
	panic(err)
}

fmt.Println(e.Hash)
Output:

2
QmdezppSoeGZmyYQZEuiUTU4cxTqyVfiwBct7D5iosY6zN
Hello2
QmbiruS6UMT6gT3JBHtZNWKitEssyUQzYu8k4gGd6rhzNc

func (*CoLog) Contains

func (l *CoLog) Contains(h Hash) bool

Contains returns whether an Entry with Hash h is stored.

func (*CoLog) FetchFromHead

func (l *CoLog) FetchFromHead(head Hash) error

FetchFromHead takes a Hash `head' and recursively adds the entries behind the head

func (*CoLog) Get

func (l *CoLog) Get(h Hash) (*Entry, error)

Get returns an entry from the db.

func (*CoLog) Heads

func (l *CoLog) Heads() []Hash

Heads returns the Hashes of the dangling heads.

func (*CoLog) Items

func (l *CoLog) Items() []*Entry

Items returns the Entries in canonical order

Example (Ordering)
package main

import (
	"fmt"
)

func checkadd(e *Entry, err error) *Entry {
	check(err)

	return e
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	l1 := New(ipfsdb)
	l2 := New(ipfsdb)
	l3 := New(ipfsdb)

	checkadd(l1.Add("init"))
	check(l2.Join(l1))

	checkadd(l1.Add("simple fix"))
	checkadd(l2.Add("fix simple bug"))
	checkadd(l2.Add("oh i missed something"))

	check(l1.Join(l2))
	check(l2.Join(l1))

	checkadd(l1.Add("bump version 0.2"))

	check(l2.Join(l1))

	checkadd(l2.Add("add feature"))

	check(l1.Join(l2))
	check(l3.Join(l2))

	checkadd(l3.Add("add chinese translation"))
	checkadd(l1.Add("add spanish translation"))
	checkadd(l2.Add("add afrikaans translation"))

	check(l1.Join(l3))
	check(l3.Join(l1))

	checkadd(l3.Add("fix i18n api"))
	checkadd(l3.Add("add i18n feature"))

	check(l1.Join(l2))
	check(l1.Join(l3))

	checkadd(l1.Add("version bump 0.3"))

	for _, e := range l1.Items() {
		fmt.Println(e.Hash, e.GetString(), e.Prev)
	}

}
Output:

QmT1yirz1BgNjWQJgefjz37UoZsc4aa5DDAdVFKcWQek3L init { null }
QmYhvpaYk2MGwVGpHwM6gGS5GQu1esCBeueQBbpSXNPRRa fix simple bug { QmT1yirz1BgNjWQJgefjz37UoZsc4aa5DDAdVFKcWQek3L }
QmcoQ6WHtjrFi6x1JB6VBLDEYzfgxaM9mYwXRJ953M2SJ8 oh i missed something { QmYhvpaYk2MGwVGpHwM6gGS5GQu1esCBeueQBbpSXNPRRa }
QmYWcu4VkcQ7vvugSqJuwsVLwLijfhDj7UGyae2a8V1xY3 simple fix { QmT1yirz1BgNjWQJgefjz37UoZsc4aa5DDAdVFKcWQek3L }
QmZtEaT7KTd1w2uzL46xMscjXMgwxupgy1chpPKHvdSbzC bump version 0.2 { QmYWcu4VkcQ7vvugSqJuwsVLwLijfhDj7UGyae2a8V1xY3, QmcoQ6WHtjrFi6x1JB6VBLDEYzfgxaM9mYwXRJ953M2SJ8 }
QmYJStDEEPBWRU85G5N55585LroCaf1axK1ynKLR9gcaFh add feature { QmZtEaT7KTd1w2uzL46xMscjXMgwxupgy1chpPKHvdSbzC }
Qme9Dqbu98VsdvmJvbpnbcKeUkh4d332BFxiCMJFFEU1Dj add spanish translation { QmYJStDEEPBWRU85G5N55585LroCaf1axK1ynKLR9gcaFh }
Qmcuv6bvnVbahziieBb28oR8E6TpgRWyX3vzWu4MgWyVHa add chinese translation { QmYJStDEEPBWRU85G5N55585LroCaf1axK1ynKLR9gcaFh }
QmRrX4qyaZX8wMTkjfHLbT8erD6Hz6suzZvDA4LbTcL646 fix i18n api { Qmcuv6bvnVbahziieBb28oR8E6TpgRWyX3vzWu4MgWyVHa, Qme9Dqbu98VsdvmJvbpnbcKeUkh4d332BFxiCMJFFEU1Dj }
QmSRozfJqeznzV7j1tL8LbTyPGHRAhFoqaBGsmzbRyReqh add i18n feature { QmRrX4qyaZX8wMTkjfHLbT8erD6Hz6suzZvDA4LbTcL646 }
QmRBzEJQ3eDaKVh9dM6XhrQ1GgMSRm6uge8M7itkHUhorE add afrikaans translation { QmYJStDEEPBWRU85G5N55585LroCaf1axK1ynKLR9gcaFh }
QmPse7WVT7ftSpvcMPXCfTPjehwigDaSMsaePpgtjANzzy version bump 0.3 { QmRBzEJQ3eDaKVh9dM6XhrQ1GgMSRm6uge8M7itkHUhorE, QmSRozfJqeznzV7j1tL8LbTyPGHRAhFoqaBGsmzbRyReqh }

func (*CoLog) Join

func (l *CoLog) Join(other *CoLog) error

Join merges colog `other' into `l'

Example (One)
var log1 = New(ipfsdb)
var log2 = New(ipfsdb)

log1.Add(value1)
log2.Add(value2)

log1.Join(log2)

items := log1.Items()
first := items[0]
second := items[1]

fmt.Println(len(items))
fmt.Println(first.Hash)
fmt.Println(second.Hash)
fmt.Println(string(first.GetString()))
fmt.Println(string(second.GetString()))
Output:

2
QmbiruS6UMT6gT3JBHtZNWKitEssyUQzYu8k4gGd6rhzNc
QmXgHKWQEG6NwpqJMvvvBdMrzWqPNo6cLtZr4BpZHFvrXV
Hello1
Hello2

func (*CoLog) Nexts

func (l *CoLog) Nexts(h Hash) HashSet

Nexts returns the set of hashes that reference hash h.

func (*CoLog) Prevs

func (l *CoLog) Prevs(h Hash) HashSet

Prevs returns the set of hashes that are referenced by hash h.

func (*CoLog) Query

func (l *CoLog) Query(qry Query) Result

Query traverses the part of the colog specified by Query

func (*CoLog) Unwatch

func (l *CoLog) Unwatch(ch <-chan *Entry)

Unwatch drops channel ch from the list of channels that are being written to

Example
l1 := New(ipfsdb)
l2 := New(ipfsdb)

ch := l1.Watch()
wait := make(chan struct{})

go func() {
	for e := range ch {
		fmt.Println(e.GetString())
		wait <- struct{}{}
	}
}()

l1.Add("abcdef")

<-wait

ch2 := l1.Watch()
l1.Unwatch(ch)

l2.Join(l1)
l2.Add("ghijk")
l1.Join(l2)

<-ch2

fmt.Println(l1.chans.Count())
Output:

abcdef
1

func (*CoLog) Watch

func (l *CoLog) Watch() <-chan *Entry

Watch returns an Entry chan, notifying you of additions to the log

Example
l1 := New(ipfsdb)
l2 := New(ipfsdb)
l3 := New(ipfsdb)
l4 := New(ipfsdb)

ch := l1.Watch()
wait := make(chan struct{})

go func() {
	for e := range ch {
		fmt.Println(e.GetString())
		wait <- struct{}{}
	}
}()

l1.Add("abcdef")

<-wait

l2.Join(l1)
l2.Add("ghijk")
l1.Join(l2)

<-wait

l3.Join(l1)
e3 := checkadd(l3.Add("lmnop"))

l1.FetchFromHead(e3.Hash)

<-wait

e4 := checkadd(l4.Add("qrstu"))

l1.FetchFromHead(e4.Hash)

<-wait
Output:

abcdef
ghijk
lmnop
qrstu

type Entry

type Entry struct {
	Hash  Hash            `json:"-"`
	Value json.RawMessage `json:"payload"`
	Prev  HashSet         `json:"next"`
}

Entry is an element of the log.

func NewEntry

func NewEntry() *Entry

NewEntry returns a new Entry.

func (*Entry) Get

func (e *Entry) Get(v interface{}) (err error)

Get writes the value that is serialized in the entry into v. v needs to be a pointer.

func (*Entry) GetString

func (e *Entry) GetString() string

GetString returns the string stored in the Entry. If the value stored is not a string, an empty string is returned.

func (*Entry) String

func (e *Entry) String() string

String returns the string representation of the Entry.

type Hash

type Hash string

Hash is the base58 string representation of a multihash

func (Hash) String

func (h Hash) String() string

String returns a Hash's string representation

type HashSet

type HashSet map[Hash]struct{}

HashSet is a set of Hashes

func NewHashSet

func NewHashSet() HashSet

NewHashSet returns a new empty HashSet.

func (HashSet) Add

func (s HashSet) Add(h Hash)

Add adds Hash h to the set

func (HashSet) Contains

func (s HashSet) Contains(h Hash) bool

Contains returns whether Hash h is in the set

func (HashSet) Copy

func (s HashSet) Copy() HashSet

Copy returns a copy of the hash set

func (HashSet) Count

func (s HashSet) Count() int

Count returns the number of elements in s

func (HashSet) Drop

func (s HashSet) Drop(h Hash)

Drop removes Hash h from the set

func (HashSet) MarshalJSON

func (s HashSet) MarshalJSON() ([]byte, error)

MarshalJSON returns the JSON representation of the set

func (HashSet) Sorted

func (s HashSet) Sorted() []Hash

Sorted returns an alphabetically ordered slice of the hashes in the set

func (HashSet) String

func (s HashSet) String() string

String returns the string representation of the set

func (HashSet) UnmarshalJSON

func (s HashSet) UnmarshalJSON(in []byte) error

UnmarshalJSON adds hashes from JSON (usually called on empty sets)

type Index

type Index map[Hash]HashSet

Index maps a hash to a set of hashes.

func (Index) Add

func (i Index) Add(h, g Hash)

Add adds hash g to the set of hashes stored for hash h.

func (Index) Get

func (i Index) Get(h Hash) HashSet

Get returns the set of hashes stored for h.

type Query

type Query struct {
	Before, After QueryBound
}

Query defines which part of the colog should be queried

type QueryBound

type QueryBound struct {
	Hash
	Closed bool // as in closed interval
}

QueryBound defines a bound for a query.

type Result

type Result func() (*Entry, error)

Result is the result of a Query

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL