X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Ffile-handle-def.c;h=2b8e40ce347b7935b68589083dcda03030c07a74;hb=9ade26c8349b4434008c46cf09bc7473ec743972;hp=6ed3f8f9f95205158cbf2a33227e5dbec6a81529;hpb=9254d30d06a0565c89daccedd93a94c4c6086004;p=pspp-builds.git diff --git a/src/data/file-handle-def.c b/src/data/file-handle-def.c index 6ed3f8f9..2b8e40ce 100644 --- a/src/data/file-handle-def.c +++ b/src/data/file-handle-def.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,23 +16,24 @@ #include -#include "file-handle-def.h" +#include "data/file-handle-def.h" #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "libpspp/compiler.h" +#include "libpspp/hmap.h" +#include "libpspp/i18n.h" +#include "libpspp/message.h" +#include "libpspp/str.h" +#include "libpspp/hash-functions.h" +#include "data/file-name.h" +#include "data/variable.h" +#include "data/scratch-handle.h" -#include "xalloc.h" +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -40,7 +41,7 @@ /* File handle. */ struct file_handle { - struct ll ll; /* Element in global list. */ + struct hmap_node name_node; /* Element in named_handles hmap. */ size_t ref_cnt; /* Number of references. */ char *id; /* Identifier token, NULL if none. */ char *name; /* User-friendly identifying name. */ @@ -59,14 +60,8 @@ struct file_handle struct scratch_handle *sh; /* Scratch file data. */ }; -static struct file_handle * -file_handle_from_ll (struct ll *ll) -{ - return ll_data (ll, struct file_handle, ll); -} - -/* List of all named handles. */ -static struct ll_list named_handles; +/* All "struct file_handle"s with nonnull 'id' member. */ +static struct hmap named_handles = HMAP_INITIALIZER (named_handles); /* Default file handle for DATA LIST, REREAD, REPEATING DATA commands. */ @@ -80,11 +75,13 @@ static struct file_handle *create_handle (const char *id, static void free_handle (struct file_handle *); static void unname_handle (struct file_handle *); +/* Hash table of all active locks. */ +static struct hmap locks = HMAP_INITIALIZER (locks); + /* File handle initialization routine. */ void fh_init (void) { - ll_init (&named_handles); inline_file = create_handle ("INLINE", xstrdup ("INLINE"), FH_REF_INLINE); inline_file->record_width = 80; inline_file->tab_width = 8; @@ -94,8 +91,11 @@ fh_init (void) void fh_done (void) { - while (!ll_is_empty (&named_handles)) - unname_handle (file_handle_from_ll (ll_head (&named_handles))); + struct file_handle *handle, *next; + + HMAP_FOR_EACH_SAFE (handle, next, + struct file_handle, name_node, &named_handles) + unname_handle (handle); } /* Free HANDLE and remove it from the global list. */ @@ -104,7 +104,7 @@ free_handle (struct file_handle *handle) { /* Remove handle from global list. */ if (handle->id != NULL) - ll_remove (&handle->ll); + hmap_delete (&named_handles, &handle->name_node); /* Free data. */ free (handle->id); @@ -123,7 +123,7 @@ unname_handle (struct file_handle *handle) assert (handle->id != NULL); free (handle->id); handle->id = NULL; - ll_remove (&handle->ll); + hmap_delete (&named_handles, &handle->name_node); /* Drop the reference held by the named_handles table. */ fh_unref (handle); @@ -172,7 +172,8 @@ fh_from_id (const char *id) { struct file_handle *handle; - ll_for_each (handle, struct file_handle, ll, &named_handles) + HMAP_FOR_EACH_WITH_HASH (handle, struct file_handle, name_node, + hash_case_string (id, 0), &named_handles) if (!strcasecmp (id, handle->id)) { handle->ref_cnt++; @@ -201,7 +202,8 @@ create_handle (const char *id, char *handle_name, enum fh_referent referent) if (id != NULL) { assert (fh_from_id (id) == NULL); - ll_push_tail (&named_handles, &handle->ll); + hmap_insert (&named_handles, &handle->name_node, + hash_case_string (handle->id, 0)); handle->ref_cnt++; } @@ -218,10 +220,10 @@ fh_inline_file (void) return inline_file; } -/* Creates and returns a new file handle with the given ID, which - may be null. If it is non-null, it must be unique among - existing file identifiers. The new handle is associated with - file FILE_NAME and the given PROPERTIES. */ +/* Creates and returns a new file handle with the given ID, which may be null. + If it is non-null, it must be a UTF-8 encoded string that is unique among + existing file identifiers. The new handle is associated with file FILE_NAME + and the given PROPERTIES. */ struct file_handle * fh_create_file (const char *id, const char *file_name, const struct fh_properties *properties) @@ -229,7 +231,7 @@ fh_create_file (const char *id, const char *file_name, char *handle_name; struct file_handle *handle; - handle_name = id != NULL ? xstrdup (id) : xasprintf ("\"%s\"", file_name); + handle_name = id != NULL ? xstrdup (id) : xasprintf ("`%s'", file_name); handle = create_handle (id, handle_name, FH_REF_FILE); handle->file_name = xstrdup (file_name); handle->mode = properties->mode; @@ -256,7 +258,7 @@ const struct fh_properties * fh_default_properties (void) { static const struct fh_properties default_properties - = {FH_MODE_TEXT, 1024, 4, LEGACY_NATIVE}; + = {FH_MODE_TEXT, 1024, 4, C_ENCODING}; return &default_properties; } @@ -329,7 +331,7 @@ const char * fh_get_legacy_encoding (const struct file_handle *handle) { assert (handle->referent & (FH_REF_FILE | FH_REF_INLINE)); - return (handle->referent == FH_REF_FILE ? handle->encoding : LEGACY_NATIVE); + return (handle->referent == FH_REF_FILE ? handle->encoding : C_ENCODING); } /* Returns the scratch file handle associated with HANDLE. @@ -373,6 +375,8 @@ fh_set_default_handle (struct file_handle *new_default_handle) /* Information about a file handle's readers or writers. */ struct fh_lock { + struct hmap_node node; /* hmap_node member. */ + /* Hash key. */ enum fh_referent referent; /* Type of underlying file. */ union @@ -392,14 +396,12 @@ struct fh_lock void *aux; /* Owner's auxiliary data. */ }; -/* Hash table of all active locks. */ -static struct hsh_table *locks; static void make_key (struct fh_lock *, const struct file_handle *, enum fh_access); static void free_key (struct fh_lock *); -static int compare_fh_locks (const void *, const void *, const void *); -static unsigned int hash_fh_lock (const void *, const void *); +static int compare_fh_locks (const struct fh_lock *a, const struct fh_lock *b); +static unsigned int hash_fh_lock (const struct fh_lock *lock); /* Tries to lock handle H for the given kind of ACCESS and TYPE of file. Returns a pointer to a struct fh_lock if successful, @@ -431,31 +433,36 @@ struct fh_lock * fh_lock (struct file_handle *h, enum fh_referent mask UNUSED, const char *type, enum fh_access access, bool exclusive) { - struct fh_lock key, *lock; - void **lockp; + struct fh_lock *key = NULL; + size_t hash ; + struct fh_lock *lock = NULL; + bool found_lock = false; assert ((fh_get_referent (h) & mask) != 0); assert (access == FH_ACC_READ || access == FH_ACC_WRITE); - if (locks == NULL) - locks = hsh_create (0, compare_fh_locks, hash_fh_lock, NULL, NULL); + key = xmalloc (sizeof *key); + + make_key (key, h, access); - make_key (&key, h, access); - lockp = hsh_probe (locks, &key); - if (*lockp == NULL) + key->open_cnt = 1; + key->exclusive = exclusive; + key->type = type; + key->aux = NULL; + + hash = hash_fh_lock (key); + + HMAP_FOR_EACH_WITH_HASH (lock, struct fh_lock, node, hash, &locks) { - lock = *lockp = xmalloc (sizeof *lock); - *lock = key; - lock->open_cnt = 1; - lock->exclusive = exclusive; - lock->type = type; - lock->aux = NULL; + if ( 0 == compare_fh_locks (lock, key)) + { + found_lock = true; + break; + } } - else - { - free_key (&key); - lock = *lockp; + if ( found_lock ) + { if (strcmp (lock->type, type)) { if (access == FH_ACC_READ) @@ -475,9 +482,27 @@ fh_lock (struct file_handle *h, enum fh_referent mask UNUSED, return NULL; } lock->open_cnt++; + + free_key (key); + free (key); + + return lock; } - return lock; + hmap_insert (&locks, &key->node, hash); + found_lock = false; + HMAP_FOR_EACH_WITH_HASH (lock, struct fh_lock, node, hash, &locks) + { + if ( 0 == compare_fh_locks (lock, key)) + { + found_lock = true; + break; + } + } + + assert (found_lock); + + return key; } /* Releases LOCK that was acquired with fh_lock. @@ -499,7 +524,7 @@ fh_unlock (struct fh_lock *lock) assert (lock->open_cnt > 0); if (--lock->open_cnt == 0) { - hsh_delete (locks, lock); + hmap_delete (&locks, &lock->node); free_key (lock); free (lock); return false; @@ -532,10 +557,24 @@ bool fh_is_locked (const struct file_handle *handle, enum fh_access access) { struct fh_lock key; - bool is_locked; + const struct fh_lock *k = NULL; + bool is_locked = false; + size_t hash ; make_key (&key, handle, access); - is_locked = hsh_find (locks, &key) != NULL; + + hash = hash_fh_lock (&key); + + + HMAP_FOR_EACH_WITH_HASH (k, struct fh_lock, node, hash, &locks) + { + if ( 0 == compare_fh_locks (k, &key)) + { + is_locked = true; + break; + } + } + free_key (&key); return is_locked; @@ -569,11 +608,8 @@ free_key (struct fh_lock *lock) /* Compares the key fields in struct fh_lock objects A and B and returns a strcmp()-type result. */ static int -compare_fh_locks (const void *a_, const void *b_, const void *aux UNUSED) +compare_fh_locks (const struct fh_lock *a, const struct fh_lock *b) { - const struct fh_lock *a = a_; - const struct fh_lock *b = b_; - if (a->referent != b->referent) return a->referent < b->referent ? -1 : 1; else if (a->access != b->access) @@ -589,9 +625,8 @@ compare_fh_locks (const void *a_, const void *b_, const void *aux UNUSED) /* Returns a hash value for LOCK. */ static unsigned int -hash_fh_lock (const void *lock_, const void *aux UNUSED) +hash_fh_lock (const struct fh_lock *lock) { - const struct fh_lock *lock = lock_; unsigned int basis; if (lock->referent == FH_REF_FILE) basis = fn_hash_identity (lock->u.file);