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/07 01:12:09 UTC

svn commit: r887808 - in /lucene/lucy/trunk/core/Lucy/Store: FSDirHandle.bp FSDirHandle.c

Author: marvin
Date: Mon Dec  7 00:12:08 2009
New Revision: 887808

URL: http://svn.apache.org/viewvc?rev=887808&view=rev
Log:
Commit LUCY-84, adding FSDirHandle -- essentially a wrapper around the OS
directory iterator.

Added:
    lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.bp   (with props)
    lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.c   (with props)

Added: lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.bp?rev=887808&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.bp (added)
+++ lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.bp Mon Dec  7 00:12:08 2009
@@ -0,0 +1,47 @@
+parcel Lucy;
+
+/** File system DirHandle.
+ */
+class Lucy::Store::FSDirHandle cnick FSDH 
+    extends Lucy::Store::DirHandle {
+    
+    void    *sys_dirhandle;
+    void    *sys_dir_entry;
+    CharBuf *fullpath;
+    Err     *saved_error;
+    bool_t   delayed_iter;
+
+    inert incremented FSDirHandle*
+    open(const CharBuf *path);
+
+    inert FSDirHandle*
+    do_open(FSDirHandle *self, const CharBuf *path);
+
+    bool_t
+    Next(FSDirHandle *self);
+
+    bool_t
+    Entry_Is_Dir(FSDirHandle *self);
+
+    bool_t
+    Close(FSDirHandle *self);
+
+    public void
+    Destroy(FSDirHandle *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/FSDirHandle.bp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.c?rev=887808&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.c (added)
+++ lucene/lucy/trunk/core/Lucy/Store/FSDirHandle.c Mon Dec  7 00:12:08 2009
@@ -0,0 +1,286 @@
+#define C_LUCY_FSDIRHANDLE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "Lucy/Util/ToolSet.h"
+#include "Lucy/Object/CharBuf.h"
+#include "Lucy/Object/Err.h"
+#include "Lucy/Object/VArray.h"
+#include "Lucy/Store/FSDirHandle.h"
+
+#ifdef CHY_HAS_SYS_TYPES_H
+  #include <sys/types.h>
+#endif
+
+FSDirHandle*
+FSDH_open(const CharBuf *dir)
+{
+    FSDirHandle *self = (FSDirHandle*)VTable_Make_Obj(FSDIRHANDLE);
+    return FSDH_do_open(self, dir);
+}
+
+void
+FSDH_destroy(FSDirHandle *self)
+{
+    /* Throw away saved error -- it's too late to call Close() now. */
+    DECREF(self->saved_error);
+    self->saved_error = NULL;
+    SUPER_DESTROY(self, FSDIRHANDLE);
+}
+
+static INLINE bool_t
+SI_is_updir(const char *name, size_t len)
+{
+    if (len == 2 && strncmp(name, "..", 2) == 0) {
+        return true;
+    }
+    else if (len == 1 && name[0] ==  '.') {
+        return true;
+    }
+    else {
+        return false;
+    }
+}
+
+/********************************** UNIXEN *********************************/
+#ifdef CHY_HAS_DIRENT_H
+
+#include <dirent.h>
+
+FSDirHandle*
+FSDH_do_open(FSDirHandle *self, const CharBuf *dir)
+{
+    char *dir_path_ptr = (char*)CB_Get_Ptr8(dir);
+
+    DH_init((DirHandle*)self, dir);
+    self->sys_dir_entry    = NULL;
+    self->fullpath         = NULL;
+
+    self->sys_dirhandle = opendir(dir_path_ptr);
+    if (!self->sys_dirhandle) {
+        Err_set_error(Err_new(CB_newf("Failed to opendir '%o'", dir)));
+        DECREF(self);
+        return NULL;
+    }
+    
+    return self;
+}
+
+bool_t
+FSDH_next(FSDirHandle *self)
+{
+    self->sys_dir_entry = (struct dirent*)readdir((DIR*)self->sys_dirhandle);
+    if (!self->sys_dir_entry) { 
+        CB_Set_Size(self->entry, 0);
+        return false; 
+    }
+    else {
+        struct dirent *sys_dir_entry = (struct dirent*)self->sys_dir_entry;
+        #ifdef CHY_HAS_DIRENT_D_NAMLEN
+        size_t len = sys_dir_entry->d_namlen;
+        #else
+        size_t len = strlen(sys_dir_entry->d_name);
+        #endif
+        if (SI_is_updir(sys_dir_entry->d_name, len)) {
+            return FSDH_Next(self);
+        }
+        else {
+            CB_Mimic_Str(self->entry, sys_dir_entry->d_name, len);
+            return true;
+        }
+    }
+}
+
+bool_t
+FSDH_entry_is_dir(FSDirHandle *self)
+{
+    struct dirent *sys_dir_entry = (struct dirent*)self->sys_dir_entry;
+    if (!sys_dir_entry) { return false; }
+
+    #ifdef CHY_HAS_DIRENT_D_TYPE
+    return sys_dir_entry->d_type == DT_DIR ? true : false;
+    #else 
+    /* Solaris struct dirent may not have a d_type member. :( */
+    {
+        struct stat stat_buf;
+        if (!self->fullpath) { 
+            self->fullpath = CB_new(CB_Get_Size(self->dir) + 20);
+        }
+        CB_setf(self->fullpath, "%o%s%o", self->dir, CHY_DIR_SEP,
+            self->entry);
+        if (stat((char*)CB_Get_Ptr8(self->fullpath), &stat_buf) != -1) {
+            if (stat_buf.st_mode & S_IFDIR) return true;
+        }
+        return false;
+    }
+    #endif /* CHY_HAS_DIRENT_D_TYPE */
+}
+
+bool_t
+FSDH_close(FSDirHandle *self)
+{
+    if (self->fullpath) {
+        CB_Dec_RefCount(self->fullpath);
+        self->fullpath = NULL;
+    }
+    if (self->sys_dirhandle) {
+        DIR *sys_dirhandle = (DIR*)self->sys_dirhandle;
+        self->sys_dirhandle = NULL;
+        if (closedir(sys_dirhandle) == -1) {
+            Err_set_error(Err_new(CB_newf("Error closing dirhandle: %s", 
+                strerror(errno))));
+            return false;
+        }
+    }
+    return true;
+}
+
+/********************************** Windows ********************************/
+#elif defined(CHY_HAS_WINDOWS_H)
+
+#include <windows.h>
+
+FSDirHandle*
+FSDH_do_open(FSDirHandle *self, const CharBuf *dir)
+{
+    size_t  dir_path_size = CB_Get_Size(dir);
+    char   *dir_path_ptr  = (char*)CB_Get_Ptr8(dir);
+    char    search_string[MAX_PATH + 1];
+    char   *path_ptr = search_string;
+
+    DH_init((DirHandle*)self, dir);
+    self->sys_dir_entry    = MALLOCATE(sizeof(WIN32_FIND_DATA));
+    self->sys_dirhandle    = INVALID_HANDLE_VALUE;
+    self->saved_error      = NULL;
+    
+    if (dir_path_size >= MAX_PATH - 2) {
+        /* Deal with Windows ceiling on file path lengths. */
+        Err_set_error(Err_new(CB_newf("Directory path is too long: %o", 
+            dir)));
+        DECREF(self);
+        return NULL;
+    }
+
+    /* Append trailing wildcard so Windows lists dir contents rather than just
+     * the dir name itself. */
+    memcpy(path_ptr, dir_path_ptr, dir_path_size);
+    memcpy(path_ptr + dir_path_size, "\\*\0", 3);
+
+    self->sys_dirhandle = FindFirstFile(search_string, 
+        (WIN32_FIND_DATA*)self->sys_dir_entry);
+    if (INVALID_HANDLE_VALUE == self->sys_dirhandle) {
+        /* Directory inaccessible or doesn't exist. */
+        Err_set_error(Err_new(CB_newf("Failed to open dir '%o'", dir)));
+        DECREF(self);
+        return NULL;
+    }
+    else {
+        /* Compensate for the fact that FindFirstFile has already returned the
+         * first entry but DirHandle's API requires that you call Next() to
+         * start the iterator. */
+        self->delayed_iter = true;
+    }
+
+    return self;
+}
+
+bool_t
+FSDH_entry_is_dir(FSDirHandle *self)
+{
+    WIN32_FIND_DATA *find_data = (WIN32_FIND_DATA*)self->sys_dir_entry;
+    if (find_data) { 
+        if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+            return true;
+        }
+    }
+    return false; 
+}
+
+bool_t
+FSDH_close(FSDirHandle *self)
+{
+    if (self->sys_dirhandle && self->sys_dirhandle != INVALID_HANDLE_VALUE) {
+        HANDLE dirhandle = (HANDLE)self->sys_dirhandle;
+        self->sys_dirhandle = NULL;
+        if (dirhandle != INVALID_HANDLE_VALUE && !FindClose(dirhandle)) {
+            if (!self->saved_error) {
+                char *win_error = Err_win_error();
+                self->saved_error = Err_new(CB_newf(
+                    "Error while closing directory: %s", win_error));
+                FREEMEM(win_error);
+            }
+        }
+    }
+    if (self->sys_dir_entry) { 
+        FREEMEM(self->sys_dir_entry);
+        self->sys_dir_entry = NULL;
+    }
+
+    /* If we encountered an error condition previously, report it now. */
+    if (self->saved_error) {
+        Err_set_error((Err*)INCREF(self->saved_error));
+        return false;
+    }
+    else {
+        return true;
+    }
+}
+
+bool_t
+FSDH_next(FSDirHandle *self)
+{
+    HANDLE           dirhandle = (HANDLE)self->sys_dirhandle;
+    WIN32_FIND_DATA *find_data = (WIN32_FIND_DATA*)self->sys_dir_entry;
+
+    /* Attempt to move forward or absorb cached iter. */
+    if (!dirhandle || dirhandle == INVALID_HANDLE_VALUE) {
+        return false;
+    }
+    else if (self->delayed_iter) {
+        self->delayed_iter = false;
+    }
+    else if ((FindNextFile(dirhandle, find_data) == 0)) {
+        /* Iterator exhausted.  Verify that no errors were encountered. */
+        CB_Set_Size(self->entry, 0);
+        if (GetLastError() != ERROR_NO_MORE_FILES) {
+            char *win_error = Err_win_error();
+            self->saved_error = Err_new(CB_newf(
+                "Error while traversing directory: %s", win_error));
+            FREEMEM(win_error);
+        }
+        return false;
+    }
+
+    /* Process the results of the iteration. */
+    {
+        size_t len = strlen(find_data->cFileName);
+        if (SI_is_updir(find_data->cFileName, len)) {
+            return FSDH_Next(self);
+        }
+        else {
+            CB_Mimic_Str(self->entry, find_data->cFileName, len);
+            return true;
+        }
+    }
+}
+
+#endif /* CHY_HAS_DIRENT_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/FSDirHandle.c
------------------------------------------------------------------------------
    svn:eol-style = native