Example #1
0
// Store records in the database. In combination with a queue or
// numbered database the append flags causes the keys of the records
// to be set to fresh record numbers, for any other database it
// prevents an existing record with the same key from being
// overwritten.
func (db Database) Put(txn Transaction, append bool, recs ...proto.Message) (err error) {
	dbtype, err := db.Type()
	if err != nil {
		return
	}

	var key, data C.DBT
	var flags C.u_int32_t = 0

	if append {
		key.flags |= C.DB_DBT_USERMEM

		switch dbtype {
		case Numbered, Queue:
			flags |= C.DB_APPEND
		default:
			flags |= C.DB_NOOVERWRITE
		}
	} else {
		key.flags |= C.DB_DBT_READONLY
	}

	data.flags |= C.DB_DBT_READONLY

	for _, rec := range recs {
		err = db.marshalData(&data, rec)
		if err != nil {
			return
		}

		err = db.marshalKey(&key, rec)
		if err == nil {
			key.ulen = key.size
		} else {
			return
		}

		err = check(C.db_put(db.ptr, txn.ptr, &key, &data, flags))
		if err != nil {
			return
		}
	}

	return
}
Example #2
0
// Get records from the database. The consume flag makes sense only in
// combination with a queue database and causes the operation to wait
// for and obtain the next enqueued record.
func (db Database) Get(txn Transaction, consume bool, recs ...proto.Message) (err error) {
	var key, data C.DBT
	var flags C.u_int32_t = 0

	if consume {
		key.flags |= C.DB_DBT_USERMEM
		flags |= C.DB_CONSUME_WAIT
	} else {
		key.flags |= C.DB_DBT_READONLY
	}

	data.flags |= C.DB_DBT_REALLOC
	defer C.free(data.data)

	for _, rec := range recs {
		err = db.marshalKey(&key, rec)
		if err == nil {
			key.ulen = key.size
		} else {
			return
		}

		err = check(C.db_get(db.ptr, txn.ptr, &key, &data, flags))
		if err != nil {
			return
		}

		err = db.unmarshalData(&data, rec)
		if err != nil {
			return
		}

		err = db.unmarshalKey(&key, rec)
		if err != nil {
			return
		}
	}

	return
}