func (self *permaNode) applyPermission(newnode *permissionNode) (err os.Error) { // Find out how far back we have to go in history to find a common anchor point for transformation h := ot.NewHistoryGraph(self.frontier, newnode.Dependencies()) reverse_permissions := []*permissionNode{} prune := map[string]bool{} // Need to rollback? if !h.Test() { // Go back in history until our history is equal to (or earlier than) that of 'mut'. // On the way remember which mutations of our history do not belong to the // history of 'mut' because these must be pruned. ch, err := self.grapher.getOTNodesDescending(self.BlobRef()) if err != nil { return err } for history_node := range ch { if !h.SubstituteBlob(history_node.BlobRef(), history_node.Dependencies()) { prune[history_node.BlobRef()] = true } if x, ok := history_node.(*permissionNode); ok { reverse_permissions = append(reverse_permissions, x) } if h.Test() { break } } } // Reverse the mutation history, such that oldest are first in the list. // This is ugly but prepending in the above loops is too slow. permissions := make([]*permissionNode, len(reverse_permissions)) for i := 0; i < len(permissions); i++ { permissions[i] = reverse_permissions[len(reverse_permissions)-1-i] } // Prune all mutations that have been applied locally but do not belong to the history of the new mutation pnodes, e := prunePermissionSeq(permissions, prune) if e != nil { log.Printf("Prune Error: %v\n", e) err = e return } // Transform 'newnode' to apply it locally pnodes = append(pnodes, newnode) for _, n := range permissions { if n.BlobRef() != pnodes[0].BlobRef() { pnodes, _, err = transformPermissionSeq(pnodes, n) if err != nil { log.Printf("TRANSFORM ERR: %v", err) return } } else { pnodes = pnodes[1:] } } *newnode = *pnodes[0] bits, ok := self.permissions[newnode.User] if !ok { bits = 0 } bits, err = ot.ExecutePermission(bits, newnode.Permission) if err == nil { self.permissions[newnode.User] = bits } return }
func (self *otHistory) Apply(newnode otNode) (deps []string, err os.Error) { // The mutation has already been applied? if self.HasApplied(newnode.BlobRef()) { return } // Are all dependencies satisfied, i.e. are all mutations // on which mut depends already processed by the builder? unsatisfied := false for _, dep := range newnode.Dependencies() { if !self.HasApplied(dep) { unsatisfied = true deps = append(deps, dep) } } if unsatisfied { return deps, nil } // Find out how far back we have to go in history to find a common anchor point for transformation frontier := self.Frontier() h := ot.NewHistoryGraph(frontier, newnode.Dependencies()) reverse_nodes := []otNode{} prune := map[string]bool{} // Need to rollback? if !h.Test() { // Go back in history until our history is equal to (or earlier than) that of 'mut'. // On the way remember which mutations of our history do not belong to the // history of 'mut' because these must be pruned. for x := range self.History(true) { history_node := x.(otNode) if !h.SubstituteBlob(history_node.BlobRef(), history_node.Dependencies()) { prune[history_node.BlobRef()] = true } reverse_nodes = append(reverse_nodes, history_node) if h.Test() { break } } } // Reverse the mutation history, such that oldest are first in the list. // This is ugly but prepending in the above loops is too slow. nodes := make([]otNode, len(reverse_nodes)) for i := 0; i < len(nodes); i++ { nodes[i] = reverse_nodes[len(reverse_nodes)-1-i] } // Prune all mutations that have been applied locally but do not belong to the history of the new mutation pnodes, e := pruneSeq(nodes, prune) if e != nil { log.Printf("Prune Error: %v\n", e) err = e return } // Transform 'mut' to apply it locally pnodes = append(pnodes, newnode) for _, n := range nodes { if n.BlobRef() != pnodes[0].BlobRef() { pnodes, _, err = transformSeq(pnodes, n) if err != nil { log.Printf("TRANSFORM ERR: %v", err) return } } else { pnodes = pnodes[1:] } } newnode = pnodes[0] // Apply the mutation if mut, ok := newnode.(*mutationNode); ok { mut.mutation.AppliedAt = len(self.appliedBlobs) } self.appliedBlobs = append(self.appliedBlobs, newnode.BlobRef()) self.members[newnode.BlobRef()] = newnode self.frontier.AddBlob(newnode.BlobRef(), newnode.Dependencies()) if mut, ok := newnode.(*mutationNode); ok { self.content, err = ot.Execute(self.content, mut.mutation) } else if perm, ok := newnode.(*permissionNode); ok { bits, ok := self.permissions[perm.permission.User] if !ok { bits = 0 } bits, err = ot.ExecutePermission(bits, perm.permission) if err == nil { self.permissions[perm.permission.User] = bits } } return }