func writeLinkBagCollectionPointer(buf *bytes.Buffer, linkBag *oschema.OLinkBag) error { // (treePointer:collectionPointer)(changes) // where collectionPtr = (fileId:long)(pageIndex:long)(pageOffset:int) err := rw.WriteLong(buf, linkBag.GetFileID()) if err != nil { return oerror.NewTrace(err) } err = rw.WriteLong(buf, linkBag.GetPageIndex()) if err != nil { return oerror.NewTrace(err) } return rw.WriteInt(buf, linkBag.GetPageOffset()) }
// // UpdateRecord should be used update an existing record in the OrientDB database. // It does the REQUEST_RECORD_UPDATE OrientDB cmd (network binary protocol) // func UpdateRecord(dbc *DBClient, doc *oschema.ODocument) error { dbc.buf.Reset() err := writeCommandAndSessionId(dbc, REQUEST_RECORD_UPDATE) if err != nil { return oerror.NewTrace(err) } if doc.RID.ClusterID < 0 || doc.RID.ClusterPos < 0 { return errors.New("Document is not updateable - has negative RID values") } err = rw.WriteShort(dbc.buf, doc.RID.ClusterID) if err != nil { return oerror.NewTrace(err) } err = rw.WriteLong(dbc.buf, doc.RID.ClusterPos) if err != nil { return oerror.NewTrace(err) } // update-content flag err = rw.WriteBool(dbc.buf, true) if err != nil { return oerror.NewTrace(err) } // serialized-doc serde := dbc.RecordSerDes[int(dbc.serializationVersion)] // this writes the serialized record to dbc.buf serializedBytes, err := serde.Serialize(dbc, doc) if err != nil { return oerror.NewTrace(err) } err = rw.WriteBytes(dbc.buf, serializedBytes) if err != nil { return oerror.NewTrace(err) } // record version err = rw.WriteInt(dbc.buf, doc.Version) if err != nil { return oerror.NewTrace(err) } // record-type: document err = rw.WriteByte(dbc.buf, byte('d')) // TODO: how support 'b' (raw bytes) & 'f' (flat data)? if err != nil { return oerror.NewTrace(err) } // mode: synchronous err = rw.WriteByte(dbc.buf, 0x0) if err != nil { return oerror.NewTrace(err) } // send to the OrientDB server _, err = dbc.conx.Write(dbc.buf.Bytes()) if err != nil { return oerror.NewTrace(err) } /* ---[ Read Response ]--- */ err = readStatusCodeAndSessionId(dbc) if err != nil { return oerror.NewTrace(err) } doc.Version, err = rw.ReadInt(dbc.conx) if err != nil { return oerror.NewTrace(err) } nCollChanges, err := rw.ReadInt(dbc.conx) if err != nil { return oerror.NewTrace(err) } if nCollChanges != 0 { // if > 0, then have to deal with RidBag mgmt: // [(uuid-most-sig-bits:long)(uuid-least-sig-bits:long)(updated-file-id:long)(updated-page-index:long)(updated-page-offset:int)] panic("CreateRecord: Found case where number-collection-changes is not zero -> log case and impl code to handle") } return nil }
func deleteByRID(dbc *DBClient, rid string, recVersion int32, async bool) error { dbc.buf.Reset() orid := oschema.NewORIDFromString(rid) err := writeCommandAndSessionId(dbc, REQUEST_RECORD_DELETE) if err != nil { return err } err = rw.WriteShort(dbc.buf, orid.ClusterID) if err != nil { return err } err = rw.WriteLong(dbc.buf, orid.ClusterPos) if err != nil { return err } err = rw.WriteInt(dbc.buf, recVersion) if err != nil { return err } // sync mode ; 0 = synchronous; 1 = asynchronous var syncMode byte if async { syncMode = byte(1) } err = rw.WriteByte(dbc.buf, syncMode) if err != nil { return err } // send to the OrientDB server _, err = dbc.conx.Write(dbc.buf.Bytes()) if err != nil { return err } /* ---[ Read Response ]--- */ err = readStatusCodeAndSessionId(dbc) if err != nil { return err } payloadStatus, err := rw.ReadByte(dbc.conx) if err != nil { return err } // status 1 means record was deleted; // status 0 means record was not deleted (either failed or didn't exist) if payloadStatus == byte(0) { return fmt.Errorf("Server reports record %s was not deleted. Either failed or did not exist.", rid) } return 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 }
// // loadConfigRecord loads record #0:0 for the current database, caching // some of the information returned into OStorageConfiguration // func loadConfigRecord(dbc *DBClient) (schemaRID string, err error) { // The config record comes back as type 'b' (raw bytes), which should // just be converted to a string then tokenized by the pipe char dbc.buf.Reset() var ( clusterId int16 clusterPos int64 ) err = writeCommandAndSessionId(dbc, REQUEST_RECORD_LOAD) if err != nil { return schemaRID, err } clusterId = 0 err = rw.WriteShort(dbc.buf, clusterId) if err != nil { return schemaRID, err } clusterPos = 0 err = rw.WriteLong(dbc.buf, clusterPos) if err != nil { return schemaRID, err } fetchPlan := "*:-1 index:0" err = rw.WriteString(dbc.buf, fetchPlan) if err != nil { return schemaRID, err } ignoreCache := true err = rw.WriteBool(dbc.buf, ignoreCache) if err != nil { return schemaRID, err } loadTombstones := true // based on Java client code err = rw.WriteBool(dbc.buf, loadTombstones) if err != nil { return schemaRID, err } // send to the OrientDB server _, err = dbc.conx.Write(dbc.buf.Bytes()) if err != nil { return schemaRID, err } /* ---[ Read Response ]--- */ err = readStatusCodeAndSessionId(dbc) if err != nil { return schemaRID, err } payloadStatus, err := rw.ReadByte(dbc.conx) if err != nil { return schemaRID, err } if payloadStatus == byte(0) { return schemaRID, errors.New("Payload status for #0:0 load was 0. No config data returned.") } rectype, err := rw.ReadByte(dbc.conx) if err != nil { return schemaRID, err } // this is the record version - don't see a reason to check or cache it right now _, err = rw.ReadInt(dbc.conx) if err != nil { return schemaRID, err } databytes, err := rw.ReadBytes(dbc.conx) if err != nil { return schemaRID, err } if rectype != 'b' { if err != nil { return schemaRID, fmt.Errorf("Expected rectype %d, but was: %d", 'b', rectype) } } payloadStatus, err = rw.ReadByte(dbc.conx) if err != nil { return schemaRID, err } if payloadStatus != byte(0) { return schemaRID, errors.New("Second Payload status for #0:0 load was not 0. More than one record returned unexpectedly") } err = parseConfigRecord(dbc.currDB, string(databytes)) if err != nil { return schemaRID, err } schemaRID = dbc.currDB.StorageCfg.schemaRID return schemaRID, err }