Skip to content

Commit

Permalink
refactor DAG, setting the number of roots when DAG is created
Browse files Browse the repository at this point in the history
  • Loading branch information
TATAUFO committed Mar 4, 2020
1 parent d6440e8 commit 999963e
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 23 deletions.
22 changes: 12 additions & 10 deletions core/universe.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func NewUniverse(Eve, Adam *User) (*Universe, error) {
if err != nil {
return nil, err
}
userD, err := dag.NewDAG(EveVertex, AdamVertex)
userD, err := dag.NewDAG(2, EveVertex, AdamVertex)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -202,7 +202,7 @@ func (u *Universe) initializeSpaceTime(msgSpaceTime *Message, ref *MsgReference)
return err
}
if u.stD == nil {
stD, err := dag.NewDAG(stVertex)
stD, err := dag.NewDAG(1, stVertex)
if err != nil {
return err
}
Expand Down Expand Up @@ -280,7 +280,7 @@ func (u *Universe) initializeMsgD(msg *Message) error {
if err != nil {
return err
}
msgD, err := dag.NewDAG(msgVertex)
msgD, err := dag.NewDAG(1, msgVertex)
if err != nil {
return err
}
Expand All @@ -306,7 +306,7 @@ func (u *Universe) createSpaceTime(msg *Message, ref *MsgReference) (*SpaceTime,
if err != nil {
return nil, err
}
timeProofDag, err := dag.NewDAG(timeVertex)
timeProofDag, err := dag.NewDAG(1, timeVertex)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -347,7 +347,7 @@ func (u *Universe) createSpaceTime(msg *Message, ref *MsgReference) (*SpaceTime,
}

func (u Universe) createUserStateD(st *SpaceTime, ref *MsgReference) (*dag.DAG, error) {
newUserStateD, err := dag.NewDAG()
newUserStateD, err := dag.NewDAG(2)
if err != nil {
return nil, err
}
Expand All @@ -367,6 +367,7 @@ func (u Universe) createUserStateD(st *SpaceTime, ref *MsgReference) (*dag.DAG,
if err != nil {
return nil, err
}

newUserStateD.AddVertex(userStateVertex)
}
return newUserStateD, nil
Expand All @@ -376,18 +377,20 @@ func (u *Universe) updateTimeProof(msg *Message) error {
if vertex := u.stD.GetVertex(msg.SenderID); vertex != nil {
st := vertex.Value().(*SpaceTime)
var currentSeq uint64 = 1
var ref interface{}
for _, r := range msg.Reference {
if r.SenderID == msg.SenderID {
refVertex := st.timeProofD.GetVertex(r.MsgID)
if refVertex != nil {
refSeq := refVertex.Value().(uint64)
if currentSeq <= refSeq {
currentSeq = refSeq + 1
ref = r.MsgID
}
}
}
}
timeVertex, err := dag.NewVertex(msg.ID(), currentSeq)
timeVertex, err := dag.NewVertex(msg.ID(), currentSeq, ref)
if err != nil {
return err
}
Expand Down Expand Up @@ -421,13 +424,12 @@ func (u *Universe) addUserByMsg(msg *Message) error {
userAdded := false
for _, ref := range msg.Reference {
if err := u.addUserToSpaceTime(ref, dobContent, user); err != nil {

continue
} else {
// at least add into one space time
userAdded = true
}
// at least add into one space time
userAdded = true
}

if !userAdded {
return errNewUserAddFail
}
Expand Down
3 changes: 2 additions & 1 deletion core/universe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import (
"encoding/json"
"errors"
"fmt"
"testing"

"github.com/pdupub/go-pdu/common"
"github.com/pdupub/go-pdu/common/log"
"github.com/pdupub/go-pdu/core/rule"
"github.com/pdupub/go-pdu/crypto"
"testing"
)

var (
Expand Down
51 changes: 41 additions & 10 deletions dag/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,51 +34,73 @@ import (

var (
errRootVertexParentsExist = errors.New("root vertex parents exist")
errRootNumberOutOfRange = errors.New("root number is out of range")
errVertexAlreadyExist = errors.New("vertex already exist")
errVertexNotExist = errors.New("vertex not exist")
errVertexHasChildren = errors.New("vertex has children")
errVertexParentNotExist = errors.New("parent not exist")
errVertexParentNumberOutOfRange = errors.New("parent number is out of range")
)

const (
defaultMaxParentsCount = 255
)

// DAG is directed acyclic graph
type DAG struct {
mu sync.Mutex
maxParentsCount int // 0 = unlimited
maxParentsCount int
strict bool
store map[interface{}]*Vertex
ids []interface{}
rufd uint // unfilled root count
}

// NewDAG create new DAG by root vertexes
func NewDAG(rootVertex ...*Vertex) (*DAG, error) {
func NewDAG(rootCnt uint, rootVertex ...*Vertex) (*DAG, error) {
dag := &DAG{
store: make(map[interface{}]*Vertex),
ids: []interface{}{},
maxParentsCount: defaultMaxParentsCount,
strict: true,
store: make(map[interface{}]*Vertex),
ids: []interface{}{},
rufd: rootCnt,
}
for _, vertex := range rootVertex {
if len(vertex.Parents()) == 0 {
if dag.rufd == 0 {
return nil, errRootNumberOutOfRange
} else if len(vertex.Parents()) == 0 {
dag.store[vertex.ID()] = vertex
dag.ids = append(dag.ids, vertex.ID())
dag.rufd--
} else {
return nil, errRootVertexParentsExist
}
}
return dag, nil
}

// IsStrict return if all parents must exist when add vertex
func (d *DAG) IsStrict() bool {
return d.strict
}

// SetStrict set if the parents rule is strict or not
func (d *DAG) SetStrict(b bool) {
d.strict = b
}

// SetMaxParentsCount set the max number of parents one vertex can get
func (d *DAG) SetMaxParentsCount(maxCount int) {
d.maxParentsCount = maxCount
}

// GetMaxParentsCount get the max number of parents
func (d DAG) GetMaxParentsCount() int {
func (d *DAG) GetMaxParentsCount() int {
return d.maxParentsCount
}

// GetVertex can get vertex by ID
func (d *DAG) GetVertex(id interface{}) *Vertex {

if _, ok := d.store[id]; !ok {
return nil
}
Expand All @@ -94,14 +116,23 @@ func (d *DAG) AddVertex(vertex *Vertex) error {
return errVertexAlreadyExist
}

if d.maxParentsCount != 0 && len(vertex.Parents()) > d.maxParentsCount {
if len(vertex.Parents()) > d.maxParentsCount {
return errVertexParentNumberOutOfRange
}
// check parents cloud be found
sequenceExist := false
for _, pid := range vertex.Parents() {
if _, ok := d.store[pid]; !ok {
return errVertexParentNotExist
}
sequenceExist = true
}
if !sequenceExist {
if d.rufd == 0 {
return errRootNumberOutOfRange
} else {
d.rufd--
}
}
// add vertex into store
d.store[vertex.ID()] = vertex
Expand Down Expand Up @@ -141,12 +172,12 @@ func (d *DAG) DelVertex(id interface{}) error {
}

// GetIDs get id list of DAG
func (d DAG) GetIDs() []interface{} {
func (d *DAG) GetIDs() []interface{} {
return d.ids
}

// String is used to print the DAG content
func (d DAG) String() string {
func (d *DAG) String() string {
result := fmt.Sprintf("maxParentsCount : %d - storeSize : %d \n", d.maxParentsCount, len(d.store))
for k, v := range d.store {
result += fmt.Sprintf("k = %v \n", k)
Expand Down
46 changes: 44 additions & 2 deletions dag/dag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
func TestDAG_AddVertex(t *testing.T) {
v1, _ := NewVertex("id-1", "hello world")
v2, _ := NewVertex("id-2", "hello you")
dag, err := NewDAG(v1, v2)
dag, err := NewDAG(2, v1, v2)
if err != nil {
t.Errorf("create DAG fail , err : %s", err)
}
Expand Down Expand Up @@ -66,10 +66,52 @@ func TestDAG_AddVertex(t *testing.T) {
}
}

func TestDAG_AddVertex2(t *testing.T) {
v1, _ := NewVertex("id-1", "hello world")
v2, _ := NewVertex("id-2", "hello you")

dag, err := NewDAG(3)
if err != nil {
t.Errorf("create DAG fail , err : %s", err)
}

if len(dag.GetIDs()) != 0 {
t.Errorf("id number not match, should be %d, dag getIDs is %d", 0, dag.GetIDs())
}

if err := dag.AddVertex(v1); err != nil {
t.Errorf("add vertex fail, err : %s", err)
}

if err := dag.AddVertex(v2); err != nil {
t.Errorf("add vertex fail, err : %s", err)
}

v3, _ := NewVertex("id-3", "hello you", v1, v2)
if err := dag.AddVertex(v3); err != nil {
t.Errorf("add vertex fail, err : %s", err)
}

v4, _ := NewVertex("id-4", "hello you", v1, v3)
if err := dag.AddVertex(v4); err != nil {
t.Errorf("add vertex fail, err : %s", err)
}

v5, _ := NewVertex("id-5", "hello you too")
if err := dag.AddVertex(v5); err != nil {
t.Errorf("add vertex fail, err : %s", err)
}

v6, _ := NewVertex("id-6", "hello you too")
if err := dag.AddVertex(v6); err != errRootNumberOutOfRange {
t.Errorf("add vertex should fail, err should be %s not %s", errRootNumberOutOfRange, err)
}
}

func TestDAG_DelVertex(t *testing.T) {
v1, _ := NewVertex("id-1", "hello world")
v2, _ := NewVertex("id-2", "hello you")
dag, err := NewDAG(v1, v2)
dag, err := NewDAG(2, v1, v2)
if err != nil {
t.Errorf("create DAG fail , err : %s", err)
}
Expand Down

0 comments on commit 999963e

Please sign in to comment.