Example #1
0
// 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
}
Example #2
0
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)
	}
}
Example #3
0
// 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
}
Example #4
0
// 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
}