diff --git a/rados/ioctx.go b/rados/ioctx.go index ff644bd..30171bd 100644 --- a/rados/ioctx.go +++ b/rados/ioctx.go @@ -234,3 +234,39 @@ func (ioctx *IOContext) SetXattr(object string, name string, data []byte) error return RadosError(int(ret)) } } + +// function that lists all the xattrs for an object, since xattrs are +// a k-v pair, this function returns a map of k-v pairs on +// success, error code on failure +func (ioctx *IOContext) ListXattrs(oid string) (map[string]string, error) { + c_oid := C.CString(oid) + defer C.free(unsafe.Pointer(c_oid)) + + var it C.rados_xattrs_iter_t + + ret := C.rados_getxattrs(ioctx.ioctx, c_oid, &it) + if ret < 0 { + return nil, RadosError(ret) + } + defer func() { C.rados_getxattrs_end(it) }() + m := make(map[string]string) + for { + var c_name, c_val *C.char + var c_len C.size_t + defer C.free(unsafe.Pointer(c_name)) + defer C.free(unsafe.Pointer(c_val)) + + ret := C.rados_getxattrs_next(it, &c_name, &c_val, &c_len) + if ret < 0 { + return nil, RadosError(int(ret)) + } + // rados api returns a null name,val & 0-length upon + // end of iteration + if c_name == nil { + return m, nil // stop iteration + } + m[C.GoString(c_name)] = C.GoStringN(c_val, (C.int)(c_len)) + } + + panic("Invalid State") +} diff --git a/rados/rados_test.go b/rados/rados_test.go index ad13afb..6ecd3c4 100644 --- a/rados/rados_test.go +++ b/rados/rados_test.go @@ -471,3 +471,38 @@ func TestReadWriteXattr(t *testing.T) { pool.Destroy() } + +func TestListXattrs(t *testing.T) { + conn, _ := rados.NewConn() + conn.ReadDefaultConfigFile() + conn.Connect() + + // make pool + pool_name := GetUUID() + err := conn.MakePool(pool_name) + assert.NoError(t, err) + + pool, err := conn.OpenIOContext(pool_name) + assert.NoError(t, err) + + bytes_in := []byte("input data") + err = pool.Write("obj", bytes_in, 0) + assert.NoError(t, err) + + input_xattrs := make(map[string]string) + for i := 0; i < 200; i++ { + name := fmt.Sprintf("key_%d", i) + data := []byte(GetUUID()) + err = pool.SetXattr("obj", name, data) + assert.NoError(t, err) + input_xattrs[name] = string(data) + } + + output_xattrs := make(map[string]string) + output_xattrs, err = pool.ListXattrs("obj") + assert.NoError(t, err) + assert.Equal(t, len(input_xattrs), len(output_xattrs)) + assert.Equal(t, input_xattrs, output_xattrs) + + pool.Destroy() +}