lucy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mar...@apache.org
Subject svn commit: r887762 - in /lucene/lucy/trunk: core/Lucy/Store/ core/Lucy/Test/Store/ perl/lib/Lucy/ perl/t/core/
Date Sun, 06 Dec 2009 20:22:42 GMT
Author: marvin
Date: Sun Dec  6 20:22:40 2009
New Revision: 887762

URL: http://svn.apache.org/viewvc?rev=887762&view=rev
Log:
Commit the remainder of LUCY-83.  Add FSFileHandle and associated tests.
Change InStream_open() and OutStream_open() to accept a CharBuf as an
option for "file", which will be interpreted as a filepath and used to derive
an FSFileHandle.

Added:
    lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.bp   (with props)
    lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.c   (with props)
    lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.bp   (with props)
    lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.c   (with props)
    lucene/lucy/trunk/perl/t/core/051-fs_file_handle.t   (with props)
Modified:
    lucene/lucy/trunk/core/Lucy/Store/InStream.c
    lucene/lucy/trunk/core/Lucy/Store/OutStream.c
    lucene/lucy/trunk/perl/lib/Lucy/Test.pm

Added: lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.bp?rev=887762&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.bp (added)
+++ lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.bp Sun Dec  6 20:22:40 2009
@@ -0,0 +1,60 @@
+parcel Lucy;
+
+/** File system FileHandle.
+ */
+class Lucy::Store::FSFileHandle cnick FSFH 
+    extends Lucy::Store::FileHandle {
+
+    int    fd;
+    void  *win_fhandle;
+    void  *win_maphandle;
+    i64_t  len;
+    i64_t  page_size;
+    char  *buf;
+
+    /** Return a new FSFileHandle, or set Err_error and return NULL if
+     * something goes wrong.
+     *
+     * @param path Filepath. 
+     * @param flags FileHandle constructor flags.
+     */
+    inert incremented FSFileHandle* 
+    open(const CharBuf *path = NULL, u32_t flags);
+
+    inert FSFileHandle* 
+    do_open(FSFileHandle *self, const CharBuf *path = NULL, u32_t flags);
+
+    bool_t
+    Window(FSFileHandle *self, FileWindow *window, i64_t offset, i64_t len);
+
+    bool_t
+    Release_Window(FSFileHandle *self, FileWindow *window);
+
+    bool_t
+    Read(FSFileHandle *self, char *dest, i64_t offset, size_t len);
+
+    bool_t
+    Write(FSFileHandle *self, const void *data, size_t len);
+
+    i64_t
+    Length(FSFileHandle *self);
+
+    bool_t
+    Close(FSFileHandle *self);
+}
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.bp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.c?rev=887762&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.c (added)
+++ lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.c Sun Dec  6 20:22:40 2009
@@ -0,0 +1,625 @@
+#define C_LUCY_FSFILEHANDLE
+#define C_LUCY_FILEWINDOW
+#include "Lucy/Util/ToolSet.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h> /* open, POSIX flags */
+#include <stdarg.h>
+
+#ifdef CHY_HAS_UNISTD_H 
+  #include <unistd.h> /* close */
+#endif
+
+#ifdef CHY_HAS_SYS_MMAN_H
+  #include <sys/mman.h>
+#elif defined(CHY_HAS_WINDOWS_H)
+  #include <windows.h>
+  #include <io.h>
+#else
+  #error "No support for memory mapped files"
+#endif
+
+#include "Lucy/Store/FSFileHandle.h"
+#include "Lucy/Store/FileWindow.h"
+
+/* Convert FileHandle flags to POSIX flags. */
+static INLINE int
+SI_posix_flags(u32_t fh_flags)
+{
+    int posix_flags = 0;
+    if (fh_flags & FH_WRITE_ONLY) { posix_flags |= O_WRONLY; }
+    if (fh_flags & FH_READ_ONLY)  { posix_flags |= O_RDONLY; }
+    if (fh_flags & FH_CREATE)     { posix_flags |= O_CREAT; }
+    if (fh_flags & FH_EXCLUSIVE)  { posix_flags |= O_EXCL; }
+#ifdef O_LARGEFILE
+    posix_flags |= O_LARGEFILE;
+#endif
+#ifdef _O_BINARY 
+    posix_flags |= _O_BINARY;
+#endif
+    return posix_flags;
+}
+
+#define IS_64_BIT (SIZEOF_PTR == 8 ? true : false)
+
+/* Memory map a region of the file with shared (read-only) permissions.  If
+ * the requested length is 0, return NULL.  If an error occurs, return NULL
+ * and set Err_error.
+ */
+static INLINE void*
+SI_map(FSFileHandle *self, i64_t offset, i64_t len);
+
+/* Release a memory mapped region assigned by SI_map. 
+ */
+static INLINE bool_t
+SI_unmap(FSFileHandle *self, char *ptr, i64_t len);
+
+/* 32-bit or 64-bit inlined helpers for FSFH_window. */
+static INLINE bool_t
+SI_window(FSFileHandle *self, FileWindow *window, i64_t offset, i64_t len);
+
+/* Architecture- and OS- specific initialization for a read-only FSFileHandle.
+ */
+static INLINE bool_t 
+SI_init_read_only(FSFileHandle *self);
+
+/* Windows-specific routine needed for closing read-only handles. */
+#ifdef CHY_HAS_WINDOWS_H
+static INLINE bool_t 
+SI_close_win_handles(FSFileHandle *self);
+#endif
+
+FSFileHandle*
+FSFH_open(const CharBuf *path, u32_t flags) 
+{
+    FSFileHandle *self = (FSFileHandle*)VTable_Make_Obj(FSFILEHANDLE);
+    return FSFH_do_open(self, path, flags);
+}
+
+FSFileHandle*
+FSFH_do_open(FSFileHandle *self, const CharBuf *path, u32_t flags) 
+{
+    FH_do_open((FileHandle*)self, path, flags);
+    if (!path || !CB_Get_Size(path)) {
+        Err_set_error(Err_new(CB_newf("Missing required param 'path'")));
+        DECREF(self);
+        return NULL;
+    }
+
+    /* Attempt to open file. */
+    if (flags & FH_WRITE_ONLY) {
+        self->fd = open((char*)CB_Get_Ptr8(path), SI_posix_flags(flags), 0666);
+        if (self->fd == -1) { 
+            self->fd = 0;
+            Err_set_error(Err_new(CB_newf("Attempt to open '%o' failed: %s", 
+                path, strerror(errno))));
+            DECREF(self);
+            return NULL;
+        }
+        if (flags & FH_EXCLUSIVE) {
+            self->len = 0;
+        }
+        else {
+            /* Derive length. */
+            self->len = lseek64(self->fd, I64_C(0), SEEK_END);
+            if (self->len == -1) {
+                Err_set_error(Err_new(CB_newf("lseek64 on %o failed: %s", 
+                    self->path, strerror(errno))));
+                DECREF(self);
+                return NULL;
+            }
+            else {
+                i64_t check_val = lseek64(self->fd, I64_C(0), SEEK_SET);
+                if (check_val == -1) {
+                    Err_set_error(Err_new(CB_newf("lseek64 on %o failed: %s", 
+                        self->path, strerror(errno))));
+                    DECREF(self);
+                    return NULL;
+                }
+            }
+        }
+    }
+    else if (flags & FH_READ_ONLY) {
+        if (SI_init_read_only(self)) {
+            /* On 64-bit systems, map the whole file up-front. */
+            if (IS_64_BIT && self->len) {
+                self->buf = (char*)SI_map(self, 0, self->len);
+                if (!self->buf) { 
+                    /* An error occurred during SI_map, which has set
+                     * Err_error for us already. */
+                    DECREF(self);
+                    return NULL;
+                }
+            }
+        }
+        else {
+            DECREF(self);
+            return NULL;
+        }
+    }
+    else {
+        Err_set_error(Err_new(CB_newf(
+            "Must specify FH_READ_ONLY or FH_WRITE_ONLY to open '%o'", 
+            path)));
+        DECREF(self);
+        return NULL;
+    }
+
+    return self;
+}
+
+bool_t
+FSFH_close(FSFileHandle *self)
+{
+    /* On 64-bit systems, cancel the whole-file mapping. */
+    if (IS_64_BIT && (self->flags & FH_READ_ONLY)) {
+        if ( !SI_unmap(self, self->buf, self->len) ) { return false; }
+        self->buf = NULL;
+    }
+    
+    /* Close system-specific handles. */
+    if (self->fd) {
+        if (close(self->fd)) {
+            Err_set_error(Err_new(CB_newf("Failed to close file: %s", 
+                strerror(errno))));
+            return false;
+        }
+        self->fd  = 0;
+    }
+    #ifdef CHY_HAS_WINDOWS_H
+    if (self->win_fhandle) {
+        if (!SI_close_win_handles(self)) { return false; }
+    }
+    #endif
+
+    return true;
+}
+
+bool_t
+FSFH_write(FSFileHandle *self, const void *data, size_t len) 
+{
+    if (len) { 
+        /* Write data, track file length, check for errors. */
+        i64_t check_val = write(self->fd, data, len);
+        self->len += check_val;
+        if (check_val != len) {
+            if (check_val == -1) {
+                Err_set_error(Err_new(CB_newf(
+                    "Error when writing %u64 bytes: %s",
+                    (u64_t)len, strerror(errno))));
+            }
+            else {
+                Err_set_error(Err_new(CB_newf(
+                    "Attempted to write %u64 bytes, but wrote %i64", 
+                    (u64_t)len, check_val)));
+            }
+            return false;
+        }
+    }
+
+    return true;
+}
+
+i64_t
+FSFH_length(FSFileHandle *self)
+{
+    return self->len;
+}
+
+bool_t
+FSFH_window(FSFileHandle *self, FileWindow *window, i64_t offset, i64_t len)
+{
+    const i64_t end = offset + len;
+    if (!(self->flags & FH_READ_ONLY)) {
+        Err_set_error(Err_new(CB_newf("Can't read from write-only handle")));
+        return false;
+    }
+    else if (offset < 0) {
+        Err_set_error(Err_new(CB_newf("Can't read from negative offset %i64", 
+            offset)));
+        return false;
+    }
+    else if (end > self->len) {
+        Err_set_error(Err_new(CB_newf(
+            "Tried to read past EOF: offset %i64 + request %i64 > len %i64", 
+            offset, len, self->len)));
+        return false;
+    }
+    else {
+		return SI_window(self, window, offset, len);
+	}
+}
+
+/********************************* 64-bit *********************************/
+
+#if IS_64_BIT
+
+static INLINE bool_t
+SI_window(FSFileHandle *self, FileWindow *window, i64_t offset, i64_t len)
+{
+	FileWindow_Set_Window(window, self->buf + offset, offset, len);
+	return true;
+}
+
+bool_t
+FSFH_release_window(FSFileHandle *self, FileWindow *window)
+{
+    UNUSED_VAR(self);
+    FileWindow_Set_Window(window, NULL, 0, 0);
+    return true;
+}
+
+bool_t
+FSFH_read(FSFileHandle *self, char *dest, i64_t offset, size_t len)
+{
+    const i64_t end = offset + len;
+    if (offset < 0) {
+        Err_set_error(Err_new(CB_newf(
+            "Can't read from an offset less than 0 (%i64)", offset)));
+        return false;
+    }
+    else if (end > self->len) {
+        Err_set_error(Err_new(CB_newf(
+            "Tried to read past EOF: offset %i64 + request %u64 > len %i64", 
+            offset, (u64_t)len, self->len)));
+        return false;
+    }
+    memcpy(dest, self->buf + offset, len);
+    return true;
+}
+
+/********************************* 32-bit *********************************/
+
+#else
+
+static INLINE bool_t
+SI_window(FSFileHandle *self, FileWindow *window, i64_t offset, i64_t len)
+{
+	/* Release the previously mmap'd region, if any. */
+	FSFH_release_window(self, window);
+
+	{
+		/* Start map on a page boundary.  Ensure that the window is at
+		 * least wide enough to view all the data spec'd in the original
+		 * request. */
+		const i64_t remainder       = offset % self->page_size;
+		const i64_t adjusted_offset = offset - remainder;
+		const i64_t adjusted_len    = len + remainder;
+		char *const buf 
+			= (char*)SI_map(self, adjusted_offset, adjusted_len);
+		if (len && buf == NULL) {
+			return false;
+		}
+		else {
+			FileWindow_Set_Window(window, buf, adjusted_offset, 
+				adjusted_len);
+		}
+	}
+
+	return true;
+}
+
+bool_t
+FSFH_release_window(FSFileHandle *self, FileWindow *window)
+{
+    if ( !SI_unmap(self, window->buf, window->len) ) { return false; }
+    FileWindow_Set_Window(window, NULL, 0, 0);
+    return true;
+}
+
+#endif /* IS_64_BIT vs. 32-bit */
+
+/********************************* UNIXEN *********************************/
+
+#ifdef CHY_HAS_SYS_MMAN_H
+
+static INLINE bool_t 
+SI_init_read_only(FSFileHandle *self)
+{
+    /* Open. */
+    self->fd = open((char*)CB_Get_Ptr8(self->path), 
+        SI_posix_flags(self->flags), 0666);
+    if (self->fd == -1) {
+        self->fd = 0;
+        Err_set_error(Err_new(CB_newf("Can't open '%o': %s", self->path,
+            strerror(errno))));
+        return false;
+    }
+
+    /* Derive len. */
+    self->len = lseek64(self->fd, I64_C(0), SEEK_END);
+    if (self->len == -1) {
+        Err_set_error(Err_new(CB_newf("lseek64 on %o failed: %s", self->path,
+            strerror(errno))));
+        return false;
+    }
+    else {
+        i64_t check_val = lseek64(self->fd, I64_C(0), SEEK_SET);
+        if (check_val == -1) {
+            Err_set_error(Err_new(CB_newf("lseek64 on %o failed: %s",
+                self->path, strerror(errno))));
+            return false;
+        }
+    }
+
+    /* Get system page size. */
+#if defined(_SC_PAGESIZE)
+    self->page_size = sysconf(_SC_PAGESIZE);
+#elif defined(_SC_PAGE_SIZE)
+    self->page_size = sysconf(_SC_PAGE_SIZE);
+#else
+    #error "Can't determine system memory page size"
+#endif
+    
+    return true;
+}
+
+static INLINE void*
+SI_map(FSFileHandle *self, i64_t offset, i64_t len)
+{
+    void *buf = NULL;
+
+    if (len) {
+        /* Read-only memory mapping. */
+        buf = mmap(NULL, len, PROT_READ, MAP_SHARED, self->fd, offset);
+        if (buf == (void*)-1) {
+            Err_set_error(Err_new(CB_newf(
+                "mmap of offset %i64 and length %i64 (page size %i64) "
+                "against '%o' failed: %s", offset, len, self->page_size,
+                self->path, strerror(errno))));
+            return NULL;
+        }
+    }
+
+    return buf;
+}
+
+static INLINE bool_t
+SI_unmap(FSFileHandle *self, char *buf, i64_t len)
+{
+    if (buf != NULL) {
+        if (munmap(buf, len)) {
+            Err_set_error(Err_new(CB_newf("Failed to munmap '%o': %s",
+                self->path, strerror(errno))));
+            return false;
+        }
+    }
+    return true;
+}
+
+#if !IS_64_BIT
+bool_t
+FSFH_read(FSFileHandle *self, char *dest, i64_t offset, size_t len)
+{
+    i64_t check_val;
+    
+    /* Sanity check. */
+    if (offset < 0) {
+        Err_set_error(Err_new(CB_newf(
+            "Can't read from an offset less than 0 (%i64)", offset)));
+        return false;
+    }
+
+    /* Read. */
+    check_val = pread64(self->fd, dest, len, offset);
+    if (check_val != (i64_t)len) {
+        if (check_val == -1) {
+            Err_set_error(Err_new(CB_newf(
+                "Tried to read %u64 bytes, got %i64: %s",
+                (u64_t)len, check_val, strerror(errno))));
+        }
+        else {
+            Err_set_error(Err_new(CB_newf(
+                "Tried to read %u64 bytes, got %i64", 
+                (u64_t)len, check_val)));
+        }
+        return false;
+    }
+
+    return true;
+}
+#endif /* !IS_64_BIT */
+
+/********************************* WINDOWS **********************************/
+
+#elif defined(CHY_HAS_WINDOWS_H)
+
+static INLINE bool_t 
+SI_init_read_only(FSFileHandle *self)
+{
+    LARGE_INTEGER large_int;
+    char *filepath = (char*)CB_Get_Ptr8(self->path);
+    SYSTEM_INFO sys_info;
+
+    /* Get system page size. */
+    GetSystemInfo(&sys_info);
+    self->page_size = sys_info.dwAllocationGranularity;
+
+    /* Open. */
+    self->win_fhandle = CreateFile(
+        filepath,
+        GENERIC_READ,
+        FILE_SHARE_READ,
+        NULL,
+        OPEN_EXISTING,
+        FILE_ATTRIBUTE_READONLY | FILE_FLAG_OVERLAPPED,
+        NULL
+    );
+    if (self->win_fhandle == INVALID_HANDLE_VALUE) {
+        char *win_error = Err_win_error();
+        Err_set_error(Err_new(CB_newf("CreateFile for %o failed: %s", 
+            self->path, win_error)));
+        FREEMEM(win_error);
+        return false;
+    }
+
+    /* Derive len. */
+    GetFileSizeEx(self->win_fhandle, &large_int);
+    self->len = large_int.QuadPart;
+    if (self->len < 0) {
+        Err_set_error(Err_new(CB_newf(
+            "GetFileSizeEx for %o returned a negative length: '%i64'", 
+            self->path, self->len)));
+        return false;
+    }
+
+    /* Init mapping handle. */
+    self->buf = NULL;
+    if (self->len) {
+        self->win_maphandle = CreateFileMapping(self->win_fhandle, NULL,
+            PAGE_READONLY, 0, 0, NULL);
+        if (self->win_maphandle == NULL) {
+            char *win_error = Err_win_error();
+            Err_set_error(Err_new(CB_newf(
+                "CreateFileMapping for %o failed: %s", 
+                self->path, win_error)));
+            FREEMEM(win_error);
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+static INLINE void*
+SI_map(FSFileHandle *self, i64_t offset, i64_t len)
+{
+    void *buf = NULL;
+
+    if (len) {
+        /* Read-only memory map. */
+        u64_t offs = (u64_t)offset;
+        DWORD file_offset_hi = offs >> 32;
+        DWORD file_offset_lo = offs & 0xFFFFFFFF;
+        size_t amount = (size_t)len;
+        buf = MapViewOfFile(
+            self->win_maphandle, 
+            FILE_MAP_READ, 
+            file_offset_hi,
+            file_offset_lo,
+            amount
+        );
+        if (buf == NULL) {
+            char *win_error = Err_win_error();
+            Err_set_error(Err_new(CB_newf(
+                "MapViewOfFile for %o failed: %s", 
+                self->path, win_error)));
+            FREEMEM(win_error);
+        }
+    }
+
+    return buf;
+}
+
+static INLINE bool_t
+SI_unmap(FSFileHandle *self, char *buf, i64_t len)
+{
+    if (buf != NULL) {
+        if (!UnmapViewOfFile(buf)) {
+            char *win_error = Err_win_error();
+            Err_set_error(Err_new(CB_newf("Failed to unmap '%o': %s", 
+                self->path, win_error)));
+            FREEMEM(win_error);
+            return false;
+        }
+    }
+    return true;
+}
+
+static INLINE bool_t 
+SI_close_win_handles(FSFileHandle *self)
+{
+    /* Close both standard handle and mapping handle. */
+    if (self->win_maphandle) {
+        if (!CloseHandle(self->win_maphandle)) {
+            char *win_error = Err_win_error();
+            Err_set_error(Err_new(CB_newf(
+                "Failed to close file mapping handle: %s", win_error)));
+            FREEMEM(win_error);
+            return false;
+        }
+        self->win_maphandle = NULL;
+    }
+    if (self->win_fhandle) {
+        if (!CloseHandle(self->win_fhandle)) {
+            char *win_error = Err_win_error();
+            Err_set_error(Err_new(CB_newf("Failed to close file handle: %s",
+                win_error)));
+            FREEMEM(win_error);
+            return false;
+        }
+        self->win_fhandle = NULL;
+    }
+
+    return true;
+}
+
+#if !IS_64_BIT
+bool_t
+FSFH_read(FSFileHandle *self, char *dest, i64_t offset, size_t len)
+{
+    BOOL check_val;
+    DWORD got;
+    OVERLAPPED read_op_state;
+    u64_t offs = (u64_t)offset;
+
+    read_op_state.hEvent     = NULL;
+    read_op_state.OffsetHigh = offs >> 32;
+    read_op_state.Offset     = offs & 0xFFFFFFFF;
+    
+    /* Sanity check. */
+    if (offset < 0) {
+        Err_set_error(Err_new(CB_newf(
+            "Can't read from an offset less than 0 (%i64)", offset)));
+        return false;
+    }
+
+    /* ReadFile() takes a DWORD (unsigned 32-bit integer) as a length
+     * argument, so throw a sensible error rather than wrap around. */
+    if (len > U32_MAX) {
+        Err_set_error(Err_new(CB_newf(
+            "Can't read more than 4 GB (%u64)", (u64_t)len))); 
+        return false;
+    }
+
+    /* Read. */
+    check_val = ReadFile(self->win_fhandle, dest, len, &got, &read_op_state);
+    if (!check_val && GetLastError() == ERROR_IO_PENDING) {
+        /* Read has been queued by the OS and will soon complete.  Wait for
+         * it, since this is a blocking IO call from the point of the rest of
+         * the library. */
+        check_val = GetOverlappedResult(self->win_fhandle, &read_op_state,
+           &got, TRUE);
+    }
+
+    /* Verify that the read has succeeded by now. */
+    if (!check_val) {
+        char *win_error = Err_win_error();
+        Err_set_error(Err_new(CB_newf("Failed to read %u64 bytes: %s",
+            (u64_t)len, win_error)));
+        FREEMEM(win_error);
+        return false;
+    }
+
+    return true;
+}
+#endif /* !IS_64_BIT */
+
+#endif /* CHY_HAS_SYS_MMAN_H vs. CHY_HAS_WINDOWS_H */
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Store/FSFileHandle.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: lucene/lucy/trunk/core/Lucy/Store/InStream.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Store/InStream.c?rev=887762&r1=887761&r2=887762&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Store/InStream.c (original)
+++ lucene/lucy/trunk/core/Lucy/Store/InStream.c Sun Dec  6 20:22:40 2009
@@ -4,6 +4,7 @@
 
 #include "Lucy/Store/InStream.h"
 #include "Lucy/Store/FileHandle.h"
+#include "Lucy/Store/FSFileHandle.h"
 #include "Lucy/Store/FileWindow.h"
 #include "Lucy/Store/RAMFile.h"
 #include "Lucy/Store/RAMFileHandle.h"
@@ -54,12 +55,10 @@
         self->file_handle 
             = (FileHandle*)RAMFH_open(NULL, FH_READ_ONLY, (RAMFile*)file);
     }
-    /*
     else if (Obj_Is_A(file, CHARBUF)) {
         self->file_handle 
             = (FileHandle*)FSFH_open((CharBuf*)file, FH_READ_ONLY);
     }
-    */
     else {
         Err_set_error(Err_new(CB_newf("Invalid type for param 'file': '%o'",
             Obj_Get_Class_Name(file))));

Modified: lucene/lucy/trunk/core/Lucy/Store/OutStream.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Store/OutStream.c?rev=887762&r1=887761&r2=887762&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Store/OutStream.c (original)
+++ lucene/lucy/trunk/core/Lucy/Store/OutStream.c Sun Dec  6 20:22:40 2009
@@ -3,6 +3,7 @@
 
 #include "Lucy/Store/OutStream.h"
 #include "Lucy/Store/FileHandle.h"
+#include "Lucy/Store/FSFileHandle.h"
 #include "Lucy/Store/FileWindow.h"
 #include "Lucy/Store/InStream.h"
 #include "Lucy/Store/RAMFile.h"
@@ -43,12 +44,10 @@
         self->file_handle 
             = (FileHandle*)RAMFH_open(NULL, FH_WRITE_ONLY, (RAMFile*)file);
     }
-    /*
     else if (Obj_Is_A(file, CHARBUF)) {
         self->file_handle = (FileHandle*)FSFH_open((CharBuf*)file,
             FH_WRITE_ONLY | FH_CREATE | FH_EXCLUSIVE );
     }
-    */
     else {
         Err_set_error(Err_new(CB_newf("Invalid type for param 'file': '%o'",
             Obj_Get_Class_Name(file))));

Added: lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.bp?rev=887762&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.bp (added)
+++ lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.bp Sun Dec  6 20:22:40 2009
@@ -0,0 +1,22 @@
+parcel Lucy;
+
+inert class Lucy::Test::Store::TestFSFileHandle cnick TestFSFH {
+    inert void
+    run_tests();
+}
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.bp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.c?rev=887762&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.c (added)
+++ lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.c Sun Dec  6 20:22:40 2009
@@ -0,0 +1,253 @@
+#include <stdio.h> /* for remove() */
+
+#define C_LUCY_CHARBUF
+#define C_LUCY_FSFILEHANDLE
+#define C_LUCY_FILEWINDOW
+#include "Lucy/Util/ToolSet.h"
+
+#ifdef CHY_HAS_UNISTD_H 
+  #include <unistd.h> /* close */
+#elif defined(CHY_HAS_IO_H)
+  #include <io.h> /* close */
+#endif
+
+#define CHAZ_USE_SHORT_NAMES
+#include "Charmonizer/Test.h"
+#include "Lucy/Test/Store/TestFSFileHandle.h"
+#include "Lucy/Store/FSFileHandle.h"
+#include "Lucy/Store/FileWindow.h"
+
+static CharBuf test_filename = ZCB_LITERAL("_fsfh_test_file");
+
+static void
+test_open(TestBatch *batch)
+{
+    FSFileHandle *fh;
+
+    remove((char*)CB_Get_Ptr8(&test_filename));
+
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_READ_ONLY);
+    ASSERT_TRUE(batch, fh == NULL, 
+        "open() with FH_READ_ONLY on non-existent file returns NULL");
+    ASSERT_TRUE(batch, Err_get_error() != NULL,
+        "open() with FH_READ_ONLY on non-existent file sets error");
+
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_WRITE_ONLY);
+    ASSERT_TRUE(batch, fh == NULL, 
+        "open() without FH_CREATE returns NULL");
+    ASSERT_TRUE(batch, Err_get_error() != NULL,
+        "open() without FH_CREATE sets error");
+
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_CREATE);
+    ASSERT_TRUE(batch, fh == NULL, 
+        "open() without FH_WRITE_ONLY returns NULL");
+    ASSERT_TRUE(batch, Err_get_error() != NULL,
+        "open() without FH_WRITE_ONLY sets error");
+
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
+    ASSERT_TRUE(batch, fh && FSFH_Is_A(fh, FSFILEHANDLE), "open() succeeds");
+    ASSERT_TRUE(batch, Err_get_error() == NULL, "open() no errors");
+    FSFH_Write(fh, "foo", 3);
+    if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
+    DECREF(fh);
+
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
+    ASSERT_TRUE(batch, fh == NULL, "FH_EXCLUSIVE blocks open()");
+    ASSERT_TRUE(batch, Err_get_error() != NULL,
+        "FH_EXCLUSIVE blocks open(), sets error");
+
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_CREATE | FH_WRITE_ONLY);
+    ASSERT_TRUE(batch, fh && FSFH_Is_A(fh, FSFILEHANDLE), 
+        "open() for append");
+    ASSERT_TRUE(batch, Err_get_error() == NULL, 
+        "open() for append -- no errors");
+    FSFH_Write(fh, "bar", 3);
+    if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
+    DECREF(fh);
+
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_READ_ONLY);
+    ASSERT_TRUE(batch, fh && FSFH_Is_A(fh, FSFILEHANDLE), "open() read only");
+    ASSERT_TRUE(batch, Err_get_error() == NULL, 
+        "open() read only -- no errors");
+    DECREF(fh);
+    
+    remove((char*)CB_Get_Ptr8(&test_filename));
+}
+
+static void
+test_Read_Write(TestBatch *batch)
+{
+    FSFileHandle *fh;
+    const char *foo = "foo";
+    const char *bar = "bar";
+    char buffer[12];
+    char *buf = buffer;
+
+    remove((char*)CB_Get_Ptr8(&test_filename));
+    fh = FSFH_open(&test_filename, 
+        FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
+
+    ASSERT_TRUE(batch, FSFH_Length(fh) == I64_C(0), "Length initially 0");
+    ASSERT_TRUE(batch, FSFH_Write(fh, foo, 3), "Write returns success");
+    ASSERT_TRUE(batch, FSFH_Length(fh) == I64_C(3), "Length after Write");
+    ASSERT_TRUE(batch, FSFH_Write(fh, bar, 3), "Write returns success");
+    ASSERT_TRUE(batch, FSFH_Length(fh) == I64_C(6), "Length after 2 Writes");
+
+    Err_set_error(NULL);
+    ASSERT_FALSE(batch, FSFH_Read(fh, buf, 0, 2), 
+        "Reading from a write-only handle returns false");
+    ASSERT_TRUE(batch, Err_get_error() != NULL, 
+        "Reading from a write-only handle sets error");
+    if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
+    DECREF(fh);
+
+    /* Reopen for reading. */
+    Err_set_error(NULL);
+    fh = FSFH_open(&test_filename, FH_READ_ONLY);
+
+    ASSERT_TRUE(batch, FSFH_Length(fh) == I64_C(6), "Length on Read");
+    ASSERT_TRUE(batch, FSFH_Read(fh, buf, 0, 6), "Read returns success");
+    ASSERT_TRUE(batch, strncmp(buf, "foobar", 6) == 0, "Read/Write");
+    ASSERT_TRUE(batch, FSFH_Read(fh, buf, 2, 3), "Read returns success");
+    ASSERT_TRUE(batch, strncmp(buf, "oba", 3) == 0, "Read with offset");
+
+    Err_set_error(NULL);
+    ASSERT_FALSE(batch, FSFH_Read(fh, buf, -1, 4),
+        "Read() with a negative offset returns false");
+    ASSERT_TRUE(batch, Err_get_error() != NULL, 
+        "Read() with a negative offset sets error");
+
+    Err_set_error(NULL);
+    ASSERT_FALSE(batch, FSFH_Read(fh, buf, 6, 1),
+        "Read() past EOF returns false");
+    ASSERT_TRUE(batch, Err_get_error() != NULL, 
+        "Read() past EOF sets error");
+
+    Err_set_error(NULL);
+    ASSERT_FALSE(batch, FSFH_Write(fh, foo, 3), 
+        "Writing to a read-only handle returns false");
+    ASSERT_TRUE(batch, Err_get_error() != NULL, 
+        "Writing to a read-only handle sets error");
+
+    DECREF(fh);
+    remove((char*)CB_Get_Ptr8(&test_filename));
+}
+
+static void
+test_Close(TestBatch *batch)
+{
+    FSFileHandle *fh;
+    bool_t        result;
+
+    remove((char*)CB_Get_Ptr8(&test_filename));
+    fh = FSFH_open(&test_filename, 
+        FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
+    ASSERT_TRUE(batch, FSFH_Close(fh), "Close returns true for write-only");
+    DECREF(fh);
+
+    /* Simulate an OS error when closing the file descriptor.  This
+     * approximates what would happen if, say, we run out of disk space. */
+    remove((char*)CB_Get_Ptr8(&test_filename));
+    fh = FSFH_open(&test_filename, 
+        FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
+    close(fh->fd);
+    fh->fd = -1;
+    Err_set_error(NULL);
+    result = FSFH_Close(fh);
+    ASSERT_FALSE(batch, result, "Failed Close() returns false");
+    ASSERT_TRUE(batch, Err_get_error() != NULL, 
+        "Failed Close() sets Err_error");
+    DECREF(fh);
+
+    fh = FSFH_open(&test_filename, FH_READ_ONLY);
+    ASSERT_TRUE(batch, FSFH_Close(fh), "Close returns true for read-only");
+
+    DECREF(fh);
+    remove((char*)CB_Get_Ptr8(&test_filename));
+}
+
+static void
+test_Window(TestBatch *batch)
+{
+    FSFileHandle *fh;
+    FileWindow *window = FileWindow_new();
+    u32_t i;
+
+    remove((char*)CB_Get_Ptr8(&test_filename));
+    fh = FSFH_open(&test_filename, 
+        FH_CREATE | FH_WRITE_ONLY | FH_EXCLUSIVE);
+    for (i = 0; i < 1024; i++) {
+        FSFH_Write(fh, "foo ", 4);
+    }
+    if (!FSFH_Close(fh)) { RETHROW(INCREF(Err_get_error())); }
+
+    /* Reopen for reading. */
+    DECREF(fh);
+    fh = FSFH_open(&test_filename, FH_READ_ONLY);
+    if (!fh) { RETHROW(INCREF(Err_get_error())); }
+
+    Err_set_error(NULL);
+    ASSERT_FALSE(batch, FSFH_Window(fh, window, -1, 4),
+        "Window() with a negative offset returns false");
+    ASSERT_TRUE(batch, Err_get_error() != NULL, 
+        "Window() with a negative offset sets error");
+
+    Err_set_error(NULL);
+    ASSERT_FALSE(batch, FSFH_Window(fh, window, 4000, 1000),
+        "Window() past EOF returns false");
+    ASSERT_TRUE(batch, Err_get_error() != NULL, 
+        "Window() past EOF sets error");
+
+    ASSERT_TRUE(batch, FSFH_Window(fh, window, 1021, 2), 
+        "Window() returns true");
+    ASSERT_TRUE(batch, 
+        strncmp(window->buf + window->offset + 1021, "oo", 2) == 0, 
+        "Window()");
+
+    ASSERT_TRUE(batch, FSFH_Release_Window(fh, window), 
+        "Release_Window() returns true");
+    ASSERT_TRUE(batch, window->buf == NULL, "Release_Window() resets buf");
+    ASSERT_TRUE(batch, window->offset == 0, "Release_Window() resets offset");
+    ASSERT_TRUE(batch, window->len == 0, "Release_Window() resets len");
+
+    DECREF(window);
+    DECREF(fh);
+    remove((char*)CB_Get_Ptr8(&test_filename));
+}
+
+void
+TestFSFH_run_tests()
+{
+    TestBatch *batch = Test_new_batch("TestFSFileHandle", 46, NULL);
+
+    PLAN(batch);
+    test_open(batch);
+    test_Read_Write(batch);
+    test_Close(batch);
+    test_Window(batch);
+
+    batch->destroy(batch);
+}
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Test/Store/TestFSFileHandle.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: lucene/lucy/trunk/perl/lib/Lucy/Test.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/lib/Lucy/Test.pm?rev=887762&r1=887761&r2=887762&view=diff
==============================================================================
--- lucene/lucy/trunk/perl/lib/Lucy/Test.pm (original)
+++ lucene/lucy/trunk/perl/lib/Lucy/Test.pm Sun Dec  6 20:22:40 2009
@@ -46,6 +46,9 @@
     else if (strEQ(package, "TestCompoundFileWriter")) {
         lucy_TestCFWriter_run_tests();
     }
+    else if (strEQ(package, "TestFSFileHandle")) {
+        lucy_TestFSFH_run_tests();
+    }
     else if (strEQ(package, "TestFileHandle")) {
         lucy_TestFH_run_tests();
     }

Added: lucene/lucy/trunk/perl/t/core/051-fs_file_handle.t
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/t/core/051-fs_file_handle.t?rev=887762&view=auto
==============================================================================
--- lucene/lucy/trunk/perl/t/core/051-fs_file_handle.t (added)
+++ lucene/lucy/trunk/perl/t/core/051-fs_file_handle.t Sun Dec  6 20:22:40 2009
@@ -0,0 +1,6 @@
+use strict;
+use warnings;
+
+use Lucy::Test;
+Lucy::Test::run_tests("TestFSFileHandle");
+

Propchange: lucene/lucy/trunk/perl/t/core/051-fs_file_handle.t
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message