From 275dfba6ceaee55ec2cfb93448085506bd37aa41 Mon Sep 17 00:00:00 2001 From: KANEKO Tatsuya Date: Tue, 28 Mar 2017 22:28:03 +0900 Subject: [PATCH] remove cgo (#5) * remove cgo Go can call POSIX API without using cgo. * update glide.yaml and glide.lock * miss * review changes * match the original C code. --- cachectl/activepages.go | 115 +++++++++++++++++----------------------- cachectl/purge.go | 58 ++++++-------------- cachectl/stat.go | 7 ++- glide.lock | 8 ++- glide.yaml | 3 ++ 5 files changed, 80 insertions(+), 111 deletions(-) diff --git a/cachectl/activepages.go b/cachectl/activepages.go index 4722df7..ea155fd 100644 --- a/cachectl/activepages.go +++ b/cachectl/activepages.go @@ -1,74 +1,55 @@ package cachectl -/* -#include -#include -#include -#include -#include -#include -#include - -int activePages(const char *path) -{ - int i, j, fd, pages, pagesize; - struct stat st; - void *m; - char *pageinfo; - - fd = open(path, O_RDONLY); - if(fd == -1) { - return -1; - } - - if(fstat(fd, &st) == -1) { - goto error; - } - - pagesize = getpagesize(); - pages = (st.st_size + pagesize - 1) / pagesize; - pageinfo = calloc(sizeof(*pageinfo), pages); - if(!pageinfo) { - goto error; - } - - m = mmap(NULL, st.st_size, PROT_NONE, MAP_SHARED, fd, 0); - if(m == MAP_FAILED) { - free(pageinfo); - goto error; - } - - if(mincore(m, st.st_size, pageinfo) == -1) { - free(pageinfo); - munmap(m, st.st_size); - goto error; - } - - i = 0; - j = 0; - for (i = 0; i < pages; i++) { - if(pageinfo[i] & 1) { - j++; - } - } - - free(pageinfo); - munmap(m, st.st_size); - - return j; -error: - close(fd); - return -1; -} -*/ -import "C" import ( + "os" "unsafe" + + "golang.org/x/sys/unix" ) -func activePages(path string) int { - cs := C.CString(path) - result := C.activePages(cs) - C.free(unsafe.Pointer(cs)) - return int(result) +func activePages(path string) (int, error) { + f, err := os.Open(path) + if err != nil { + return 0, err + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + return 0, err + } + fsize := fi.Size() + + if fsize == 0 { + return 0, nil + } + + mmap, err := unix.Mmap(int(f.Fd()), 0, int(fsize), unix.PROT_NONE, unix.MAP_SHARED) + if err != nil { + return 0, err + } + defer unix.Munmap(mmap) + + pagesize := int64(os.Getpagesize()) + pages := (fsize + pagesize - 1) / pagesize + pageinfo := make([]byte, pages) + + mmapPtr := uintptr(unsafe.Pointer(&mmap[0])) + sizePtr := uintptr(fsize) + pageinfoPtr := uintptr(unsafe.Pointer(&pageinfo[0])) + + ret, _, err := unix.Syscall(unix.SYS_MINCORE, mmapPtr, sizePtr, pageinfoPtr) + if ret != 0 { + return 0, err + } + + result := 0 + + for _, p := range pageinfo { + if p&1 == 1 { + result++ + } + } + + return result, nil } diff --git a/cachectl/purge.go b/cachectl/purge.go index 6f3adb2..552ce6e 100644 --- a/cachectl/purge.go +++ b/cachectl/purge.go @@ -1,45 +1,11 @@ package cachectl -/* -#include -#include -#include -#include -#include - -int fadvise(const char *path, float r) -{ - int fd; - struct stat st; - off_t l; - fd = open(path, O_RDONLY); - if(fd == -1) { - return -1; - } - - if(fstat(fd, &st) == -1) { - goto error; - } - - l = (off_t)(st.st_size * r); - - if(posix_fadvise(fd, 0, l, POSIX_FADV_DONTNEED) != 0) { - goto error; - } - - close(fd); - return 1; -error: - close(fd); - return -1; -} - -*/ -import "C" import ( "fmt" "log" - "unsafe" + "os" + + "golang.org/x/sys/unix" ) func purgePages(fpath string, fsize int64, rate float64) error { @@ -47,10 +13,20 @@ func purgePages(fpath string, fsize int64, rate float64) error { return fmt.Errorf("%.1f: rate should be over 0.0 and less than 1.0\n", rate) } - cs := C.CString(fpath) - defer C.free(unsafe.Pointer(cs)) - result := C.fadvise(cs, C.float(rate)) - if result == -1 { + f, err := os.Open(fpath) + if err != nil { + return err + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + return err + } + size := fi.Size() + + err = unix.Fadvise(int(f.Fd()), 0, int64(float64(size)*rate), unix.FADV_DONTNEED) + if err != nil { return fmt.Errorf("failed to purge page cache for %s", fpath) } diff --git a/cachectl/stat.go b/cachectl/stat.go index 87816df..02180bc 100644 --- a/cachectl/stat.go +++ b/cachectl/stat.go @@ -16,7 +16,12 @@ func PrintPagesStat(fpath string, fsize int64) { pages := (fsize + int64(pagesize) - 1) / int64(pagesize) - pagesActive := activePages(fpath) + pagesActive, err := activePages(fpath) + if err != nil { + log.Printf("%v\n", err) + return + } + activeRate := float64(0) if pagesActive == -1 { pagesActive = 0 diff --git a/glide.lock b/glide.lock index 926ba23..f5e877e 100644 --- a/glide.lock +++ b/glide.lock @@ -1,6 +1,10 @@ hash: 97ba093871d504b11b7aee975ce375916e97eee907bcfb9652a0d1b7644e7898 -updated: 2016-04-16T22:42:22.495229271+09:00 +updated: 2017-03-28T16:11:27.911677621+09:00 imports: - name: github.com/BurntSushi/toml version: bbd5bb678321a0d6e58f1099321dfa73391c1b6f -devImports: [] +- name: golang.org/x/sys + version: afadfcc7779c1f4db0f6f6438afcb108d9c9c7cd + subpackages: + - unix +testImports: [] diff --git a/glide.yaml b/glide.yaml index 84f95f0..118a059 100644 --- a/glide.yaml +++ b/glide.yaml @@ -2,3 +2,6 @@ package: github.com/cubicdaiya/cachectl import: - package: github.com/BurntSushi/toml version: v0.2.0 +- package: golang.org/x/sys + subpackages: + - unix