// Interface towards the Grapher func (self *latestTransformer) TransformClientMutation(mutation grapher.MutationNode, concurrent <-chan grapher.MutationNode) (err os.Error) { mut, e := decodeGenericMutation(mutation) if e != nil { log.Printf("Err: Decoding") return e } // If any of these is later, then the mutation is transformed into the epsilon operation for m := range concurrent { if m.Time() > mut.Time { mutation.SetOperation([]byte("null")) return } } return }
func (self *channelAPI) Blob_Mutation(perma grapher.PermaNode, mutation grapher.MutationNode) { mutJson := map[string]interface{}{"perma": perma.BlobRef(), "seq": mutation.SequenceNumber(), "type": "mutation", "signer": mutation.Signer(), "entity": mutation.EntityBlobRef(), "field": mutation.Field(), "time": mutation.Time()} switch mutation.Operation().(type) { case []ot.StringOperation: op := mutation.Operation().([]ot.StringOperation) // The following two lines work around a problem in GO/JSON mutJson["op"] = &op case []byte: msg := json.RawMessage(mutation.Operation().([]byte)) mutJson["op"] = &msg default: panic("Unsupported operation kind") } schema, err := json.Marshal(mutJson) if err != nil { panic(err.String()) } if self.bufferOnly { self.messageBuffer = append(self.messageBuffer, string(schema)) } else { err = self.forwardToFollowers(perma.BlobRef(), string(schema)) } if err != nil { log.Printf("Err Forward: %v", err) } }
// Interface towards the Grapher func (self *latestTransformer) TransformMutation(mutation grapher.MutationNode, rollback <-chan grapher.MutationNode, concurrent []string) (err os.Error) { mut, e := decodeGenericMutation(mutation) if e != nil { return e } // Get a list of all concurrent mutations conc := make(map[string]bool) for _, id := range concurrent { conc[id] = true } for m := range rollback { // Skip those which are not concurrent if _, ok := conc[m.BlobRef()]; !ok { continue } if m.Time() > mut.Time { mutation.SetOperation([]byte("null")) return } } return }
// TODO: Perform type checking for other data types. This one does only strings func decodeGenericMutation(mutation grapher.MutationNode) (mut latestMutation, err os.Error) { switch mutation.Operation().(type) { case []byte: buffer := []byte(`{"op":`) buffer = append(buffer, mutation.Operation().([]byte)...) buffer = append(buffer, []byte("}")...) var val stringDummy err = json.Unmarshal(buffer, &val) if err != nil { return mut, err } mut.Operation = val.Value default: mut.Operation = mutation.Operation() } mut.Time = mutation.Time() return }