Example #1
0
//
// The link map allow to have as key the types:
// STRING,SHORT,INTEGER,LONG,BYTE,DATE,DECIMAL,DATETIME,DATA,FLOAT,DOUBLE
// the serialization of the linkmap is a list of entry
//
// +----------------------------+
// | values:link_map_entry[]    |
// +----------------------------+
//
// link_map_entry structure
//
// +--------------+------------------+------------+
// | keyType:byte | keyValue:byte[]  | link:LINK  |
// +--------------+------------------+------------+
//
// keyType -  is the type of the key, can be only one of the listed type.
// keyValue - the value of the key serialized with the serializer of the type
// link -     the link value stored with the formant of a LINK
//
// TODO: right now only supporting string keys, but need to support the
//       datatypes listed above (also for EmbeddedMaps)
//
func (serde ORecordSerializerV0) writeLinkMap(buf *obuf.WriteBuf, m map[string]*oschema.OLink) error {
	// number of entries in the map
	err := varint.EncodeAndWriteVarInt32(buf, int32(len(m)))
	if err != nil {
		return oerror.NewTrace(err)
	}

	for k, v := range m {
		// keyType
		err = rw.WriteByte(buf, byte(oschema.STRING))
		if err != nil {
			return oerror.NewTrace(err)
		}
		// keyValue
		err = varint.WriteString(buf, k)
		if err != nil {
			return oerror.NewTrace(err)
		}
		// link
		err = serde.writeLink(buf, v)
		if err != nil {
			return oerror.NewTrace(err)
		}
	}

	return nil
}
Example #2
0
//
// writeEmbeddedMap serializes the EMBEDDEDMAP type. Currently, OrientDB only uses string
// types for the map keys, so that is an assumption of this method as well.
//
func (serde ORecordSerializerV0) writeEmbeddedMap(buf *obuf.WriteBuf, m oschema.OEmbeddedMap) error {
	// number of entries in the map
	err := varint.EncodeAndWriteVarInt32(buf, int32(m.Len()))
	if err != nil {
		return oerror.NewTrace(err)
	}

	ptrPos := make([]int, 0, m.Len()) // position in buf where data ptr int needs to be written

	// TODO: do the map entries have to be written in any particular order?  I will assume no for now
	keys, vals, types := m.All()

	/* ---[ write embedded map header ]--- */
	for i, k := range keys {
		// key type
		err = rw.WriteByte(buf, byte(oschema.STRING))
		if err != nil {
			return oerror.NewTrace(err)
		}

		// write the key value
		err = varint.WriteString(buf, k)
		if err != nil {
			return oerror.NewTrace(err)
		}

		ptrPos = append(ptrPos, buf.Len())
		buf.Skip(4) // placeholder integer for data ptr

		dataType := types[i]
		if dataType == oschema.UNKNOWN {
			dataType = getDataType(vals[i]) // TODO: not sure this is necessary
		}
		// write data type of the data
		err = rw.WriteByte(buf, byte(dataType))
		if err != nil {
			return oerror.NewTrace(err)
		}
	}

	/* ---[ write embedded map data values ]--- */
	for i := 0; i < len(vals); i++ {
		currPos := buf.Len()
		buf.Seek(uint(ptrPos[i]))
		err = rw.WriteInt(buf, int32(currPos))
		if err != nil {
			return oerror.NewTrace(err)
		}
		buf.Seek(uint(currPos))
		err = serde.writeDataValue(buf, vals[i], types[i])
		if err != nil {
			return oerror.NewTrace(err)
		}
	}

	return nil
}
Example #3
0
//
// +-----------------+-----------------+
// |clusterId:varint | recordId:varInt |
// +-----------------+-----------------+
//
func (serde ORecordSerializerV0) writeLink(buf *obuf.WriteBuf, lnk *oschema.OLink) error {
	err := varint.EncodeAndWriteVarInt32(buf, int32(lnk.RID.ClusterID))
	if err != nil {
		return oerror.NewTrace(err)
	}

	err = varint.EncodeAndWriteVarInt64(buf, lnk.RID.ClusterPos)
	if err != nil {
		return oerror.NewTrace(err)
	}
	return nil
}
Example #4
0
//
// +-------------+-------------------+
// | size:varint | collection:LINK[] |
// +-------------+-------------------+
//
func (serde ORecordSerializerV0) writeLinkList(buf *obuf.WriteBuf, lnks []*oschema.OLink) error {
	// number of entries in the list
	err := varint.EncodeAndWriteVarInt32(buf, int32(len(lnks)))
	if err != nil {
		return oerror.NewTrace(err)
	}

	for _, lnk := range lnks {
		err = serde.writeLink(buf, lnk)
		if err != nil {
			return oerror.NewTrace(err)
		}
	}

	return nil
}
Example #5
0
//
// Serialization format for EMBEDDEDLIST and EMBEDDEDSET
// +-------------+------------+-------------------+
// |size:varInt  | type:Otype | items:item_data[] |
// +-------------+------------+-------------------+
//
// The item_data data structure is:
// +------------------+--------------+
// | data_type:OType  | data:byte[]  |
// +------------------+--------------+
//
func (serde ORecordSerializerV0) serializeEmbeddedCollection(buf *obuf.WriteBuf, ls oschema.OEmbeddedList) error {
	err := varint.EncodeAndWriteVarInt32(buf, int32(ls.Len()))
	if err != nil {
		return oerror.NewTrace(err)
	}

	// following the lead of the Java driver, you don't specify the type of the list overall
	// (I tried to and it doesn't work, at least with OrientDB-2.0.1)
	err = rw.WriteByte(buf, byte(oschema.ANY))
	if err != nil {
		return oerror.NewTrace(err)
	}

	for _, val := range ls.Values() {
		buf.WriteByte(byte(ls.Type()))
		err = serde.writeDataValue(buf, val, ls.Type())
		if err != nil {
			return oerror.NewTrace(err)
		}
	}

	return nil
}
Example #6
0
//
// writeDataValue is part of the Serialize functionality
// TODO: change name to writeSingleValue ?
//
func (serde ORecordSerializerV0) writeDataValue(buf *obuf.WriteBuf, value interface{}, datatype oschema.ODataType) (err error) {
	switch datatype {
	case oschema.STRING:
		err = varint.WriteString(buf, value.(string))
		ogl.Debugf("DEBUG STR: -writeDataVal val: %v\n", value.(string)) // DEBUG

	case oschema.BOOLEAN:
		err = rw.WriteBool(buf, value.(bool))
		ogl.Debugf("DEBUG BOOL: -writeDataVal val: %v\n", value.(bool)) // DEBUG

	case oschema.INTEGER:
		var i32val int32
		i32val, err = toInt32(value)
		if err == nil {
			err = varint.EncodeAndWriteVarInt32(buf, i32val)         // TODO: are serialized integers ALWAYS varint encoded?
			ogl.Debugf("DEBUG INT: -writeDataVal val: %v\n", i32val) // DEBUG
		}

	case oschema.SHORT:
		// TODO: needs toInt16 conversion fn
		err = varint.EncodeAndWriteVarInt32(buf, int32(value.(int16)))
		ogl.Debugf("DEBUG SHORT: -writeDataVal val: %v\n", value.(int16)) // DEBUG

	case oschema.LONG:
		var i64val int64
		i64val, err = toInt64(value)
		if err == nil {
			err = varint.EncodeAndWriteVarInt64(buf, i64val)          // TODO: are serialized longs ALWAYS varint encoded?
			ogl.Debugf("DEBUG LONG: -writeDataVal val: %v\n", i64val) // DEBUG
		}

	case oschema.FLOAT:
		var f32 float32
		f32, err = toFloat32(value)
		if err == nil {
			err = rw.WriteFloat(buf, f32)
		}
		ogl.Debugf("DEBUG FLOAT: -writeDataVal val: %v\n", value) // DEBUG

	case oschema.DOUBLE:
		var f64 float64
		f64, err = toFloat64(value)
		if err == nil {
			err = rw.WriteDouble(buf, f64)
		}
		ogl.Debugf("DEBUG DOUBLE: -writeDataVal val: %v\n", value.(float64)) // DEBUG

	case oschema.DATETIME:
		err = writeDateTime(buf, value)
		ogl.Debugf("DEBUG DATETIME: -writeDataVal val: %v\n", value) // DEBUG

	case oschema.DATE:
		err = writeDate(buf, value)
		ogl.Debugf("DEBUG DATE: -writeDataVal val: %v\n", value) // DEBUG

	case oschema.BINARY:
		err = varint.WriteBytes(buf, value.([]byte))
		ogl.Debugf("DEBUG BINARY: -writeDataVal val: %v\n", value.([]byte)) // DEBUG

	case oschema.EMBEDDED:
		err = serde.serializeDocument(buf, value.(*oschema.ODocument))
		ogl.Debugf("DEBUG EMBEDDED: -writeDataVal val: %v\n", value) // DEBUG

	case oschema.EMBEDDEDLIST:
		err = serde.serializeEmbeddedCollection(buf, value.(oschema.OEmbeddedList))
		ogl.Debugf("DEBUG EMBD-LIST: -writeDataVal val: %v\n", value) // DEBUG

	case oschema.EMBEDDEDSET:
		err = serde.serializeEmbeddedCollection(buf, value.(oschema.OEmbeddedList))
		ogl.Debugf("DEBUG EMBD-SET: -writeDataVal val: %v\n", value) // DEBUG

	case oschema.EMBEDDEDMAP:
		err = serde.writeEmbeddedMap(buf, value.(oschema.OEmbeddedMap))
		ogl.Debugf("DEBUG EMBEDDEDMAP:  val %v\n", value.(oschema.OEmbeddedMap))

	case oschema.LINK:
		err = serde.writeLink(buf, value.(*oschema.OLink))
		ogl.Debugf("DEBUG LINK:  val %v\n", value) // DEBUG

	case oschema.LINKLIST:
		err = serde.writeLinkList(buf, value.([]*oschema.OLink))
		ogl.Debugf("DEBUG LINKLIST:  val %v\n", value) // DEBUG

	case oschema.LINKSET:
		err = serde.writeLinkList(buf, value.([]*oschema.OLink))
		ogl.Debugf("DEBUG LINKSET:  val %v\n", value) // DEBUG

	case oschema.LINKMAP:
		err = serde.writeLinkMap(buf, value.(map[string]*oschema.OLink))
		ogl.Debugf("DEBUG LINKMAP:  val %v\n", value) // DEBUG

	case oschema.BYTE:
		err = rw.WriteByte(buf, value.(byte))
		ogl.Debugf("DEBUG BYTE: -writeDataVal val: %v\n", value.(byte)) // DEBUG

	case oschema.DECIMAL:
		// TODO: impl me -> Java client uses BigDecimal for this
		panic("ORecordSerializerV0#writeDataValue DECIMAL NOT YET IMPLEMENTED")

	case oschema.CUSTOM:
		// TODO: impl me
		panic("ORecordSerializerV0#writeDataValue CUSTOM NOT YET IMPLEMENTED")
	case oschema.LINKBAG:
		panic("ORecordSerializerV0#writeDataValue LINKBAG NOT YET IMPLEMENTED")
	default:
		// ANY and TRANSIENT are do nothing ops
	}
	return err
}
Example #7
0
//
// In Progress attempt to rewrite writeSerializedRecord and related fns
// using a seekable/skipping WriteBuf
//
func (serde ORecordSerializerV0) writeSerializedRecord(wbuf *obuf.WriteBuf, doc *oschema.ODocument) (err error) {
	nfields := len(doc.FieldNames())
	ptrPos := make([]int, 0, nfields) // position in buf where data ptr int needs to be written

	currDB := serde.dbc.GetCurrDB()
	oclass, ok := currDB.Classes[doc.Classname]

	docFields := doc.GetFields()
	for _, fld := range docFields {
		var oprop *oschema.OProperty
		if ok {
			oprop = oclass.Properties[fld.Name]
		}

		// FROM THE JAVA CLIENT:
		// if (properties[i] != null) {
		//   OVarIntSerializer.write(bytes, (properties[i].getId() + 1) * -1);
		//   if (properties[i].getType() != OType.ANY)
		//     pos[i] = bytes.alloc(OIntegerSerializer.INT_SIZE);
		//   else
		//     pos[i] = bytes.alloc(OIntegerSerializer.INT_SIZE + 1);   // TODO: why does ANY required an additional byte?
		// } else {
		//   writeString(bytes, entry.getKey());
		//   pos[i] = bytes.alloc(OIntegerSerializer.INT_SIZE + 1);

		if oprop != nil {
			// if property is known in the global properties, then
			// just write its encoded id
			varint.EncodeAndWriteVarInt32(wbuf, encodeFieldIDForHeader(oprop.ID))
			ptrPos = append(ptrPos, wbuf.Len())
			wbuf.Skip(4)
			// Note: no need to write property type when writing property ID

		} else {
			// property Name
			err = varint.WriteString(wbuf, fld.Name)
			if err != nil {
				return oerror.NewTrace(err)
			}
			ptrPos = append(ptrPos, wbuf.Len())
			wbuf.Skip(4)

			// property Type
			err = rw.WriteByte(wbuf, byte(fld.Type))
			if err != nil {
				return oerror.NewTrace(err)
			}
		}
	}
	wbuf.WriteByte(0) // End of Header sentinel

	// now write out the data values
	for i, fld := range docFields {
		currPos := wbuf.Len()
		wbuf.Seek(uint(ptrPos[i]))
		err = rw.WriteInt(wbuf, int32(currPos))
		if err != nil {
			return oerror.NewTrace(err)
		}
		wbuf.Seek(uint(currPos))
		err = serde.writeDataValue(wbuf, fld.Value, fld.Type)
		if err != nil {
			return oerror.NewTrace(err)
		}
	}

	return nil
}