Example #1
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 #2
0
func (self *Grapher) CreateEntityBlob(perma_blobref string, mimeType string, content []byte) (node AbstractNode, err os.Error) {
	perma, e := self.permaNode(perma_blobref)
	if e != nil {
		err = e
		return
	}
	c := json.RawMessage(content)
	deps := perma.frontier.IDs()
	entityJson := map[string]interface{}{"signer": self.userID, "perma": perma_blobref, "content": &c, "dep": deps, "mimetype": mimeType}
	entityBlob, err := json.Marshal(entityJson)
	if err != nil {
		panic(err.String())
	}
	entityBlob = append([]byte(`{"type":"entity",`), entityBlob[1:]...)
	log.Printf("Storing entity %v\n", string(entityBlob))
	entityBlobRef := newBlobRef(entityBlob)
	// Process it
	var schema superSchema
	schema.Type = "entity"
	schema.Signer = self.userID
	schema.PermaNode = perma_blobref
	schema.Content = &c
	schema.MimeType = mimeType
	schema.Dependencies = deps
	_, node, err = self.handleSchemaBlob(&schema, entityBlobRef)
	return
}
Example #3
0
func (self *Replication) getnHandlerIntern(prefix string, conn *Connection) {
	channel, err := self.store.GetBlobs(prefix)
	if err != nil {
		log.Printf("Error while talking to store: %v\n", err)
		return
	}
	for blob := range channel {
		log.Printf("sendblob %v\n", blob.BlobRef)
		conn.Send("BLOB", json.RawMessage(blob.Data))
	}
}
Example #4
0
// Called from the store when a new blob has been stored
func (self *Replication) HandleBlob(blob []byte, blobref string) os.Error {
	for connection, flags := range self.connections {
		if flags&connStreaming == connStreaming {
			// Do not send the blob on the same connection on which it has been received
			if !connection.hasReceivedBlob(blobref) {
				connection.Send("BLOB", json.RawMessage(blob))
			}
		}
	}
	return nil
}
Example #5
0
func (self *Replication) getnxHandlerIntern(prefix string, except map[string]bool, conn *Connection) {
	channel, err := self.store.GetBlobs(prefix)
	if err != nil {
		log.Printf("Error while talking to store: %v\n", err)
		return
	}
	for blob := range channel {
		if _, ok := except[blob.BlobRef]; ok {
			continue
		}
		conn.Send("BLOB", json.RawMessage(blob.Data))
	}
}
Example #6
0
func (self *channelAPI) Blob_Entity(perma grapher.PermaNode, entity grapher.EntityNode) {
	entityJson := map[string]interface{}{"perma": perma.BlobRef(), "seq": entity.SequenceNumber(), "type": "entity", "signer": entity.Signer(), "mimetype": entity.MimeType(), "blobref": entity.BlobRef()}
	msg := json.RawMessage(entity.Content())
	entityJson["content"] = &msg
	schema, err := json.Marshal(entityJson)
	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 #7
0
func (self *Message) EncodePayload(data interface{}) os.Error {
	if data == nil {
		self.Payload = nil
		return nil
	}
	if raw, ok := data.(json.RawMessage); ok {
		self.Payload = &raw
		return nil
	}
	bytes, err := json.Marshal(data)
	if err != nil {
		return err
	}
	p := json.RawMessage(bytes)
	self.Payload = &p
	return nil
}
Example #8
0
// Handles the 'GET' command
func (self *Replication) getHandler(msg Message) {
	var blobref string
	if msg.DecodePayload(&blobref) != nil {
		log.Printf("Error in GET request")
		return
	}
	blob, err := self.store.GetBlob(blobref)
	if err != nil {
		log.Printf("Error while talking to store: %v\n", err)
		return
	}
	// TODO: If this is not a JSON blob ...
	err = msg.connection.Send("BLOB", json.RawMessage(blob))
	if err != nil {
		log.Printf("Error while sending %v\n", err)
	}
}
Example #9
0
	}
	// PkgPath will be non-empty even for an exported type,
	// so we need to check the type name as well.
	return isExported(t.Name()) || t.PkgPath() == ""
}

// ----------------------------------------------------------------------------
// Server
// ----------------------------------------------------------------------------

// A value sent as a placeholder for the response when the server receives
// an invalid request.
type InvalidRequest struct{}

var invalidRequest = InvalidRequest{}
var null = json.RawMessage([]byte("null"))

type JsonRequest struct {
	// A String containing the name of the method to be invoked.
	Method string `json:"method"`
	// An Array of objects to pass as arguments to the method.
	Params *json.RawMessage `json:"params"`
	// The request id. This can be of any type. It is used to match the
	// response with the request that it is replying to.
	Id *json.RawMessage `json:"id"`
}

type JsonResponse struct {
	// The Object that was returned by the invoked method. This must be null
	// in case there was an error invoking the method.
	Result interface{} `json:"result"`
Example #10
0
func (self *Grapher) CreateMutationBlob(perma_blobref string, entity_blobref string, field string, operation []byte, applyAtSeqNumber int64) (node AbstractNode, err os.Error) {
	perma, e := self.permaNode(perma_blobref)
	if e != nil {
		err = e
		return
	}
	entity, e := self.entity(perma.BlobRef(), entity_blobref)
	if e != nil {
		err = e
		return
	}
	transformer, e := self.transformer(perma, entity, field)
	if e != nil {
		err = e
		return
	}
	// Update the operation such that it can be applied after all currently applied operations
	m := &mutationNode{}
	m.permaBlobRef = perma_blobref
	m.mutationBlobRef = "Z" // This ensures that the client mutation looses against all server mutations. The client-side must handle it the same.
	m.mutationSigner = self.userID
	m.entityBlobRef = entity_blobref
	m.field = field
	m.operation = operation
	m.time = time.Seconds()
	if transformer != nil {
		ch, e := self.getMutationsAscending(perma.BlobRef(), entity_blobref, field, applyAtSeqNumber, perma.SequenceNumber())
		if e != nil {
			err = e
			return
		}
		e = transformer.TransformClientMutation(m, ch)
		if e != nil {
			err = e
			return
		}
	}
	deps := perma.frontier.IDs()
	mutJson := map[string]interface{}{"signer": self.userID, "perma": perma_blobref, "dep": deps, "entity": entity_blobref, "field": field}
	var msg json.RawMessage
	switch m.operation.(type) {
	case ot.StringOperation:
		op := m.operation.(ot.StringOperation) // The following two lines work around a problem in GO/JSON
		op_bytes, err := op.MarshalJSON()
		if err != nil {
			return nil, err
		}
		msg = json.RawMessage(op_bytes)
	case []byte:
		msg = json.RawMessage(m.operation.([]byte))
	default:
		panic("Unsupported operation kind")
	}
	mutJson["op"] = &msg
	schema, err := json.Marshal(mutJson)
	if err != nil {
		panic(err.String())
	}
	mutBlob := []byte(`{"type":"mutation",`)
	mutBlob = append(mutBlob, schema[1:]...)
	log.Printf("Storing mut %v\n", string(mutBlob))
	mutBlobRef := newBlobRef(mutBlob)
	// Process it
	var schema2 superSchema
	schema2.Type = "mutation"
	schema2.Signer = self.userID
	schema2.PermaNode = perma_blobref
	schema2.Dependencies = deps
	schema2.Entity = entity_blobref
	schema2.Field = field
	schema2.Operation = &msg
	_, node, err = self.handleSchemaBlob(&schema2, mutBlobRef)
	return
}
Example #11
0
// Handles the 'TCHLD' command
func (self *Replication) treeHashChildrenHandler(msg Message) {
	req := struct {
		Prefix   string   "prefix"
		Kind     int      "kind"
		Children []string "chld"
	}{}
	var prefix string
	// This is a request?
	if msg.DecodePayload(&prefix) == nil {
		req.Kind, req.Children, _ = self.store.HashTree().Children(prefix)
		req.Prefix = prefix
		msg.connection.Send("TCHLD", &req)
		return
	}
	if msg.DecodePayload(&req) != nil {
		log.Printf("Error in TCHL message")
		return
	}

	kind1, children1, prefix := req.Kind, req.Children, req.Prefix
	kind2, children2, err := self.store.HashTree().Children(prefix)
	if kind1 == HashTree_NIL || kind2 == HashTree_NIL || err != nil {
		log.Printf("Comparison of hash trees failed: prefix=%v, kind1=%v, kind2=%v, err=%v\n", prefix, kind1, kind2, err)
		return
	}

	// Turn a list of strings into a map of strings for further efficient processing
	map1 := map[string]bool{}
	for _, ch := range children1 {
		map1[ch] = true
	}
	map2 := map[string]bool{}
	for _, ch := range children2 {
		map2[ch] = true
	}

	if kind1 == HashTree_IDs && kind2 == HashTree_IDs {
		// Both returned hashes. Compare the two sets of hashes
		for key, _ := range map1 {
			if _, ok := map2[key]; !ok {
				msg.connection.Send("GET", key)
			}
		}
		for key, _ := range map2 {
			if _, ok := map1[key]; !ok {
				blob, err := self.store.GetBlob(key)
				if err != nil {
					log.Printf("Retrieving block %v failed\n", key)
				} else {
					msg.connection.Send("BLOB", json.RawMessage(blob))
				}
			}
		}
	} else if kind1 == HashTree_InnerNodes && kind2 == HashTree_InnerNodes {
		// Both returned subtree nodes? Recursion into the sub tree nodes
		for i := 0; i < HashTree_NodeDegree; i++ {
			if children1[i] == children2[i] {
				continue
			}
			p := prefix + string(hextable[i])
			if children1[i] == "" {
				self.getnHandlerIntern(p, msg.connection)
			} else if children2[i] == "" {
				// Get all blobs with this prefix
				msg.connection.Send("GETN", p)
			} else {
				// Recursion
				msg.connection.Send("TCHLD", p)
			}
		}
	} else if kind1 == HashTree_InnerNodes && kind2 == HashTree_IDs {
		for i := 0; i < HashTree_NodeDegree; i++ {
			// Get all blox with this prefix (except those in map1) from the other side
			p := prefix + string(hextable[i])
			lst := []string{}
			for key, _ := range map1 {
				lst = append(lst, key)
			}
			r := struct {
				Prefix string   "prefix"
				Except []string "except"
			}{p, lst}
			msg.connection.Send("GETNX", &r)
		}
	} else {
		for i := 0; i < HashTree_NodeDegree; i++ {
			// Send all blobs with this prefix (except those in map2) to the other side
			p := prefix + string(hextable[i])
			self.getnxHandlerIntern(p, map2, msg.connection)
		}
	}
}