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 // }
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) }
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) }
// // 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 }
// // 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 }
// // 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 }