Skip to content
This repository has been archived by the owner on Mar 31, 2019. It is now read-only.

Commit

Permalink
addressing race condition on sync/node
Browse files Browse the repository at this point in the history
  • Loading branch information
zabawaba99 committed Oct 23, 2016
1 parent 132c3d1 commit 6788375
Showing 1 changed file with 23 additions and 3 deletions.
26 changes: 23 additions & 3 deletions sync/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import (
"reflect"
"strconv"
"strings"
"sync"
)

// Node represents an object linked in Database. This object
// should not be created by hand, use NewNode when creating
// a new instance of Node.
type Node struct {
mtx sync.RWMutex
Key string
Value interface{}
Children map[string]*Node
Expand All @@ -23,10 +25,13 @@ type Node struct {
// NewNode converts the given data into a node.
func NewNode(key string, data interface{}) *Node {
n := &Node{
Key: key,
Children: map[string]*Node{},
Key: key,
}

n.mtx.Lock()
n.Children = map[string]*Node{}
n.mtx.Unlock()

if data == nil {
return n
}
Expand Down Expand Up @@ -78,7 +83,10 @@ func (n *Node) MarshalJSON() ([]byte, error) {
// If a node was created from a slice initially, a slice will be return.
// If a node has child nodes, a map will be returned.
// Otherwise, a primitive type will be returned.
func (n Node) Objectify() interface{} {
func (n *Node) Objectify() interface{} {
n.mtx.RLock()
defer n.mtx.RUnlock()

if n.isNil() {
return nil
}
Expand Down Expand Up @@ -111,6 +119,9 @@ func (n Node) Objectify() interface{} {
// The relative path can either be a simple child key (e.g. 'fred') or a deeper
// slash-separated path (e.g. 'fred/name/first').
func (n *Node) Child(name string) (*Node, bool) {
n.mtx.RLock()
defer n.mtx.RUnlock()

name = strings.Trim(name, "/")
rabbitHole := strings.Split(name, "/")

Expand All @@ -128,17 +139,26 @@ func (n *Node) Child(name string) (*Node, bool) {
}

func (n *Node) isNil() bool {
n.mtx.RLock()
defer n.mtx.RUnlock()

return n.Value == nil && len(n.Children) == 0
}

func (n *Node) merge(newNode *Node) {
n.mtx.Lock()
defer n.mtx.Unlock()

for k, v := range newNode.Children {
n.Children[k] = v
}
n.Value = newNode.Value
}

func (n *Node) prune() *Node {
n.mtx.Lock()
defer n.mtx.Unlock()

if len(n.Children) > 0 || n.Value != nil {
return nil
}
Expand Down

0 comments on commit 6788375

Please sign in to comment.