Exemplo n.º 1
0
func Connect(target string) (Client, error) {
	conn, err := net.Dial("tcp", target)
	if err != nil {
		return nil, err
	}
	// hanshake
	_, cmd, _, err := network.Receive(conn)
	if err != nil {
		return nil, err
	}

	ch := make(chan PendingOperation)

	c := &NetworkClient{connectionId: *cmd.Header.ConnectionID,
		userId:   USER_ID,
		secret:   CLIENT_SECRET,
		sequence: 1,
		conn:     conn,
		closed:   false,
		error:    nil,
		notifier: ch}

	go c.listen(ch)
	return c, nil
}
Exemplo n.º 2
0
func (self *NetworkClient) listen(notifications <-chan PendingOperation) {
	pending := make(map[int64]PendingOperation) // pendings
	for {
		_, cmd, value, err := network.Receive(self.conn)
		if err != nil {
			if !self.closed {
				self.error = err
				// TODO: try closing socket
			}
			break
		}

		var response error
		if *cmd.Status.Code != kproto.Command_Status_SUCCESS {
			response = RemoteError{status: *cmd.Status}
		}

		// Notify caller
		// Seems more complicated than it should, but we are optimizing
		// for when we receive in order
		for {
			op := <-notifications
			// Chances are, it's in order
			if op.sequence == *cmd.Header.AckSequence {
				if *cmd.Status.Code == kproto.Command_Status_SUCCESS {
					// Status SUCCESS
					switch *cmd.Header.MessageType {
					case kproto.Command_GET_RESPONSE:
						// GET
						op.value <- value
					case kproto.Command_GETVERSION_RESPONSE:
						// Get Version
						op.value <- cmd.Body.KeyValue.DbVersion
					case kproto.Command_GETNEXT_RESPONSE:
						// Get Next
						op.value <- cmd.Body.KeyValue.Key
					case kproto.Command_GETPREVIOUS_RESPONSE:
						// Get Previous
						op.value <- cmd.Body.KeyValue.Key
					case kproto.Command_GETKEYRANGE_RESPONSE:
						// Get Key Range
						op.array <- cmd.Body.Range.Keys
					default:
						// PUT, DELETE
						op.receiver <- response // TODO: send back the actual response
					}
				} else {
					// Status FAILURE
					op.receiver <- response // TODO: send back the actual response
				}
				break
			} else {
				// Either we missed it or it hasnt arrived yet.
				pending[op.sequence] = op
				op, ok := pending[*cmd.Header.AckSequence]
				if ok { // this is the case where we missed it
					op.receiver <- response
					delete(pending, op.sequence)
					break
				}
			}
		}
	}

	// Notify all pendings that we are closed for business
}