Beispiel #1
0
func (s *boltStmt) QueryPipeline(params ...map[string]interface{}) (PipelineRows, error) {
	if s.closed {
		return nil, errors.New("Neo4j Bolt statement already closed")
	}
	if s.rows != nil {
		return nil, errors.New("Another query is already open")
	}

	if len(params) != len(s.queries) {
		return nil, errors.New("Must pass same number of params as there are queries")
	}

	for i, query := range s.queries {
		err := s.conn.sendRunPullAll(query, params[i])
		if err != nil {
			return nil, errors.Wrap(err, "Error running query:\n\n%s\n\nWith Params:\n%#v", query, params[i])
		}
	}

	log.Info("Successfully ran all pipeline queries")

	resp, err := s.conn.consume()
	if err != nil {
		return nil, errors.Wrap(err, "An error occurred consuming initial pipeline command")
	}

	success, ok := resp.(messages.SuccessMessage)
	if !ok {
		return nil, errors.New("Got unexpected return message when consuming initial pipeline command: %#v", resp)
	}

	s.rows = newPipelineRows(s, success.Metadata, 0)
	return s.rows, nil
}
Beispiel #2
0
// NextNeo gets the next row result
// When the rows are completed, returns the success metadata
// and io.EOF
func (r *boltRows) NextNeo() ([]interface{}, map[string]interface{}, error) {
	if r.closed {
		return nil, nil, errors.New("Rows are already closed")
	}

	if !r.consumed {
		r.consumed = true
		if err := r.statement.conn.sendPullAll(); err != nil {
			r.finishedConsume = true
			return nil, nil, err
		}
	}

	respInt, err := r.statement.conn.consume()
	if err != nil {
		return nil, nil, err
	}

	switch resp := respInt.(type) {
	case messages.SuccessMessage:
		log.Infof("Got success message: %#v", resp)
		r.finishedConsume = true
		return nil, resp.Metadata, io.EOF
	case messages.RecordMessage:
		log.Infof("Got record message: %#v", resp)
		return resp.Fields, nil, nil
	default:
		return nil, nil, errors.New("Unrecognized response type getting next query row: %#v", resp)
	}
}
func (d Decoder) decodeNode(buffer *bytes.Buffer) (graph.Node, error) {
	node := graph.Node{}

	nodeIdentityInt, err := d.decode(buffer)
	if err != nil {
		return node, err
	}
	node.NodeIdentity = nodeIdentityInt.(int64)

	labelInt, err := d.decode(buffer)
	if err != nil {
		return node, err
	}
	labelIntSlice, ok := labelInt.([]interface{})
	if !ok {
		return node, errors.New("Expected: Labels []string, but got %T %+v", labelInt, labelInt)
	}
	node.Labels, err = sliceInterfaceToString(labelIntSlice)
	if err != nil {
		return node, err
	}

	propertiesInt, err := d.decode(buffer)
	if err != nil {
		return node, err
	}
	node.Properties, ok = propertiesInt.(map[string]interface{})
	if !ok {
		return node, errors.New("Expected: Properties map[string]interface{}, but got %T %+v", propertiesInt, propertiesInt)
	}

	return node, nil

}
Beispiel #4
0
// Rollback rolls back and closes the transaction
func (t *boltTx) Rollback() error {
	if t.closed {
		return errors.New("Transaction already closed")
	}
	if t.conn.statement != nil {
		if err := t.conn.statement.Close(); err != nil {
			return errors.Wrap(err, "An error occurred closing open rows in transaction Rollback")
		}
	}

	successInt, pullInt, err := t.conn.sendRunPullAllConsumeSingle("ROLLBACK", nil)
	if err != nil {
		return errors.Wrap(err, "An error occurred rolling back transaction")
	}

	success, ok := successInt.(messages.SuccessMessage)
	if !ok {
		return errors.New("Unrecognized response type rolling back transaction: %#v", success)
	}

	log.Infof("Got success message rolling back transaction: %#v", success)

	pull, ok := pullInt.(messages.SuccessMessage)
	if !ok {
		return errors.New("Unrecognized response type pulling transaction: %#v", pull)
	}

	log.Infof("Got success message pulling transaction: %#v", pull)

	t.conn.transaction = nil
	t.closed = true
	return err
}
func (d Decoder) decodeUnboundRelationship(buffer *bytes.Buffer) (graph.UnboundRelationship, error) {
	rel := graph.UnboundRelationship{}

	relIdentityInt, err := d.decode(buffer)
	if err != nil {
		return rel, err
	}
	rel.RelIdentity = relIdentityInt.(int64)

	var ok bool
	typeInt, err := d.decode(buffer)
	if err != nil {
		return rel, err
	}
	rel.Type, ok = typeInt.(string)
	if !ok {
		return rel, errors.New("Expected: Type string, but got %T %+v", typeInt, typeInt)
	}

	propertiesInt, err := d.decode(buffer)
	if err != nil {
		return rel, err
	}
	rel.Properties, ok = propertiesInt.(map[string]interface{})
	if !ok {
		return rel, errors.New("Expected: Properties map[string]interface{}, but got %T %+v", propertiesInt, propertiesInt)
	}

	return rel, nil
}
Beispiel #6
0
// Begin begins a new transaction with the Neo4J Database
func (c *boltConn) Begin() (driver.Tx, error) {
	if c.transaction != nil {
		return nil, errors.New("An open transaction already exists")
	}
	if c.statement != nil {
		return nil, errors.New("Cannot open a transaction when you already have an open statement")
	}
	if c.closed {
		return nil, errors.New("Connection already closed")
	}

	successInt, pullInt, err := c.sendRunPullAllConsumeSingle("BEGIN", nil)
	if err != nil {
		return nil, errors.Wrap(err, "An error occurred beginning transaction")
	}

	success, ok := successInt.(messages.SuccessMessage)
	if !ok {
		return nil, errors.New("Unrecognized response type beginning transaction: %#v", success)
	}

	log.Infof("Got success message beginning transaction: %#v", success)

	success, ok = pullInt.(messages.SuccessMessage)
	if !ok {
		return nil, errors.New("Unrecognized response type pulling transaction:  %#v", success)
	}

	log.Infof("Got success message pulling transaction: %#v", success)

	return newTx(c), nil
}
// Write to the net conn, recording the interaction
func (r *recorder) Write(b []byte) (n int, err error) {
	if r.Conn != nil {
		numWritten, err := r.Conn.Write(b)
		if numWritten > 0 {
			r.record(b[:numWritten], true)
		}

		if err != nil {
			r.recordErr(err, true)
		}

		return numWritten, err
	}

	if r.currentEvent >= len(r.events) {
		return 0, errors.New("Trying to write past all of the events in the recorder! %#v", r)
	}
	event := r.events[r.currentEvent]
	if !event.IsWrite {
		return 0, errors.New("Recorder expected Write, got Read! %#v, Event: %#v", r, event)
	}

	for i := 0; i < len(b); i++ {
		if len(event.Event) == 0 {
			return i, errors.New("Attempted to write past current event in recorder! %#v, Event: %#v", r, event)
		}
		event.Event = event.Event[1:]
	}

	if len(event.Event) == 0 {
		r.currentEvent++
	}

	return len(b), nil
}
Beispiel #8
0
// ExecNeo executes a query that returns no rows. Implements a Neo-friendly alternative to sql/driver.
func (s *boltStmt) ExecNeo(params map[string]interface{}) (Result, error) {
	if s.closed {
		return nil, errors.New("Neo4j Bolt statement already closed")
	}
	if s.rows != nil {
		return nil, errors.New("Another query is already open")
	}

	runResp, pullResp, _, err := s.conn.sendRunPullAllConsumeAll(s.query, params)
	if err != nil {
		return nil, err
	}

	success, ok := runResp.(messages.SuccessMessage)
	if !ok {
		return nil, errors.New("Unrecognized response type when running exec query: %#v", success)

	}

	log.Infof("Got run success message: %#v", success)

	success, ok = pullResp.(messages.SuccessMessage)
	if !ok {
		return nil, errors.New("Unrecognized response when discarding exec rows: %#v", success)
	}

	log.Infof("Got discard all success message: %#v", success)

	return newResult(success.Metadata), nil
}
Beispiel #9
0
// PreparePipeline prepares a new pipeline statement for a query.
func (c *boltConn) PreparePipeline(queries ...string) (PipelineStmt, error) {
	if c.statement != nil {
		return nil, errors.New("An open statement already exists")
	}
	if c.closed {
		return nil, errors.New("Connection already closed")
	}
	c.statement = newPipelineStmt(queries, c)
	return c.statement, nil
}
Beispiel #10
0
func (c *boltConn) prepare(query string) (*boltStmt, error) {
	if c.statement != nil {
		return nil, errors.New("An open statement already exists")
	}
	if c.closed {
		return nil, errors.New("Connection already closed")
	}
	c.statement = newStmt(query, c)
	return c.statement, nil
}
Beispiel #11
0
func (c *boltConn) parseURL() (*url.URL, error) {
	user := ""
	password := ""
	url, err := url.Parse(c.connStr)
	if err != nil {
		return url, errors.Wrap(err, "An error occurred parsing bolt URL")
	} else if strings.ToLower(url.Scheme) != "bolt" {
		return url, errors.New("Unsupported connection string scheme: %s. Driver only supports 'bolt' scheme.", url.Scheme)
	}

	if url.User != nil {
		c.user = url.User.Username()
		var isSet bool
		c.password, isSet = url.User.Password()
		if !isSet {
			return url, errors.New("Must specify password when passing user")
		}
	}

	timeout := url.Query().Get("timeout")
	if timeout != "" {
		timeoutInt, err := strconv.Atoi(timeout)
		if err != nil {
			return url, errors.New("Invalid format for timeout: %s.  Must be integer", timeout)
		}

		c.timeout = time.Duration(timeoutInt) * time.Second
	}

	useTLS := url.Query().Get("tls")
	c.useTLS = strings.HasPrefix(strings.ToLower(useTLS), "t") || useTLS == "1"

	if c.useTLS {
		c.certFile = url.Query().Get("tls_cert_file")
		c.keyFile = url.Query().Get("tls_key_file")
		c.caCertFile = url.Query().Get("tls_ca_cert_file")
		noVerify := url.Query().Get("tls_no_verify")
		c.tlsNoVerify = strings.HasPrefix(strings.ToLower(noVerify), "t") || noVerify == "1"
	}

	log.Trace("Bolt Host: ", url.Host)
	log.Trace("Timeout: ", c.timeout)
	log.Trace("User: "******"Password: "******"TLS: ", c.useTLS)
	log.Trace("TLS No Verify: ", c.tlsNoVerify)
	log.Trace("Cert File: ", c.certFile)
	log.Trace("Key File: ", c.keyFile)
	log.Trace("CA Cert File: ", c.caCertFile)

	return url, nil
}
Beispiel #12
0
func (c *boltConn) ExecPipeline(queries []string, params ...map[string]interface{}) ([]Result, error) {
	if c.statement != nil {
		return nil, errors.New("An open statement already exists")
	}
	if c.closed {
		return nil, errors.New("Connection already closed")
	}

	stmt := newPipelineStmt(queries, c)
	defer stmt.Close()

	return stmt.ExecPipeline(params...)
}
Beispiel #13
0
// Exec executes a query that returns no rows. See sql/driver.Stmt.
// You must bolt encode a map to pass as []bytes for the driver value
func (c *boltConn) Exec(query string, args []driver.Value) (driver.Result, error) {
	if c.statement != nil {
		return nil, errors.New("An open statement already exists")
	}
	if c.closed {
		return nil, errors.New("Connection already closed")
	}

	stmt := newStmt(query, c)
	defer stmt.Close()

	return stmt.Exec(args)
}
Beispiel #14
0
// ExecNeo executes a query that returns no rows. Implements a Neo-friendly alternative to sql/driver.
func (c *boltConn) ExecNeo(query string, params map[string]interface{}) (Result, error) {
	if c.statement != nil {
		return nil, errors.New("An open statement already exists")
	}
	if c.closed {
		return nil, errors.New("Connection already closed")
	}

	stmt := newStmt(query, c)
	defer stmt.Close()

	return stmt.ExecNeo(params)
}
Beispiel #15
0
func (s *boltStmt) ExecPipeline(params ...map[string]interface{}) ([]Result, error) {
	if s.closed {
		return nil, errors.New("Neo4j Bolt statement already closed")
	}
	if s.rows != nil {
		return nil, errors.New("Another query is already open")
	}

	if len(params) != len(s.queries) {
		return nil, errors.New("Must pass same number of params as there are queries")
	}

	for i, query := range s.queries {
		err := s.conn.sendRunPullAll(query, params[i])
		if err != nil {
			return nil, errors.Wrap(err, "Error running exec query:\n\n%s\n\nWith Params:\n%#v", query, params[i])
		}
	}

	log.Info("Successfully ran all pipeline queries")

	results := make([]Result, len(s.queries))
	for i := range s.queries {
		runResp, err := s.conn.consume()
		if err != nil {
			return nil, errors.Wrap(err, "An error occurred getting result of exec command: %#v", runResp)
		}

		success, ok := runResp.(messages.SuccessMessage)
		if !ok {
			return nil, errors.New("Unexpected response when getting exec query result: %#v", runResp)
		}

		_, pullResp, err := s.conn.consumeAll()
		if err != nil {
			return nil, errors.Wrap(err, "An error occurred getting result of exec discard command: %#v", pullResp)
		}

		success, ok = pullResp.(messages.SuccessMessage)
		if !ok {
			return nil, errors.New("Unexpected response when getting exec query discard result: %#v", pullResp)
		}

		results[i] = newResult(success.Metadata)

	}

	return results, nil
}
// Read out the object bytes to decode
func (d Decoder) read() (*bytes.Buffer, error) {
	output := &bytes.Buffer{}
	for {
		lengthBytes := make([]byte, 2)
		if numRead, err := d.r.Read(lengthBytes); numRead != 2 {
			return nil, errors.Wrap(err, "Couldn't read expected bytes for message length. Read: %d Expected: 2.", numRead)
		}

		// Chunk header contains length of current message
		messageLen := binary.BigEndian.Uint16(lengthBytes)
		if messageLen == 0 {
			// If the length is 0, the chunk is done.
			return output, nil
		}

		data, err := d.readData(messageLen)
		if err != nil {
			return output, errors.Wrap(err, "An error occurred reading message data")
		}

		numWritten, err := output.Write(data)
		if numWritten < len(data) {
			return output, errors.New("Didn't write full data on output. Expected: %d Wrote: %d", len(data), numWritten)
		} else if err != nil {
			return output, errors.Wrap(err, "Error writing data to output")
		}
	}
}
// RowsAffected returns the number of nodes+rels created/deleted.  For reasons of limitations
// on the API, we cannot tell how many nodes+rels were updated, only how many properties were
// updated.  If this changes in the future, number updated will be added to the output of this
// interface.
func (r boltResult) RowsAffected() (int64, error) {
	stats, ok := r.metadata["stats"].(map[string]interface{})
	if !ok {
		return -1, errors.New("Unrecognized type for stats metadata: %#v", r.metadata)
	}

	var rowsAffected int64
	nodesCreated, ok := stats["nodes-created"]
	if ok {
		rowsAffected += nodesCreated.(int64)
	}

	relsCreated, ok := stats["relationships-created"]
	if ok {
		rowsAffected += relsCreated.(int64)
	}

	nodesDeleted, ok := stats["nodes-deleted"]
	if ok {
		rowsAffected += nodesDeleted.(int64)
	}

	relsDeleted, ok := stats["relationships-deleted"]
	if ok {
		rowsAffected += relsDeleted.(int64)
	}

	return rowsAffected, nil
}
Beispiel #18
0
func (c *boltConn) ackFailure(failure messages.FailureMessage) error {
	log.Infof("Acknowledging Failure: %#v", failure)

	ack := messages.NewAckFailureMessage()
	err := encoding.NewEncoder(c, c.chunkSize).Encode(ack)
	if err != nil {
		return errors.Wrap(err, "An error occurred encoding ack failure message")
	}

	for {
		respInt, err := encoding.NewDecoder(c).Decode()
		if err != nil {
			return errors.Wrap(err, "An error occurred decoding ack failure message response")
		}

		switch resp := respInt.(type) {
		case messages.IgnoredMessage:
			log.Infof("Got ignored message when acking failure: %#v", resp)
			continue
		case messages.SuccessMessage:
			log.Infof("Got success message when acking failure: %#v", resp)
			return nil
		case messages.FailureMessage:
			log.Errorf("Got failure message when acking failure: %#v", resp)
			return c.reset()
		default:
			log.Errorf("Got unrecognized response from acking failure: %#v", resp)
			err := c.Close()
			if err != nil {
				log.Errorf("An error occurred closing the session: %s", err)
			}
			return errors.New("Got unrecognized response from acking failure: %#v. CLOSING SESSION!", resp)
		}
	}
}
// Encode encodes an object to the stream
func (e Encoder) encode(iVal interface{}) error {

	var err error
	if iVal == nil {
		return e.encodeNil()
	}
	rv := reflect.ValueOf(iVal)
	switch rv.Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		err = e.encodeInt(int64(rv.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		err = e.encodeInt(int64(rv.Uint()))
	case reflect.Float32, reflect.Float64:
		err = e.encodeFloat(rv.Float())
	case reflect.Bool:
		err = e.encodeBool(rv.Bool())
	case reflect.String:
		err = e.encodeString(rv.String())
	case reflect.Slice:
		ret := make([]interface{}, rv.Len())
		for i := 0; i < rv.Len(); i++ {
			ret[i] = rv.Index(i).Interface()
		}
		err = e.encodeSlice(ret)
	case reflect.Map:
		if rv.Type().Key().Kind() == reflect.String {
			iv := rv.Interface()
			val, ok := iv.(map[string]interface{})
			if ok {
				err = e.encodeMap(val)
			}
		} else {
			err = errors.New("Unsupported kind of map: %T, %+v", rv, rv)
		}
	case reflect.Struct:
		val, ok := iVal.(structures.Structure)
		if ok {
			err = e.encodeStructure(val)
		} else {
			err = errors.New("Unsupported Struct: %T, %+v", rv, rv)
		}
	default:
		return errors.New("Unrecognized type when encoding data for Bolt transport: %T %+v", rv, rv)
	}
	return err
}
// encodeInt encodes a nil object to the stream
func (e Encoder) encodeInt(val int64) error {
	var err error
	switch {
	case val >= math.MinInt64 && val < math.MinInt32:
		// Write as INT_64
		if _, err = e.Write([]byte{Int64Marker}); err != nil {
			return err
		}
		err = binary.Write(e, binary.BigEndian, val)
	case val >= math.MinInt32 && val < math.MinInt16:
		// Write as INT_32
		if _, err = e.Write([]byte{Int32Marker}); err != nil {
			return err
		}
		err = binary.Write(e, binary.BigEndian, int32(val))
	case val >= math.MinInt16 && val < math.MinInt8:
		// Write as INT_16
		if _, err = e.Write([]byte{Int16Marker}); err != nil {
			return err
		}
		err = binary.Write(e, binary.BigEndian, int16(val))
	case val >= math.MinInt8 && val < -16:
		// Write as INT_8
		if _, err = e.Write([]byte{Int8Marker}); err != nil {
			return err
		}
		err = binary.Write(e, binary.BigEndian, int8(val))
	case val >= -16 && val <= math.MaxInt8:
		// Write as TINY_INT
		err = binary.Write(e, binary.BigEndian, int8(val))
	case val > math.MaxInt8 && val <= math.MaxInt16:
		// Write as INT_16
		if _, err = e.Write([]byte{Int16Marker}); err != nil {
			return err
		}
		err = binary.Write(e, binary.BigEndian, int16(val))
	case val > math.MaxInt16 && val <= math.MaxInt32:
		// Write as INT_32
		if _, err = e.Write([]byte{Int32Marker}); err != nil {
			return err
		}
		err = binary.Write(e, binary.BigEndian, int32(val))
	case val > math.MaxInt32 && val <= math.MaxInt64:
		// Write as INT_64
		if _, err = e.Write([]byte{Int64Marker}); err != nil {
			return err
		}
		err = binary.Write(e, binary.BigEndian, val)
	default:
		return errors.New("Int too long to write: %d", val)
	}
	if err != nil {
		return errors.Wrap(err, "An error occured writing an int to bolt")
	}
	return err
}
Beispiel #21
0
func (c *boltConn) QueryPipeline(queries []string, params ...map[string]interface{}) (PipelineRows, error) {
	if c.statement != nil {
		return nil, errors.New("An open statement already exists")
	}
	if c.closed {
		return nil, errors.New("Connection already closed")
	}

	c.statement = newPipelineStmt(queries, c)
	rows, err := c.statement.QueryPipeline(params...)
	if err != nil {
		return nil, err
	}

	// Since we're not exposing the statement,
	// tell the rows to close it when they are closed
	rows.(*boltRows).closeStatement = true
	return rows, nil
}
Beispiel #22
0
func sliceInterfaceToNode(from []interface{}) ([]graph.Node, error) {
	to := make([]graph.Node, len(from))
	for idx, item := range from {
		toItem, ok := item.(graph.Node)
		if !ok {
			return nil, errors.New("Expected Node value. Got %T %+v", item, item)
		}
		to[idx] = toItem
	}
	return to, nil
}
Beispiel #23
0
func sliceInterfaceToUnboundRelationship(from []interface{}) ([]graph.UnboundRelationship, error) {
	to := make([]graph.UnboundRelationship, len(from))
	for idx, item := range from {
		toItem, ok := item.(graph.UnboundRelationship)
		if !ok {
			return nil, errors.New("Expected UnboundRelationship value. Got %T %+v", item, item)
		}
		to[idx] = toItem
	}
	return to, nil
}
Beispiel #24
0
func sliceInterfaceToString(from []interface{}) ([]string, error) {
	to := make([]string, len(from))
	for idx, item := range from {
		toItem, ok := item.(string)
		if !ok {
			return nil, errors.New("Expected string value. Got %T %+v", item, item)
		}
		to[idx] = toItem
	}
	return to, nil
}
Beispiel #25
0
// NextPipeline gets the next row result
// When the rows are completed, returns the success metadata and the next
// set of rows.
// When all rows are completed, returns io.EOF
func (r *boltRows) NextPipeline() ([]interface{}, map[string]interface{}, PipelineRows, error) {
	if r.closed {
		return nil, nil, nil, errors.New("Rows are already closed")
	}

	respInt, err := r.statement.conn.consume()
	if err != nil {
		return nil, nil, nil, err
	}

	switch resp := respInt.(type) {
	case messages.SuccessMessage:
		log.Infof("Got success message: %#v", resp)

		if r.pipelineIndex == len(r.statement.queries)-1 {
			r.finishedConsume = true
			return nil, nil, nil, err
		}

		successResp, err := r.statement.conn.consume()
		if err == io.EOF {
		} else if err != nil {
			return nil, nil, nil, errors.Wrap(err, "An error occurred getting next set of rows from pipeline command: %#v", successResp)
		}

		success, ok := successResp.(messages.SuccessMessage)
		if !ok {
			return nil, nil, nil, errors.New("Unexpected response getting next set of rows from pipeline command: %#v", successResp)
		}

		r.statement.rows = newPipelineRows(r.statement, success.Metadata, r.pipelineIndex+1)
		r.statement.rows.closeStatement = r.closeStatement
		return nil, success.Metadata, r.statement.rows, nil

	case messages.RecordMessage:
		log.Infof("Got record message: %#v", resp)
		return resp.Fields, nil, nil, nil
	default:
		return nil, nil, nil, errors.New("Unrecognized response type getting next pipeline row: %#v", resp)
	}
}
func (d Decoder) decodePath(buffer *bytes.Buffer) (graph.Path, error) {
	path := graph.Path{}

	nodesInt, err := d.decode(buffer)
	if err != nil {
		return path, err
	}
	nodesIntSlice, ok := nodesInt.([]interface{})
	if !ok {
		return path, errors.New("Expected: Nodes []Node, but got %T %+v", nodesInt, nodesInt)
	}
	path.Nodes, err = sliceInterfaceToNode(nodesIntSlice)
	if err != nil {
		return path, err
	}

	relsInt, err := d.decode(buffer)
	if err != nil {
		return path, err
	}
	relsIntSlice, ok := relsInt.([]interface{})
	if !ok {
		return path, errors.New("Expected: Relationships []Relationship, but got %T %+v", relsInt, relsInt)
	}
	path.Relationships, err = sliceInterfaceToUnboundRelationship(relsIntSlice)
	if err != nil {
		return path, err
	}

	seqInt, err := d.decode(buffer)
	if err != nil {
		return path, err
	}
	seqIntSlice, ok := seqInt.([]interface{})
	if !ok {
		return path, errors.New("Expected: Sequence []int, but got %T %+v", seqInt, seqInt)
	}
	path.Sequence, err = sliceInterfaceToInt(seqIntSlice)

	return path, err
}
// Close the net conn, outputting the recording
func (r *recorder) Close() error {
	if r.Conn != nil {
		err := r.flush()
		if err != nil {
			return err
		}
		return r.Conn.Close()
	} else if len(r.events) > 0 {
		if r.currentEvent != len(r.events) {
			return errors.New("Didn't read all of the events in the recorder on close! %#v", r)
		}

		if len(r.events[len(r.events)-1].Event) != 0 {
			return errors.New("Left data in an event in the recorder on close! %#v", r)
		}

		return nil
	}

	return nil
}
func (d Decoder) decodeSuccessMessage(buffer *bytes.Buffer) (messages.SuccessMessage, error) {
	metadataInt, err := d.decode(buffer)
	if err != nil {
		return messages.SuccessMessage{}, err
	}
	metadata, ok := metadataInt.(map[string]interface{})
	if !ok {
		return messages.SuccessMessage{}, errors.New("Expected: Metadata map[string]interface{}, but got %T %+v", metadataInt, metadataInt)
	}

	return messages.NewSuccessMessage(metadata), nil
}
func (d Decoder) decodeRecordMessage(buffer *bytes.Buffer) (messages.RecordMessage, error) {
	fieldsInt, err := d.decode(buffer)
	if err != nil {
		return messages.RecordMessage{}, err
	}
	fields, ok := fieldsInt.([]interface{})
	if !ok {
		return messages.RecordMessage{}, errors.New("Expected: Fields []interface{}, but got %T %+v", fieldsInt, fieldsInt)
	}

	return messages.NewRecordMessage(fields), nil
}
Beispiel #30
0
func (c *boltConn) reset() error {
	log.Info("Resetting session")

	reset := messages.NewResetMessage()
	err := encoding.NewEncoder(c, c.chunkSize).Encode(reset)
	if err != nil {
		return errors.Wrap(err, "An error occurred encoding reset message")
	}

	for {
		respInt, err := encoding.NewDecoder(c).Decode()
		if err != nil {
			return errors.Wrap(err, "An error occurred decoding reset message response")
		}

		switch resp := respInt.(type) {
		case messages.IgnoredMessage:
			log.Infof("Got ignored message when resetting session: %#v", resp)
			continue
		case messages.SuccessMessage:
			log.Infof("Got success message when resetting session: %#v", resp)
			return nil
		case messages.FailureMessage:
			log.Errorf("Got failure message when resetting session: %#v", resp)
			err = c.Close()
			if err != nil {
				log.Errorf("An error occurred closing the session: %s", err)
			}
			return errors.New("Error resetting session: %#v. CLOSING SESSION!", resp)
		default:
			log.Errorf("Got unrecognized response from resetting session: %#v", resp)
			err = c.Close()
			if err != nil {
				log.Errorf("An error occurred closing the session: %s", err)
			}
			return errors.New("Got unrecognized response from resetting session: %#v. CLOSING SESSION!", resp)
		}
	}
}