You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2009/12/06 21:22:42 UTC
svn commit: r887762 - in /lucene/lucy/trunk: core/Lucy/Store/
core/Lucy/Test/Store/ perl/lib/Lucy/ perl/t/core/
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