示例#1
0
func TestReadVarInt4BytesRandomInputA(t *testing.T) {
	bs := []byte{0x8f, 0x8f, 0x8f, 0x70}
	buf := obuf.NewReadBuffer(bs)
	actualUint, err := ReadVarIntToUint(buf)
	ok(t, err)

	expectedBytes := []byte{0x0e, 0x03, 0xc7, 0x8f}
	var expectedUint uint32
	buf2 := bytes.NewBuffer(expectedBytes)
	err = binary.Read(buf2, binary.BigEndian, &expectedUint)
	ok(t, err)

	equals(t, uint64(expectedUint), actualUint)

	// ----------------------------
	// explanation of this example:
	// ----------------------------
	// Varints are encoded in little endian order. The varint input
	// for this example is:
	//         0x8f        0x8f         0x8f         0x70
	//     [1000 1111]  [1000 1111]  [1000 1111]  [0111 0000]
	// idx:     0            1            2            3
	//
	// To "inflate" the varint, let's flip to big endian order:
	//     [0111 0000]  [1000 1111]  [1000 1111]  [1000 1111]
	// Now remove the high bit from each:
	//      111 0000  000 1111  000 1111  000 1111
	// then squash together - the highest bits get set to zero
	//     [0000 1110]  [0000 0011]  [1100 0111]  [1000 1111]
	//        0x0e         0x03         0xc7         0x8f
	//
}
示例#2
0
func TestReadVarInt1ByteAllZeros(t *testing.T) {
	bs := []byte{0x0}
	buf := obuf.NewReadBuffer(bs)
	actualUint, err := ReadVarIntToUint(buf)
	ok(t, err)

	expectedBytes := []byte{0x0, 0x0, 0x0, 0x0}
	var expectedUint uint32
	buf2 := bytes.NewBuffer(expectedBytes)
	err = binary.Read(buf2, binary.BigEndian, &expectedUint)
	ok(t, err)

	equals(t, uint64(expectedUint), actualUint)
}
示例#3
0
func TestReadVarInt1ByteRandomInputA(t *testing.T) {
	bs := []byte{0x39}
	buf := obuf.NewReadBuffer(bs)
	actualUint, err := ReadVarIntToUint(buf)
	ok(t, err)

	expectedBytes := []byte{0x0, 0x0, 0x0, 0x39}
	var expectedUint uint32
	buf2 := bytes.NewBuffer(expectedBytes)
	// I'm specifying BigEndian here because that's how I
	// ordered the "expectedBytes" - it is unrelated to how the
	// actual varint is ordered (which is LittleEndian)
	err = binary.Read(buf2, binary.BigEndian, &expectedUint)
	ok(t, err)

	equals(t, uint64(expectedUint), actualUint)
}
示例#4
0
//
// TODO: in the Java version there is a "fill" method on ODocument (ORecord)
//       to create a record from these entries => maybe move this there?
//
func createDocumentFromBytes(rid oschema.ORID, recVersion int32, serializedDoc []byte, dbc *DBClient) (*oschema.ODocument, error) {
	var doc *oschema.ODocument
	doc = oschema.NewDocument("") // don't know classname yet (in serialized record)
	doc.RID = rid
	doc.Version = recVersion

	// TODO: here need to make a query to look up the schema of the doc if we don't have it already cached

	// the first byte specifies record serialization version
	// use it to look up serializer and strip off that byte
	serde := dbc.RecordSerDes[int(serializedDoc[0])]
	recBuf := obuf.NewReadBuffer(serializedDoc[1:])
	err := serde.Deserialize(dbc, doc, recBuf)
	if err != nil {
		return nil, err
	}
	return doc, nil
}
示例#5
0
//
// FetchRecordByRID takes an ORID and reads that record from the database.
// NOTE: for now I'm assuming all records are Documents (they can also be "raw bytes" or "flat data")
// and for some reason I don't understand, multiple records can be returned, so I'm returning
// a slice of ODocument
//
// TODO: may also want to expose options: ignoreCache, loadTombstones bool
// TODO: need to properly handle fetchPlan
func FetchRecordByRID(dbc *DBClient, orid oschema.ORID, fetchPlan string) ([]*oschema.ODocument, error) {
	dbc.buf.Reset()

	err := writeCommandAndSessionId(dbc, REQUEST_RECORD_LOAD)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	err = rw.WriteShort(dbc.buf, orid.ClusterID)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	err = rw.WriteLong(dbc.buf, orid.ClusterPos)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	err = rw.WriteString(dbc.buf, fetchPlan)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	ignoreCache := true // hardcoding for now
	err = rw.WriteBool(dbc.buf, ignoreCache)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	loadTombstones := false // hardcoding for now
	err = rw.WriteBool(dbc.buf, loadTombstones)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	// send to the OrientDB server
	_, err = dbc.conx.Write(dbc.buf.Bytes())
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	/* ---[ Read Response ]--- */

	err = readStatusCodeAndSessionId(dbc)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	// this query can return multiple records (though I don't understand why)
	// so must do this in a loop
	docs := make([]*oschema.ODocument, 0, 1)
	for {
		payloadStatus, err := rw.ReadByte(dbc.conx)
		if err != nil {
			return nil, oerror.NewTrace(err)
		}

		if payloadStatus == byte(0) {
			break
		}

		rectype, err := rw.ReadByte(dbc.conx)
		if err != nil {
			return nil, oerror.NewTrace(err)
		}

		recversion, err := rw.ReadInt(dbc.conx)
		if err != nil {
			return nil, oerror.NewTrace(err)
		}

		databytes, err := rw.ReadBytes(dbc.conx)
		if err != nil {
			return nil, oerror.NewTrace(err)
		}

		ogl.Debugf("rectype:%v, recversion:%v, len(databytes):%v\n", rectype, recversion, len(databytes))

		if rectype == 'd' {
			// we don't know the classname so set empty value
			doc := oschema.NewDocument("")
			doc.RID = orid
			doc.Version = recversion

			// the first byte specifies record serialization version
			// use it to look up serializer
			serde := dbc.RecordSerDes[int(databytes[0])]
			// then strip off the version byte and send the data to the serde
			err = serde.Deserialize(dbc, doc, obuf.NewReadBuffer(databytes[1:]))
			if err != nil {
				return nil, fmt.Errorf("ERROR in Deserialize for rid %v: %v\n", orid, err)
			}
			docs = append(docs, doc)

		} else {
			return nil,
				fmt.Errorf("Only `document` records are currently supported by the client. Record returned was type: %v", rectype)
		}
	}

	return docs, nil
}
示例#6
0
//
// RequestDBList works like the "list databases" command from the OrientDB client.
// The result is put into a map, where the key of the map is the name of the
// database and the value is the type concatenated with the path, like so:
//
//     key:  cars
//     val:  plocal:/path/to/orientdb-community-2.0.1/databases/cars
//
func RequestDBList(dbc *DBClient) (map[string]string, error) {
	dbc.buf.Reset()

	if dbc.sessionId == NoSessionID {
		return nil, oerror.SessionNotInitialized{}
	}

	// cmd
	err := rw.WriteByte(dbc.buf, REQUEST_DB_LIST)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	// session id
	err = rw.WriteInt(dbc.buf, dbc.sessionId)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	// send to the OrientDB server
	_, err = dbc.conx.Write(dbc.buf.Bytes())
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	status, err := rw.ReadByte(dbc.conx)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	err = readAndValidateSessionId(dbc.conx, dbc.sessionId)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	if status == RESPONSE_STATUS_ERROR {
		serverExceptions, err := rw.ReadErrorResponse(dbc.conx)
		if err != nil {
			return nil, oerror.NewTrace(err)
		}
		return nil, fmt.Errorf("Server Error(s): %v", serverExceptions)
	}

	// the bytes returned as a serialized EMBEDDEDMAP, so send it to the SerDe
	responseBytes, err := rw.ReadBytes(dbc.conx)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	serde := dbc.RecordSerDes[int(responseBytes[0])]
	buf := obuf.NewReadBuffer(responseBytes[1:])
	doc := oschema.NewDocument("")
	err = serde.Deserialize(dbc, doc, buf)
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	m := make(map[string]string)
	fldMap := doc.GetField("databases").Value.(map[string]interface{})
	for k, v := range fldMap {
		m[k] = v.(string)
	}

	return m, nil
}