Ejemplo n.º 1
0
//
// FetchFirstKeyOfRemoteLinkBag is the entry point for retrieving links from
// a remote server-side side LinkBag.  In general, this method should not be
// called by end users. Instead, end users should call FetchEntriesOfRemoteLinkBag
//
// TODO: make this an unexported func?
//
func FetchFirstKeyOfRemoteLinkBag(dbc *DBClient, linkBag *oschema.OLinkBag) (*oschema.OLink, error) {
	dbc.buf.Reset()

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

	err = writeLinkBagCollectionPointer(dbc.buf, linkBag)
	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)
	}

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

	var (
		typeByte  byte
		typeSerde binserde.OBinaryTypeSerializer
	)

	typeByte = firstKeyBytes[0]
	typeSerde = binserde.TypeSerializers[typeByte]
	result, err := typeSerde.Deserialize(bytes.NewBuffer(firstKeyBytes[1:]))
	if err != nil {
		return nil, oerror.NewTrace(err)
	}

	firstLink, ok := result.(*oschema.OLink)

	if !ok {
		// TODO: fmt.Errorf is an anti-pattern
		return nil, fmt.Errorf("Typecast error. Expected *oschema.OLink but is %T", result)
	}

	return firstLink, nil
}
Ejemplo n.º 2
0
//
// FetchEntriesOfRemoteLinkBag fills in the links of an OLinkBag that is remote
// (tree-based) rather than embedded.  This function will fill in the links
// of the passed in OLinkBag, rather than returning the new links. The Links
// will have RIDs only, not full Records (ODocuments).  If you then want the
// Records filled in, call the ResolveLinks function.
//
func FetchEntriesOfRemoteLinkBag(dbc *DBClient, linkBag *oschema.OLinkBag, inclusive bool) error {
	var (
		firstLink *oschema.OLink
		linkSerde binserde.OBinaryTypeSerializer
		err       error
	)

	firstLink, err = FetchFirstKeyOfRemoteLinkBag(dbc, linkBag)
	if err != nil {
		return oerror.NewTrace(err)
	}

	dbc.buf.Reset()

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

	err = writeLinkBagCollectionPointer(dbc.buf, linkBag)
	if err != nil {
		return oerror.NewTrace(err)
	}

	typeByte := byte(9)
	linkSerde = binserde.TypeSerializers[typeByte] // the OLinkSerializer

	linkBytes, err := linkSerde.Serialize(firstLink)
	if err != nil {
		return oerror.NewTrace(err)
	}

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

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

	// copied from Java client OSBTreeBonsaiRemote#fetchEntriesMajor
	if dbc.binaryProtocolVersion >= 21 {
		err = rw.WriteInt(dbc.buf, 128)
	}

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

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

	// all the rest of the response from the server in in this byte slice so
	// we can reset the dbc.buf and reuse it to deserialize the serialized links
	dbc.buf.Reset()
	// ignoring error since doc says this method panics rather than return
	// non-nil error
	n, _ := dbc.buf.Write(linkEntryBytes)
	if n != len(linkEntryBytes) {
		return fmt.Errorf("Unexpected error when writing bytes to bytes.Buffer")
	}

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

	var result interface{}
	nr := int(nrecs)
	// loop over all the serialized links
	for i := 0; i < nr; i++ {
		result, err = linkSerde.Deserialize(dbc.buf)
		if err != nil {
			return oerror.NewTrace(err)
		}
		linkBag.AddLink(result.(*oschema.OLink))

		// FIXME: for some reason the server returns a serialized link
		//        followed by an integer (so far always a 1 in my expts).
		//        Not sure what to do with this int, so ignore for now
		intval, err := rw.ReadInt(dbc.buf)
		if err != nil {
			return oerror.NewTrace(err)
		}
		if intval != int32(1) {
			ogl.Warnf("DEBUG: Found a use case where the val pair of a link was not 1: %d\n", intval)
		}
	}

	return nil
}