package rados // #cgo LDFLAGS: -lrados // #include // #include // #include // import "C" import ( "unsafe" "github.com/ceph/go-ceph/internal/cutil" ts "github.com/ceph/go-ceph/internal/timespec" ) // Timespec is a public type for the internal C 'struct timespec' type Timespec ts.Timespec // WriteOp manages a set of discrete actions that will be performed together // atomically. type WriteOp struct { operation op C.rados_write_op_t } // CreateWriteOp returns a newly constructed write operation. func CreateWriteOp() *WriteOp { return &WriteOp{ op: C.rados_create_write_op(), } } // Release the resources associated with this write operation. func (w *WriteOp) Release() { C.rados_release_write_op(w.op) w.op = nil w.free() } func (w WriteOp) operate2( ioctx *IOContext, oid string, mtime *Timespec, flags OperationFlags) error { if err := ioctx.validate(); err != nil { return err } cOid := C.CString(oid) defer C.free(unsafe.Pointer(cOid)) var cMtime *C.struct_timespec if mtime != nil { cMtime = &C.struct_timespec{} ts.CopyToCStruct( ts.Timespec(*mtime), ts.CTimespecPtr(cMtime)) } ret := C.rados_write_op_operate2( w.op, ioctx.ioctx, cOid, cMtime, C.int(flags)) return w.update(writeOp, ret) } // Operate will perform the operation(s). func (w *WriteOp) Operate(ioctx *IOContext, oid string, flags OperationFlags) error { return w.operate2(ioctx, oid, nil, flags) } // OperateWithMtime will perform the operation while setting the modification // time stamp to the supplied value. func (w *WriteOp) OperateWithMtime( ioctx *IOContext, oid string, mtime Timespec, flags OperationFlags) error { return w.operate2(ioctx, oid, &mtime, flags) } func (w *WriteOp) operateCompat(ioctx *IOContext, oid string) error { switch err := w.Operate(ioctx, oid, OperationNoFlag).(type) { case nil: return nil case OperationError: return err.OpError default: return err } } // Create a rados object. func (w *WriteOp) Create(exclusive CreateOption) { // category, the 3rd param, is deprecated and has no effect so we do not // implement it in go-ceph C.rados_write_op_create(w.op, C.int(exclusive), nil) } // SetOmap appends the map `pairs` to the omap `oid`. func (w *WriteOp) SetOmap(pairs map[string][]byte) { keys := make([]string, len(pairs)) values := make([][]byte, len(pairs)) idx := 0 for k, v := range pairs { keys[idx] = k values[idx] = v idx++ } cKeys := cutil.NewBufferGroupStrings(keys) cValues := cutil.NewBufferGroupBytes(values) defer cKeys.Free() defer cValues.Free() C.rados_write_op_omap_set2( w.op, (**C.char)(cKeys.BuffersPtr()), (**C.char)(cValues.BuffersPtr()), (*C.size_t)(cKeys.LengthsPtr()), (*C.size_t)(cValues.LengthsPtr()), (C.size_t)(len(pairs))) } // RmOmapKeys removes the specified `keys` from the omap `oid`. func (w *WriteOp) RmOmapKeys(keys []string) { cKeys := cutil.NewBufferGroupStrings(keys) defer cKeys.Free() C.rados_write_op_omap_rm_keys2( w.op, (**C.char)(cKeys.BuffersPtr()), (*C.size_t)(cKeys.LengthsPtr()), (C.size_t)(len(keys))) } // CleanOmap clears the omap `oid`. func (w *WriteOp) CleanOmap() { C.rados_write_op_omap_clear(w.op) } // AssertExists assures the object targeted by the write op exists. // // Implements: // // void rados_write_op_assert_exists(rados_write_op_t write_op); func (w *WriteOp) AssertExists() { C.rados_write_op_assert_exists(w.op) } // Write a given byte slice at the supplied offset. // // Implements: // // void rados_write_op_write(rados_write_op_t write_op, // const char *buffer, // size_t len, // uint64_t offset); func (w *WriteOp) Write(b []byte, offset uint64) { oe := newWriteStep(b, 0, offset) w.steps = append(w.steps, oe) C.rados_write_op_write( w.op, oe.cBuffer, oe.cDataLen, oe.cOffset) } // WriteFull writes a given byte slice as the whole object, // atomically replacing it. // // Implements: // // void rados_write_op_write_full(rados_write_op_t write_op, // const char *buffer, // size_t len); func (w *WriteOp) WriteFull(b []byte) { oe := newWriteStep(b, 0, 0) w.steps = append(w.steps, oe) C.rados_write_op_write_full( w.op, oe.cBuffer, oe.cDataLen) } // WriteSame write a given byte slice to the object multiple times, until // writeLen is satisfied. // // Implements: // // void rados_write_op_writesame(rados_write_op_t write_op, // const char *buffer, // size_t data_len, // size_t write_len, // uint64_t offset); func (w *WriteOp) WriteSame(b []byte, writeLen, offset uint64) { oe := newWriteStep(b, writeLen, offset) w.steps = append(w.steps, oe) C.rados_write_op_writesame( w.op, oe.cBuffer, oe.cDataLen, oe.cWriteLen, oe.cOffset) }