func (c *Client) write(request *protobuf.Request) chan protobuf.Response { data, err := proto.Marshal(request) if err != nil { log.Printf("Marshaling error: %v\n", err) return nil } length := len(data) lengthBytes := make([]byte, 4) binary.BigEndian.PutUint32(lengthBytes, uint32(length)) // Guarantee squential write of length then protobuf on stream c.connLock.Lock() defer c.connLock.Unlock() _, err = c.conn.Write(lengthBytes) if err != nil { log.Printf("Error writing data: %v\n", err) return nil } _, err = c.conn.Write(data) if err != nil { log.Printf("Error writing data: %v\n", err) return nil } callback := make(chan protobuf.Response) c.pending[request.GetId()] = callback return callback }
func (c *Client) Get(key string) (int, string) { request := new(protobuf.Request) request.Id = proto.String(randomId()) request.Type = proto.String("get") request.Key = proto.String(key) callback := c.write(request) if callback == nil { return -1, "" } // Block on callback response := <-callback return int(response.GetResult()), response.GetValue() }
func (s *Server) run() { for { if conn, err := s.listener.Accept(); err == nil { go func(s *Server, conn net.Conn) { defer conn.Close() log.Println("Connection established with client") for { data := make([]byte, 4) _, err := conn.Read(data) if err != nil { log.Printf("Error reading length: %v", err) return } length := int(binary.BigEndian.Uint32(data)) data = make([]byte, length) for i := 0; i < length; { //Read the data waiting on the connection and put it in the data buffer n, err := conn.Read(data[i : length-i]) i += n if err != nil { log.Printf("Error reading request: %v", err) return } } //Create an struct pointer of type protobuf.Request and protobuf.Response struct request := new(protobuf.Request) //Convert all the data retrieved into the ProtobufTest.TestMessage struct type err = proto.Unmarshal(data[:length], request) if err != nil { log.Printf("Error in Unmarshalling: %v\n", err) return } response := new(protobuf.Response) response.Id = request.Id if request.GetType() == "get" { result, value := s.Get(request.GetKey()) response.Result = proto.Int32(int32(result)) response.Value = proto.String(value) } else { result, value := s.Set(request.GetKey(), request.GetValue()) response.Result = proto.Int32(int32(result)) response.Value = proto.String(value) } data, err = proto.Marshal(response) if err != nil { log.Printf("Marshaling error: %v\n", err) continue } length = len(data) lengthBytes := make([]byte, 4) binary.BigEndian.PutUint32(lengthBytes, uint32(length)) _, err = conn.Write(lengthBytes) if err != nil { log.Printf("Error writing data: %v\n", err) return } _, err = conn.Write(data) if err != nil { log.Printf("Error writing data: %v\n", err) return } } }(s, conn) } else { continue } } }