From 82110d81c973bc6dbae1541f36b4a0c607d99541 Mon Sep 17 00:00:00 2001 From: Daniel Erat Date: Sun, 17 Jul 2011 23:12:02 +0000 Subject: [PATCH 1/3] sqlite go vfs work of dubious correctness: open, close Change-Id: I1bf4e67a3f96a53285635f0816075790a4543b55 --- misc/sqlite/sqlite3_os_go.c | 46 ++++++++++++++++++++++++++++++++----- misc/sqlite/vfs.go | 33 ++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/misc/sqlite/sqlite3_os_go.c b/misc/sqlite/sqlite3_os_go.c index 9fe31d32f..e9b096f10 100644 --- a/misc/sqlite/sqlite3_os_go.c +++ b/misc/sqlite/sqlite3_os_go.c @@ -6,23 +6,34 @@ #define SKIP_SQLITE_VERSION #include "sqlite3.h" +static sqlite3_io_methods g_file_methods; + typedef struct GoFile GoFile; struct GoFile { sqlite3_io_methods const *pMethod; /* Always the first entry */ + int fd; }; +static int go_file_close(sqlite3_file* file) { + return GoFileClose(((GoFile*) file)->fd) == 0 ? SQLITE_OK : SQLITE_ERROR; +} + static int go_vfs_open(sqlite3_vfs* vfs, const char* zName, sqlite3_file* file, int flags, int* pOutFlags) { - struct GoVFSOpen_return r; - r = GoVFSOpen((char*) zName, flags); - if (r.r0 == -1) { + GoFile* go_file = (GoFile*) file; + memset(go_file, 0, sizeof(go_file)); + + const int fd = GoVFSOpen((char*) zName, flags); + if (fd == -1) { return SQLITE_ERROR; } - return SQLITE_ERROR; + go_file->pMethod = &g_file_methods; + go_file->fd = fd; + return SQLITE_OK; } int sqlite3_os_init(void) { @@ -36,8 +47,6 @@ int sqlite3_os_init(void) { vfs.pAppData = NULL; vfs.xOpen = go_vfs_open; #if 0 - int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, - int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); @@ -69,6 +78,31 @@ int sqlite3_os_init(void) { }; #endif sqlite3_vfs_register(&vfs, 1); + + memset(&g_file_methods, 0, sizeof(g_file_methods)); + g_file_methods.iVersion = 1; + g_file_methods.xClose = go_file_close; +#if 0 + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Methods above are valid for version 1 */ + int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); + int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); + void (*xShmBarrier)(sqlite3_file*); + int (*xShmUnmap)(sqlite3_file*, int deleteFlag); + /* Methods above are valid for version 2 */ + /* Additional methods may be added in future releases */ +#endif + return SQLITE_OK; } diff --git a/misc/sqlite/vfs.go b/misc/sqlite/vfs.go index 7ea2b0131..f406d5fa4 100644 --- a/misc/sqlite/vfs.go +++ b/misc/sqlite/vfs.go @@ -1,9 +1,38 @@ package sqlite import "C" +import "os" +import "sync" + +var file_map_mutex sync.Mutex +var file_map = make(map[int]*os.File) + +func GetFile(fd int) (file *os.File) { + file_map_mutex.Lock() + defer file_map_mutex.Unlock() + return file_map[fd] +} + +//export GoFileClose +// Returns 0 on success and 1 on error. +func GoFileClose(fd C.int) (int) { + file := GetFile(int(fd)) + if file.Close() != nil { + return 1 + } + return 0 +} //export GoVFSOpen // fd is -1 on error. -func GoVFSOpen(filename *C.char, flags C.int) (int, int) { - return -1, 0 +func GoVFSOpen(filename *C.char, flags C.int) (int) { + file, err := os.OpenFile(C.GoString(filename), int(flags), 0) + if err != nil { + return -1 + } + + file_map_mutex.Lock() + defer file_map_mutex.Unlock() + file_map[file.Fd()] = file + return file.Fd() } From 5b1774164e1acf3a6841efc29106f38bcd44b22e Mon Sep 17 00:00:00 2001 From: Daniel Erat Date: Sun, 17 Jul 2011 23:58:53 +0000 Subject: [PATCH 2/3] sqlite: handle open flags Change-Id: I8382ea56aee06fc029e9538946598e70fe6fbb62 --- misc/sqlite/.gitignore | 1 + misc/sqlite/sqlite3_os_go.c | 100 +++++++++++++++++++++++++++++++----- misc/sqlite/vfs.go | 40 +++++++++++++-- 3 files changed, 123 insertions(+), 18 deletions(-) create mode 100644 misc/sqlite/.gitignore diff --git a/misc/sqlite/.gitignore b/misc/sqlite/.gitignore new file mode 100644 index 000000000..e206f1f68 --- /dev/null +++ b/misc/sqlite/.gitignore @@ -0,0 +1 @@ +foo.db diff --git a/misc/sqlite/sqlite3_os_go.c b/misc/sqlite/sqlite3_os_go.c index e9b096f10..251b69df4 100644 --- a/misc/sqlite/sqlite3_os_go.c +++ b/misc/sqlite/sqlite3_os_go.c @@ -1,4 +1,5 @@ #include +#include #include #include "_cgo_export.h" @@ -14,15 +15,30 @@ struct GoFile { int fd; }; +/* File methods */ + static int go_file_close(sqlite3_file* file) { return GoFileClose(((GoFile*) file)->fd) == 0 ? SQLITE_OK : SQLITE_ERROR; } +static int go_file_read(sqlite3_file* file, void* dest, int iAmt, sqlite3_int64 iOfst) { + fprintf(stderr, "read\n"); + return 0; +} + +static int go_file_write(sqlite3_file* file, const void* src, int iAmt, sqlite3_int64 iOfst) { + fprintf(stderr, "write\n"); + return 0; +} + +/* VFS methods */ + static int go_vfs_open(sqlite3_vfs* vfs, const char* zName, sqlite3_file* file, int flags, int* pOutFlags) { + fprintf(stderr, "go_vfs_open: %s\n", zName); GoFile* go_file = (GoFile*) file; memset(go_file, 0, sizeof(go_file)); @@ -36,28 +52,84 @@ static int go_vfs_open(sqlite3_vfs* vfs, return SQLITE_OK; } +static int go_vfs_delete(sqlite3_vfs* vfs, const char* zName, int syncDir) { + fprintf(stderr, "delete: %s\n", zName); + return SQLITE_OK; +} + +static int go_vfs_access(sqlite3_vfs* vfs, + const char* zName, + int flags, + int* pResOut) { + fprintf(stderr, "access: %s\n", zName); + return SQLITE_OK; +} + +static int go_vfs_full_pathname(sqlite3_vfs* vfs, + const char* zName, + int nOut, + char* zOut) { + strncpy(zOut, zName, nOut); + zOut[nOut - 1] = '\0'; + return SQLITE_OK; +} + +static void* go_vfs_dl_open(sqlite3_vfs* vfs, const char* zFilename) { + return NULL; +} + +static void go_vfs_dl_error(sqlite3_vfs* vfs, int nByte, char *zErrMsg) { +} + +static void* go_vfs_dl_sym(sqlite3_vfs* vfs, + void* handle, + const char* zSymbol) { + return NULL; +} + +static void go_vfs_dl_close(sqlite3_vfs* vfs, void* handle) { +} + +static int go_vfs_randomness(sqlite3_vfs* vfs, int nByte, char *zOut) { + return SQLITE_OK; +} + +static int go_vfs_sleep(sqlite3_vfs* vfs, int microseconds) { + return SQLITE_OK; +} + +static int go_vfs_current_time(sqlite3_vfs* vfs, double* now) { + return SQLITE_OK; +} + +static int go_vfs_get_last_error(sqlite3_vfs* vfs, int foo, char* bar) { + // Unused, per sqlite3's os_unix.c. + return SQLITE_OK; +} + int sqlite3_os_init(void) { static sqlite3_vfs vfs; memset(&vfs, 0, sizeof(vfs)); - vfs.iVersion = 3; + vfs.iVersion = 1; vfs.szOsFile = sizeof(GoFile); vfs.mxPathname = 512; vfs.pNext = NULL; vfs.zName = "go"; vfs.pAppData = NULL; + /* Version 1 methods */ vfs.xOpen = go_vfs_open; + vfs.xDelete = go_vfs_delete; + vfs.xAccess = go_vfs_access; + vfs.xFullPathname = go_vfs_full_pathname; + vfs.xDlOpen = go_vfs_dl_open; + vfs.xDlError = go_vfs_dl_error; + vfs.xDlSym = go_vfs_dl_sym; + vfs.xDlClose = go_vfs_dl_close; + vfs.xRandomness = go_vfs_randomness; + vfs.xSleep = go_vfs_sleep; + vfs.xCurrentTime = go_vfs_current_time; + vfs.xGetLastError = go_vfs_get_last_error; #if 0 - int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); - int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); - int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); - void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); - void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); - void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); - void (*xDlClose)(sqlite3_vfs*, void*); - int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); - int (*xSleep)(sqlite3_vfs*, int microseconds); - int (*xCurrentTime)(sqlite3_vfs*, double*); - int (*xGetLastError)(sqlite3_vfs*, int, char *); /* ** The methods above are in version 1 of the sqlite_vfs object ** definition. Those that follow are added in version 2 or later @@ -82,9 +154,9 @@ int sqlite3_os_init(void) { memset(&g_file_methods, 0, sizeof(g_file_methods)); g_file_methods.iVersion = 1; g_file_methods.xClose = go_file_close; + g_file_methods.xRead = go_file_read; + g_file_methods.xWrite = go_file_write; #if 0 - int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); - int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); int (*xSync)(sqlite3_file*, int flags); int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); diff --git a/misc/sqlite/vfs.go b/misc/sqlite/vfs.go index f406d5fa4..5a92ab0cf 100644 --- a/misc/sqlite/vfs.go +++ b/misc/sqlite/vfs.go @@ -1,8 +1,15 @@ package sqlite +/* +#define SKIP_SQLITE_VERSION +#include "sqlite3.h" +*/ import "C" -import "os" -import "sync" + +import ( + "os" + "sync" +) var file_map_mutex sync.Mutex var file_map = make(map[int]*os.File) @@ -25,8 +32,33 @@ func GoFileClose(fd C.int) (int) { //export GoVFSOpen // fd is -1 on error. -func GoVFSOpen(filename *C.char, flags C.int) (int) { - file, err := os.OpenFile(C.GoString(filename), int(flags), 0) +func GoVFSOpen(filename *C.char, flags C.int) (fd int) { + println("opening", C.GoString(filename), "with flags", int(flags)) + + goflags := 0 + if flags & C.SQLITE_OPEN_READONLY != 0 { + goflags |= os.O_RDONLY + } + if flags & C.SQLITE_OPEN_READWRITE != 0 { + goflags |= os.O_RDWR + } + if flags & C.SQLITE_OPEN_CREATE != 0 { + goflags |= os.O_RDWR | os.O_CREATE | os.O_TRUNC + } + if flags & C.SQLITE_OPEN_DELETEONCLOSE != 0 { + // TODO: Do something. + } + if flags & C.SQLITE_OPEN_EXCLUSIVE != 0{ + goflags |= os.O_EXCL + } + + file, err := os.OpenFile(C.GoString(filename), goflags, 0666) + defer func() { + if err != nil { + println("got error:", err.String()) + } + println("returning fd", fd); + }() if err != nil { return -1 } From 8d19dabe737868adef57373d8f974dc117739bea Mon Sep 17 00:00:00 2001 From: Daniel Erat Date: Mon, 18 Jul 2011 00:24:15 +0000 Subject: [PATCH 3/3] sqlite: read Change-Id: I925cce717ead61ae35d06602e9a7df16cc78db22 --- misc/sqlite/sqlite3_os_go.c | 5 +++-- misc/sqlite/vfs.go | 42 +++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/misc/sqlite/sqlite3_os_go.c b/misc/sqlite/sqlite3_os_go.c index 251b69df4..e2cbd83a1 100644 --- a/misc/sqlite/sqlite3_os_go.c +++ b/misc/sqlite/sqlite3_os_go.c @@ -22,8 +22,9 @@ static int go_file_close(sqlite3_file* file) { } static int go_file_read(sqlite3_file* file, void* dest, int iAmt, sqlite3_int64 iOfst) { - fprintf(stderr, "read\n"); - return 0; + return GoFileRead(((GoFile*) file)->fd, dest, iAmt, iOfst) == 0 ? + SQLITE_OK : + SQLITE_ERROR; } static int go_file_write(sqlite3_file* file, const void* src, int iAmt, sqlite3_int64 iOfst) { diff --git a/misc/sqlite/vfs.go b/misc/sqlite/vfs.go index 5a92ab0cf..2b10b4b74 100644 --- a/misc/sqlite/vfs.go +++ b/misc/sqlite/vfs.go @@ -1,6 +1,8 @@ package sqlite /* +#include + #define SKIP_SQLITE_VERSION #include "sqlite3.h" */ @@ -9,6 +11,7 @@ import "C" import ( "os" "sync" + "unsafe" ) var file_map_mutex sync.Mutex @@ -21,15 +24,50 @@ func GetFile(fd int) (file *os.File) { } //export GoFileClose -// Returns 0 on success and 1 on error. +// Returns 0 on success and -1 on error. func GoFileClose(fd C.int) (int) { file := GetFile(int(fd)) if file.Close() != nil { - return 1 + return -1 } return 0 } +//export GoFileRead +// Returns 0 on success and -1 on error. +func GoFileRead(fd C.int, dst *C.char, n C.int, offset C.int) (rv int) { + println("reading", n, "bytes at offset", offset, "from fd", fd); + defer func() { + println("read returning", rv); + }() + + file := GetFile(int(fd)) + if file == nil { + return -1 + } + + buf := make([]byte, n) + curbuf := buf + for n > 0 { + read, err := file.ReadAt(curbuf, int64(offset)) + curbuf = curbuf[read:] + n -= C.int(read) + if err == os.EOF { + break + } + if err != nil { + return -1 + } + } + + if n != 0 { + return -1 + } + + C.memcpy(unsafe.Pointer(dst), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) + return 0 +} + //export GoVFSOpen // fd is -1 on error. func GoVFSOpen(filename *C.char, flags C.int) (fd int) {