예제 #1
0
파일: header.go 프로젝트: appaquet/gostore
func (lfh *LocalFileHeader) Save() {
	// TODO: Fix this double marshalling!

	bytes, err := json.Marshal(lfh.header)

	if err != nil {
		log.Error("Couldn't marshal header: %s", err)
	}

	file, err := os.Create(lfh.headerpath)
	if err != nil {
		log.Error("Couldn't save header file for %s: %s", lfh.headerpath, err)

	} else {
		n, err := file.Write(lfh.header.ToJSON())

		if n != len(bytes) {
			log.Error("Didn't write all header data: written %n bytes", n)
		}

		if err != nil {
			log.Error("Couldn't save file header: %s", err)
		}
	}

	file.Close()
}
예제 #2
0
func (fss *FsService) replicationWatcher() {
	for fss.running {
		if fss.replQueue.Len() > 0 {
			fss.replQueueMutex.Lock()
			if fss.replQueue.Len() > 0 {
				next := fss.replQueue.Front()
				fss.replQueue.Remove(next)
				fss.replQueueMutex.Unlock()

				path := next.Value.(*Path)
				localheader := fss.headers.GetFileHeader(path)

				log.Info("%d: FSS: Starting replica download for path %s version %d...", fss.cluster.MyNode.Id, path, localheader.header.Version)

				// TODO: Make sure we don't download the same replica twice...

				// check if the file doesn't already exist locally
				file := OpenFile(fss, localheader, 0)
				if !file.Exists() {
					// TODO: Use config to get temp path
					tempfile := fmt.Sprintf("%s/%d.%d.%d.data", os.TempDir(), path.Hash(), time.Nanoseconds(), localheader.header.Version)

					fd, err := os.Create(tempfile)
					if err == nil {
						_, err = fss.Read(path, 0, -1, 0, fd, nil)
						fd.Close()
						if err == nil {
							os.Rename(tempfile, file.datapath)
							log.Info("%d: FSS: Successfully replicated %s version %d locally", fss.cluster.MyNode.Id, path, localheader.header.Version)

						} else {
							log.Error("%d: FSS: Couldn't replicate file %s locally because couldn't read: %s", fss.cluster.MyNode.Id, path, err)
						}

					} else {
						log.Error("%d: FSS: Couldn't open temporary file %s to download replica localy for path %s", fss.cluster.MyNode.Id, tempfile, path)
						os.Remove(tempfile)
					}

				} else {
					log.Info("%d: FSS: Local replica for %s version %d already exist", fss.cluster.MyNode.Id, path, localheader.header.Version)
				}

			} else {
				fss.replQueueMutex.Unlock()
			}

		} else {
			// if no more replica in the queue, stop replica force
			if fss.replQueue.Len() == 0 {
				fss.replForce = false
			}
		}

		// TODO: Put that in configuration
		if !fss.replForce {
			time.Sleep(100 * 1000 * 1000)
		}
	}
}
예제 #3
0
파일: server.go 프로젝트: appaquet/gostore
func (s *Server) acceptUDP() {
	// Looping for new messages
	for {
		buf := make([]byte, MAX_MSG_SIZE)
		n, adr, err := s.udpsock.ReadFrom(buf)

		if s.comm.running {
			if err != nil {
				log.Error("Error while reading UDP (read %d) from %s: %s\n", n, adr, err)

			} else {
				abcon := net.Conn(s.udpsock)
				connection := NewConnection(s.comm.pool, P_UDP, D_Inbound, abcon)
				read := io.Reader(bytes.NewBuffer(buf))
				msg := s.comm.NewMessage()
				msg.connection = connection
				err := msg.readMessage(read)

				if err != nil {
					log.Error("Couldn't handle message received from UDP because of errors: %s %s\n", msg, err)
				} else {
					go s.comm.handleMessage(msg)
				}
			}
		} else {
			log.Info("Dropping connection because communications have been paused")
		}
	}
}
예제 #4
0
func (fss *FsService) sendToReplicaNode(resolv *cluster.ResolveResult, req_cb func(node *cluster.Node) *comm.Message) chan os.Error {
	toSyncCount := resolv.Count() - 1 // minus one for the master
	var syncError os.Error = nil
	myNodeId := fss.cluster.MyNode.Id
	errChan := make(chan os.Error, 1) // channel used to return data to the messageor
	c := make(chan bool, toSyncCount) // channel used to wait for all replicas

	if toSyncCount > 0 {
		go func() {
			for i := 0; i < resolv.Count(); i++ {
				node := resolv.Get(i)

				if node.Status == cluster.Status_Online && node.Id != myNodeId {
					// get the new message
					req := req_cb(node)

					req.Timeout = 1000 // TODO: Config
					req.OnResponse = func(message *comm.Message) {
						log.Debug("%d: FSS: Received acknowledge message for message %s\n", fss.cluster.MyNode.Id, req)
						c <- true
					}
					req.OnTimeout = func(last bool) (retry bool, handled bool) {
						// TODO: Retry it!
						syncError = comm.ErrorTimeout
						log.Error("%d: FSS: Couldn't send message to replicate node %s because of a timeout for message %s\n", fss.cluster.MyNode.Id, node, req)
						c <- true

						return true, false
					}
					req.OnError = func(message *comm.Message, syncError os.Error) {
						log.Error("%d: FSS: Received an error while sending to replica %s for message %s: %d %s\n", fss.cluster.MyNode.Id, req, node, syncError)
						c <- true
					}

					fss.comm.SendNode(node, req)
				}
			}

			// wait for nodes to sync the handoff
			for i := 0; i < toSyncCount; i++ {
				<-c
			}

			errChan <- syncError
		}()
	} else {
		errChan <- nil
	}

	return errChan
}
예제 #5
0
파일: config.go 프로젝트: appaquet/gostore
func (c Config) Save(path string) {
	bytes, err := json.Marshal(c)

	if err != nil {
		log.Error("Couldn't save config: %s", err)
	}

	fc, err := os.Create(path)
	_, err = fc.Write(bytes)

	if err != nil {
		log.Error("Couldn't write config: %s", err)
	}
}
예제 #6
0
파일: config.go 프로젝트: appaquet/gostore
func LoadConfig(path string) Config {
	config := new(Config)

	fc, err := os.Open(path)
	if err != nil {
		log.Error("Couldn't load config file: %s", err)
	}

	buf := new(bytes.Buffer)
	buf.ReadFrom(fc)

	strOrigConfig := string(buf.Bytes())
	strFinConfig := ""
	lines := strings.Split(strOrigConfig, "\n", -1)
	for _, line := range lines {
		trimedLine := strings.TrimSpace(line)
		if len(trimedLine) < 2 || trimedLine[:2] != "//" {
			strFinConfig += trimedLine
		}
	}

	err = json.Unmarshal([]byte(strFinConfig), config)

	if err != nil {
		log.Fatal("Couldn't unmarshal config: %s %s", strFinConfig, err)
	}

	return *config
}
예제 #7
0
파일: service.go 프로젝트: appaquet/gostore
func (cs *ClusterService) RemoteContactMaster(msg *comm.Message) {
	myNode := cs.cluster.MyNode
	log.Debug("%d: Got a ContactMaster request: %s", myNode.Id, msg)

	if cs.state == state_online {
		masters := cs.cluster.Rings.GetRing(cs.masterRing).ResolveToken(master_token)

		// make sure I'm the master, and online
		if myNode.Status == cluster.Status_Online && masters.IsFirst(myNode) {
			node := cluster.NewEmptyNode()
			err := node.Unserialize(msg.Message)
			if err != nil {
				cs.comm.RespondError(msg, os.NewError("Couldn't unmarshal node data"))
				log.Error("Couldn't unmarshal node data: %s", err)
				return
			}

			node.Status = cluster.Status_Online
			cs.cluster.MergeNode(node, true)

			// TODO: Send the cluster back to the node
			resp := cs.comm.NewMsgMessage(cs.serviceId)
			cs.comm.RespondSource(msg, resp)
			//log.Fatal("BLABLA", node.Id)

			// TODO: LOCK SO THAT WE DON'T MAKE IT ONLINE TWICE

			// TODO: Accept the node
			// TODO: Check its rings
			// TODO: Broadcast the change
		} else {
			cs.comm.RedirectFirst(masters, msg)
		}
	}
}
예제 #8
0
파일: segment.go 프로젝트: appaquet/gostore
func (s *segment) replay(db *Db) (err os.Error) {
	log.Info("Replaying segment %s", s)

	entrych, errch := s.iter(0)

	end := false
	count := 0
	for !end {
		select {
		case entry, ok := <-entrych:
			if ok {
				count++
				err = entry.mutation.execute(db, true) // execute mutation (for replay)
				if err != nil {
					log.Error("Got an error replaying a mutation: %s", err)
					return
				}
			} else {
				end = true
			}

		case segerr, ok := <-errch:
			if ok {
				return segerr
			} else {
				end = true
			}
		}
	}

	log.Info("Segment %s replayed: %d mutations replayed", s, count)

	return
}
예제 #9
0
파일: header.go 프로젝트: appaquet/gostore
func (f *FileHeader) ToJSON() []byte {
	bytes, err := json.Marshal(f)
	if err != nil {
		log.Error("Couldn't marshal header: %s", err)
	}

	return bytes
}
예제 #10
0
파일: service.go 프로젝트: appaquet/gostore
func (fss *FsService) Unlock(key string) {
	mutex, found := fss.mutexes[key]
	if !found {
		log.Error("FSS: Couldn't find file mutex to unlock for key %s\n", key)
		return
	}

	mutex.Unlock()
}
예제 #11
0
파일: file.go 프로젝트: appaquet/gostore
func (f *File) Size() int64 {
	dir, err := os.Stat(f.datapath)
	if err != nil {
		log.Error("Cannot stat data file: %s\n", f.path)
	} else {
		return dir.Size
	}

	return 0
}
예제 #12
0
파일: server.go 프로젝트: appaquet/gostore
// Returns an API Server
func NewServer(handler Handler, adr string) *Server {
	server := new(Server)
	server.handler = handler
	server.servmux = http.NewServeMux()

	con, err := net.Listen("tcp", adr)
	if err != nil {
		log.Error("API: Couldn't create listener socket: %s\n", err)
	}

	// Add handling function at root, delegating everything to the handler
	server.servmux.HandleFunc("/", func(httpresp http.ResponseWriter, httpreq *http.Request) {
		log.Debug("API: Connection on url %s\n", httpreq.URL)

		resp := &ResponseWriter{httpresp}

		var req *Request
		if req = NewRequest(resp, httpreq); req == nil {
			log.Error("API: Couldn't create request object")
			return
		}

		handler.Handle(resp, req)

		// TODO: Remove that! Shouldn't be here!!
		// Read the rest, so we don't cause Broken Pipe on the other end if we don't read to the end
		ioutil.ReadAll(req.Body)
	})

	// Start serving the API on another thread
	go func() {
		log.Debug("API: Starting API server on adr %s\n", adr)
		err = http.Serve(con, server.servmux)
		con.Close()

		if err != nil {
			log.Fatal("API: Serve error: ", err.String())
		}
	}()

	return server
}
예제 #13
0
// Returns an interface marshaled in JSON
func (r *ResponseWriter) ReturnJSON(v interface{}) {

	bytes, err := json.Marshal(v)
	if err != nil {
		log.Error("API: Couldn't marshall JSON response: %s\n", err)
	}

	r.Header().Set("Content-Type", "application/json")
	//r.SetHeader("Content-Type", "application/json")
	r.Write(bytes)
}
예제 #14
0
파일: header.go 프로젝트: appaquet/gostore
func LoadFileHeaderFromJSON(bytes []byte) *FileHeader {
	fh := new(FileHeader)
	errtok := json.Unmarshal(bytes, fh)

	if errtok != nil {
		fh = new(FileHeader)
		log.Error("Couldn't load file header: %s, %s", errtok, bytes)
	}

	return fh
}
예제 #15
0
파일: api.go 프로젝트: appaquet/gostore
func (api *api) get(resp *rest.ResponseWriter, req *rest.Request, path *Path) {
	log.Debug("FSS API: Received a read request for path %s\n", path)

	// TODO: Handle offset
	// TODO: Handle version
	// TODO: Handle size
	_, err := api.fss.Read(path, 0, -1, 0, resp, nil)
	log.Debug("API: Fs Read data returned\n")
	if err != nil && err != os.EOF {
		log.Error("API: Fs Read returned an error for %s: %s\n", path, err)
		resp.ReturnError(err.String())
	}
}
예제 #16
0
파일: api.go 프로젝트: appaquet/gostore
func (api *api) head(resp *rest.ResponseWriter, req *rest.Request, path *Path) {
	log.Debug("FSS API: Received a head request for path %s\n", path)

	header, err := api.fss.HeaderJSON(path, nil)

	resp.Write(header)

	log.Debug("API: Fs Header data returned\n")
	if err != nil {
		log.Error("API: Fs header returned an error: %s\n", err)
		resp.ReturnError(err.String())
	}
}
예제 #17
0
파일: server.go 프로젝트: appaquet/gostore
func (s *Server) acceptTCP() {
	for {
		conn, err := s.tcpsock.Accept()
		if s.comm.running {
			if err != nil {
				log.Error("Couldn't accept TCP connexion: %s\n", err)
			}

			go s.handleTCPConnection(conn)
		} else {
			log.Info("Dropping connection because communications have been paused")
		}
	}
}
예제 #18
0
파일: pool.go 프로젝트: appaquet/gostore
func (p *Pool) GetMsgConnection(node *cluster.Node) *Connection {
	// TODO: IMPLEMENT THE POOLING

	adr := net.UDPAddr{node.Address, int(node.UdpPort)}
	con, err := net.DialUDP("udp", nil, &adr) // TODO: should use local address instead of nil (implicitly local)
	if err != nil {
		log.Error("NETPOOL: Couldn't create a connection\n", err)
		return nil
	}

	abcon := net.Conn(con)
	connection := NewConnection(p, P_UDP, D_Outbound, abcon)
	return connection
}
예제 #19
0
파일: server.go 프로젝트: appaquet/gostore
func (s *Server) handleTCPConnection(conn net.Conn) {
	connection := NewConnection(s.comm.pool, P_TCP, D_Inbound, conn)

	reader := io.Reader(conn)
	msg := s.comm.NewMessage()
	msg.connection = connection
	err := msg.readMessage(reader)

	if err != nil {
		log.Error("Couldn't handle message received from TCP because of errors: %s %s\n", msg, err)
		conn.Close() // Close the connection to make sure we don't cause error
	} else {
		s.comm.handleMessage(msg)
	}
}
예제 #20
0
파일: request.go 프로젝트: appaquet/gostore
// Returns a new request composed of the original http.Request structure
func NewRequest(r *ResponseWriter, httpreq *http.Request) *Request {
	req := new(Request)
	req.Request = httpreq

	// try to parse the URL
	params, err := http.ParseQuery(httpreq.URL.RawQuery)
	if err != nil {
		log.Error("API: Couldn't parse GET parameters: %s\n", err)
		r.ReturnError("Parameters error")
		return nil
	}
	req.Params = params

	return req
}
예제 #21
0
파일: api.go 프로젝트: appaquet/gostore
func (api *api) delete(resp *rest.ResponseWriter, req *rest.Request, path *Path) {
	log.Debug("FSS API: Received a delete request for %s\n", path)

	recursive := false
	mrec, ok := req.Params["recursive"]
	if ok {
		recursive = (mrec[0] == "1") || (mrec[0] == "true")
	}

	err := api.fss.Delete(path, recursive, nil)
	if err != nil {
		log.Error("API: Fs Write returned an error: %s\n", err)
		resp.ReturnError(err.String())
	}
}
예제 #22
0
func (fss *FsService) RemoteChildRemove(message *comm.Message) {
	str, _ := message.Message.ReadString() // path
	path := NewPath(str)
	child, _ := message.Message.ReadString() // child

	log.Debug("FSS: Received message to remove the child %s from %s\n", child, path)

	// resolve path
	mynode := fss.cluster.MyNode
	resolv := fss.ring.Resolve(path.String())

	// only the master has the lock
	if resolv.IsFirst(mynode) {
		fss.Lock(path.String())
	}

	localheader := fss.headers.GetFileHeader(path)
	localheader.header.RemoveChild(child)

	if resolv.IsFirst(mynode) {
		// replicate to nodes
		syncChan := fss.sendToReplicaNode(resolv, func(node *cluster.Node) *comm.Message {
			msg := fss.comm.NewMsgMessage(fss.serviceId)
			msg.Function = "RemoteChildRemove"

			msg.Message.WriteString(path.String()) // path
			msg.Message.WriteString(child)         // child name

			return msg
		})

		// wait for replicas sync
		syncError := <-syncChan

		// check for sync error
		if syncError != nil {
			log.Error("FSS: Couldn't replicate remove child to nodes: %s\n", syncError)
			fss.comm.RespondError(message, os.NewError("Couldn't replicate remove child to all nodes"))
		}

		// unlock
		fss.Unlock(path.String())
	}

	// Send an acknowledgement
	msg := fss.comm.NewMsgMessage(fss.serviceId)
	fss.comm.RespondSource(message, msg)
}
예제 #23
0
파일: api.go 프로젝트: appaquet/gostore
func (api *api) post(resp *rest.ResponseWriter, req *rest.Request, path *Path) {
	log.Debug("FSS API: Received a write request for %d bytes\n", req.ContentLength)

	mimetype := "application/octet-stream"
	mtar, ok := req.Params["type"]
	if ok {
		mimetype = mtar[0]
	}

	err := api.fss.Write(path, req.ContentLength, mimetype, req.Body, nil)
	if err != nil {
		log.Error("API: Fs Write returned an error: %s\n", err)
		resp.ReturnError(err.String())
	}

	log.Debug("API: Fs Write returned\n")
}
예제 #24
0
파일: comm.go 프로젝트: appaquet/gostore
func (comm *Comm) handleMessage(message *Message) {
	// TODO: We should make sure we don't handle a message twice (since UDP can duplicate packets)

	if message.FunctionId == FUNC_ERROR {
		log.Info("Comm: Received an error: %s\n", message)
	}

	// Check if the message needed an acknowledgement or check if
	// it has an error callback
	handled := false
	if message.SourceNode().Equals(comm.Cluster.MyNode) {
		handled = comm.handleTracker(message)
	}

	// Service #0 is net and there is no implementation yet.
	// Function = RESPONSE should be handled by callback
	if message.ServiceId != 0 && message.FunctionId != FUNC_RESPONSE && !handled {
		serviceWrapper := comm.GetWrapper(message.ServiceId)

		if serviceWrapper.service != nil {
			// if its an error
			if message.FunctionId == FUNC_ERROR {
				err := ReadErrorPayload(message)
				message.SeekZero()
				serviceWrapper.service.HandleUnmanagedError(message, err)
			} else {
				// call the right function
				handled := serviceWrapper.callFunction(message.FunctionId, message)

				if !handled {
					serviceWrapper.service.HandleUnmanagedMessage(message)
				}
			}
		} else {
			log.Error("Comm: Couldn't find service for message %s\n", message)
		}
	}
}
예제 #25
0
func (cs *ClusterService) loadCluster() {
	cs.clusterMutex.Lock()

	// Load data
	log.Debug("cls: Loading cluster data...")
	stat, err := os.Stat(cs.clsDataPath)
	if err == nil && stat.IsRegular() {
		file, err := os.Open(cs.clsDataPath)
		if err == nil {
			typedFile := typedio.NewReader(file)

			cs.clusterVersion, _ = typedFile.ReadInt64() // cluster version
			cs.diskVerson = cs.clusterVersion

			nbNodes, _ := typedFile.ReadUint16() // nodes count
			var i uint16
			for i = 0; i < nbNodes; i++ {
				node := cluster.NewEmptyNode()
				node.Unserialize(typedFile)

				node.Status = cluster.Status_Offline

				cs.cluster.MergeNode(node, false) // merge node, doesn't notify
			}

		} else {
			log.Error("cls: Error while opening data file", err)
		}
	}

	// replay commit log
	log.Info("cls: Replaying commit log...")
	cs.commitlog.Replay()

	// TODO: Load cluster data

	cs.clusterMutex.Unlock()
}
예제 #26
0
파일: header.go 프로젝트: appaquet/gostore
func NewLocalFileHeader(headerpath string) *LocalFileHeader {
	lfh := new(LocalFileHeader)
	lfh.headerpath = headerpath

	file, err := os.Open(lfh.headerpath)

	// no error
	if err == nil {
		lfh.header = LoadFileHeader(file)
	} else {
		if ptherror, ok := err.(*os.PathError); ok && ptherror.Error == os.ENOENT {
			// if file doesn't exists, we don't show an error
			lfh.header = NewFileHeader()
		} else {
			lfh.header = NewFileHeader()
			log.Error("Couldn't load header file for %s: %d", lfh.headerpath, err)
		}

	}

	file.Close()

	return lfh
}
예제 #27
0
파일: service.go 프로젝트: appaquet/gostore
func (cs *ClusterService) HandleUnmanagedMessage(msg *comm.Message) {
	log.Error("CS: Got an unmanaged message: %s", msg)
}
예제 #28
0
파일: message.go 프로젝트: appaquet/gostore
func (r *Message) writeMessage(writer io.Writer) (err os.Error) {
	twriter := typedio.NewWriter(writer)

	err = twriter.WriteUint16(r.Id) // message id
	if err != nil {
		return
	}

	// prepare flags
	var flags byte
	if r.InitId != 0 {
		flags = flags | prm_has_init_msg_id
	}

	if r.Type == T_DATA {
		flags = flags | prm_is_data
	}

	if r.srcNodeAdhoc {
		flags = flags | prm_src_node_adhoc
	}

	if r.middleNodePresent {
		flags = flags | prm_has_middle_node
	}

	if r.middleNodeAdhoc {
		flags = flags | prm_middle_node_adhoc
	}

	err = twriter.WriteUint8(flags) // flags
	if err != nil {
		return
	}

	if r.InitId != 0 {
		err = twriter.WriteUint16(r.InitId) // initial message id
		if err != nil {
			return
		}
	}

	err = twriter.WriteUint8(r.ServiceId) // service id
	if err != nil {
		return
	}

	msgSize := uint16(r.Message.Size)
	err = twriter.WriteUint16(msgSize) // message size
	if err != nil {
		return
	}

	if r.Type == T_DATA {
		twriter.WriteInt64(r.DataSize) // data size
		if err != nil {
			return
		}
	}

	if r.srcNodeAdhoc { // source node information
		err = twriter.WriteString(r.srcNodeAdr.String()) // addr
		if err != nil {
			return
		}

		err = twriter.WriteUint16(r.srcNodeTcpPort) // tcp port
		if err != nil {
			return
		}

		err = twriter.WriteUint16(r.srcNodeUdpPort) // udp port
		if err != nil {
			return
		}

	} else {
		err = twriter.WriteUint16(r.srcNodeId) // node id
		if err != nil {
			return
		}
	}

	if r.middleNodePresent { // middle node information
		if r.middleNodeAdhoc {
			err = twriter.WriteString(r.middleNodeAdr.String()) // addr
			if err != nil {
				return
			}

			err = twriter.WriteUint16(r.middleNodeTcpPort) // tcp port
			if err != nil {
				return
			}

			err = twriter.WriteUint16(r.middleNodeUdpPort) // udp port
			if err != nil {
				return
			}

		} else {
			err = twriter.WriteUint16(r.middleNodeId) // node id
			if err != nil {
				return
			}
		}
	}

	err = twriter.WriteUint8(r.FunctionId) // function id
	if err != nil {
		return
	}

	// Write message
	r.Message.Seek(0, 0)
	w, err := io.Copyn(writer, r.Message, r.Message.Size) // message

	if err != nil {
		log.Error("Couldn't write message message to writer: %s\n", err)
		return err
	}

	if w != int64(msgSize) {
		log.Error("Couldn't write the whole message message to write: written %d out of %d\n", w, msgSize)
		return os.NewError("Message write truncated")
	}

	// Write data
	if r.Type == T_DATA {
		io.Copyn(writer, r.Data, r.DataSize) // data
	}

	return nil
}
예제 #29
0
파일: message.go 프로젝트: appaquet/gostore
func (r *Message) readMessage(reader io.Reader) (err os.Error) {
	treader := typedio.NewReader(reader)

	r.Id, err = treader.ReadUint16() // message id
	if err != nil {
		return
	}

	flags, err := treader.ReadUint8() // flags
	if err != nil {
		return
	}

	hasInitId := false
	if flags&prm_has_init_msg_id == prm_has_init_msg_id {
		hasInitId = true
	}

	if flags&prm_is_data == prm_is_data {
		r.Type = T_DATA
	} else {
		r.Type = T_MSG
	}

	if flags&prm_src_node_adhoc == prm_src_node_adhoc {
		r.srcNodeAdhoc = true
	}

	if flags&prm_has_middle_node == prm_has_middle_node {
		r.middleNodePresent = true
	}

	if flags&prm_middle_node_adhoc == prm_middle_node_adhoc {
		r.middleNodeAdhoc = true
	}

	if hasInitId {
		r.InitId, err = treader.ReadUint16() // initial message id
		if err != nil {
			return
		}
	}

	r.ServiceId, err = treader.ReadUint8() // service id
	if err != nil {
		return
	}

	msgSize, err := treader.ReadUint16() // message size
	if err != nil {
		return
	}

	if r.Type == T_DATA {
		r.DataSize, err = treader.ReadInt64() // data size
		if err != nil {
			return
		}
	}

	if r.srcNodeAdhoc { // source node information
		adr, err := treader.ReadString() // addr
		if err != nil {
			return
		}
		r.srcNodeAdr = net.ParseIP(adr)

		r.srcNodeTcpPort, err = treader.ReadUint16() // tcp port
		if err != nil {
			return
		}

		r.srcNodeUdpPort, err = treader.ReadUint16() // udp port
		if err != nil {
			return
		}
	} else {
		r.srcNodeId, err = treader.ReadUint16() // node id
		if err != nil {
			return
		}
	}

	// TODO: Adhoc
	if r.middleNodePresent {
		if r.middleNodeAdhoc {
			adr, err := treader.ReadString() // addr
			if err != nil {
				return
			}
			r.middleNodeAdr = net.ParseIP(adr)

			r.middleNodeTcpPort, err = treader.ReadUint16() // tcp port
			if err != nil {
				return
			}

			r.middleNodeUdpPort, err = treader.ReadUint16() // udp port
			if err != nil {
				return
			}
		} else {
			r.middleNodeId, err = treader.ReadUint16() // node id
			if err != nil {
				return
			}
		}
	}

	r.FunctionId, err = treader.ReadUint8() // function id
	if err != nil {
		return
	}

	// Load message
	r.Message = buffer.NewWithSize(int64(msgSize), false) // message
	n, err := io.Copyn(r.Message, reader, int64(msgSize))
	r.Message.Seek(0, 0)

	if err != nil {
		log.Error("COMM: Got an error reading message from message: %s", err)
		return err
	}

	if n != int64(msgSize) {
		log.Error("COMM: Couldn't read the whole message. Read %d out of %d", n, msgSize)
		return os.NewError("Message truncated")
	}

	// release the connection if its a message
	if r.Type == T_MSG {
		r.Release()
	} else {
		r.Data = reader
	}

	return nil
}
예제 #30
0
파일: service.go 프로젝트: appaquet/gostore
func (cs *ClusterService) HandleUnmanagedError(errorMessage *comm.Message, error os.Error) {
	log.Error("CS: Got an unmanaged error: %s", errorMessage)
}