Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gfapi: reflect API changes in gluster-7 #34

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions gfapi/fd.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build !gluster3

package gfapi

// This file includes lower level operations on fd like the ones in the 'syscall' package
Expand All @@ -6,6 +8,12 @@ package gfapi
// #include "glusterfs/api/glfs.h"
// #include <stdlib.h>
// #include <sys/stat.h>
/*
struct glfs_stat* alloc_stat(){
struct glfs_stat *ptr = malloc(sizeof(struct glfs_stat));
return ptr;
}
*/
import "C"
import (
"os"
Expand Down Expand Up @@ -45,7 +53,12 @@ func (fd *Fd) Fstat(stat *syscall.Stat_t) error {
//
// Returns error on failure
func (fd *Fd) Fsync() error {
ret, err := C.glfs_fsync(fd.fd)
preStat := C.alloc_stat()
postStat := C.alloc_stat()
defer C.free(unsafe.Pointer(preStat))
defer C.free(unsafe.Pointer(postStat))

ret, err := C.glfs_fsync(fd.fd, preStat, postStat)
if ret < 0 {
return err
}
Expand All @@ -56,7 +69,12 @@ func (fd *Fd) Fsync() error {
//
// Returns error on failure
func (fd *Fd) Ftruncate(size int64) error {
_, err := C.glfs_ftruncate(fd.fd, C.off_t(size))
preStat := C.alloc_stat()
postStat := C.alloc_stat()
defer C.free(unsafe.Pointer(preStat))
defer C.free(unsafe.Pointer(postStat))

_, err := C.glfs_ftruncate(fd.fd, C.off_t(size), preStat, postStat)

return err
}
Expand All @@ -65,7 +83,10 @@ func (fd *Fd) Ftruncate(size int64) error {
//
// Returns number of bytes read on success and error on failure
func (fd *Fd) Pread(b []byte, off int64) (int, error) {
n, err := C.glfs_pread(fd.fd, unsafe.Pointer(&b[0]), C.size_t(len(b)), C.off_t(off), 0)
postStat := C.alloc_stat()
defer C.free(unsafe.Pointer(postStat))

n, err := C.glfs_pread(fd.fd, unsafe.Pointer(&b[0]), C.size_t(len(b)), C.off_t(off), 0, postStat)

return int(n), err
}
Expand All @@ -74,7 +95,12 @@ func (fd *Fd) Pread(b []byte, off int64) (int, error) {
//
// Returns number of bytes written on success and error on failure
func (fd *Fd) Pwrite(b []byte, off int64) (int, error) {
n, err := C.glfs_pwrite(fd.fd, unsafe.Pointer(&b[0]), C.size_t(len(b)), C.off_t(off), 0)
preStat := C.alloc_stat()
postStat := C.alloc_stat()
defer C.free(unsafe.Pointer(preStat))
defer C.free(unsafe.Pointer(postStat))

n, err := C.glfs_pwrite(fd.fd, unsafe.Pointer(&b[0]), C.size_t(len(b)), C.off_t(off), 0, preStat, postStat)

return int(n), err
}
Expand Down
263 changes: 263 additions & 0 deletions gfapi/fd_gluster3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
// +build gluster3

package gfapi

// This file includes lower level operations on fd like the ones in the 'syscall' package

// #cgo pkg-config: glusterfs-api
// #include "glusterfs/api/glfs.h"
// #include <stdlib.h>
// #include <sys/stat.h>
import "C"
import (
"os"
"syscall"
"unsafe"
)

// Fd is the glusterfs fd type
type Fd struct {
fd *C.glfs_fd_t
}

var _zero uintptr

// Fchmod changes the mode of the Fd to the given mode
//
// Returns error on failure
func (fd *Fd) Fchmod(mode uint32) error {
_, err := C.glfs_fchmod(fd.fd, C.mode_t(mode))

return err
}

// Fstat performs an fstat call on the Fd and saves stat details in the passed stat structure
//
// Returns error on failure
func (fd *Fd) Fstat(stat *syscall.Stat_t) error {

ret, err := C.glfs_fstat(fd.fd, (*C.struct_stat)(unsafe.Pointer(stat)))
if int(ret) < 0 {
return err
}
return nil
}

// Fsync performs an fsync on the Fd
//
// Returns error on failure
func (fd *Fd) Fsync() error {
ret, err := C.glfs_fsync(fd.fd)
if ret < 0 {
return err
}
return nil
}

// Ftruncate truncates the size of the Fd to the given size
//
// Returns error on failure
func (fd *Fd) Ftruncate(size int64) error {
_, err := C.glfs_ftruncate(fd.fd, C.off_t(size))

return err
}

// Pread reads at most len(b) bytes into b from offset off in Fd
//
// Returns number of bytes read on success and error on failure
func (fd *Fd) Pread(b []byte, off int64) (int, error) {
n, err := C.glfs_pread(fd.fd, unsafe.Pointer(&b[0]), C.size_t(len(b)), C.off_t(off), 0)

return int(n), err
}

// Pwrite writes len(b) bytes from b into the Fd from offset off
//
// Returns number of bytes written on success and error on failure
func (fd *Fd) Pwrite(b []byte, off int64) (int, error) {
n, err := C.glfs_pwrite(fd.fd, unsafe.Pointer(&b[0]), C.size_t(len(b)), C.off_t(off), 0)

return int(n), err
}

// Read reads at most len(b) bytes into b from Fd
//
// Returns number of bytes read on success and error on failure
func (fd *Fd) Read(b []byte) (n int, err error) {
var p0 unsafe.Pointer

if len(b) > 0 {
p0 = unsafe.Pointer(&b[0])
} else {
p0 = unsafe.Pointer(&_zero)
}

// glfs_read returns a ssize_t. The value of which is the number of bytes written.
// Unless, ret is -1, an error, implying to check errno. cgo collects errno as the
// functions error return value.
ret, e1 := C.glfs_read(fd.fd, p0, C.size_t(len(b)), 0)
n = int(ret)
if n < 0 {
err = e1
}

return n, err
}

// Write writes len(b) bytes from b into the Fd
//
// Returns number of bytes written on success and error on failure
func (fd *Fd) Write(b []byte) (n int, err error) {
var p0 unsafe.Pointer

if len(b) > 0 {
p0 = unsafe.Pointer(&b[0])
} else {
p0 = unsafe.Pointer(&_zero)
}

// glfs_write returns a ssize_t. The value of which is the number of bytes written.
// Unless, ret is -1, an error, implying to check errno. cgo collects errno as the
// functions error return value.
ret, e1 := C.glfs_write(fd.fd, p0, C.size_t(len(b)), 0)
n = int(ret)
if n < 0 {
err = e1
}

return n, err
}

func (fd *Fd) lseek(offset int64, whence int) (int64, error) {
ret, err := C.glfs_lseek(fd.fd, C.off_t(offset), C.int(whence))

return int64(ret), err
}

func (fd *Fd) Fallocate(mode int, offset int64, len int64) error {
ret, err := C.glfs_fallocate(fd.fd, C.int(mode),
C.off_t(offset), C.size_t(len))

if ret == 0 {
err = nil
}
return err
}

func (fd *Fd) Fgetxattr(attr string, dest []byte) (int64, error) {
var ret C.ssize_t
var err error

cattr := C.CString(attr)
defer C.free(unsafe.Pointer(cattr))

if len(dest) <= 0 {
ret, err = C.glfs_fgetxattr(fd.fd, cattr, nil, 0)
} else {
ret, err = C.glfs_fgetxattr(fd.fd, cattr,
unsafe.Pointer(&dest[0]), C.size_t(len(dest)))
}

if ret >= 0 {
return int64(ret), nil
} else {
return int64(ret), err
}
}

func (fd *Fd) Fsetxattr(attr string, data []byte, flags int) error {

cattr := C.CString(attr)
defer C.free(unsafe.Pointer(cattr))

ret, err := C.glfs_fsetxattr(fd.fd, cattr,
unsafe.Pointer(&data[0]), C.size_t(len(data)),
C.int(flags))

if ret == 0 {
err = nil
}
return err
}

func (fd *Fd) Fremovexattr(attr string) error {

cattr := C.CString(attr)
defer C.free(unsafe.Pointer(cattr))

ret, err := C.glfs_fremovexattr(fd.fd, cattr)

if ret == 0 {
err = nil
}
return err
}

func direntName(dirent *syscall.Dirent) string {
name := make([]byte, 0, len(dirent.Name))
for i, c := range dirent.Name {
if c == 0 || i > 255 {
break
}

name = append(name, byte(c))
}

return string(name)
}

// Readdir returns the information of files in a directory.
//
// n is the maximum number of items to return. If there are more items than
// the maximum they can be obtained in successive calls. If maximum is 0
// then all the items will be returned.
func (fd *Fd) Readdir(n int) ([]os.FileInfo, error) {
var (
stat syscall.Stat_t
files []os.FileInfo
statP = (*C.struct_stat)(unsafe.Pointer(&stat))
)

for i := 0; n == 0 || i < n; i++ {
d, err := C.glfs_readdirplus(fd.fd, statP)
if err != nil {
return nil, err
}

dirent := (*syscall.Dirent)(unsafe.Pointer(d))
if dirent == nil {
break
}

name := direntName(dirent)
file := fileInfoFromStat(&stat, name)
files = append(files, file)
}

return files, nil
}

// Readdirnames returns the names of files in a directory.
//
// n is the maximum number of items to return and works the same way as Readdir.
func (fd *Fd) Readdirnames(n int) ([]string, error) {
var names []string

for i := 0; n == 0 || i < n; i++ {
d, err := C.glfs_readdir(fd.fd)
if err != nil {
return nil, err
}

dirent := (*syscall.Dirent)(unsafe.Pointer(d))
if dirent == nil {
break
}

name := direntName(dirent)
names = append(names, name)
}

return names, nil
}