Merge in data tree sharing, minus locking support, plus a bugfix or two
authorKen Raeburn <raeburn@mit.edu>
Fri, 20 Dec 2002 22:38:04 +0000 (22:38 +0000)
committerKen Raeburn <raeburn@mit.edu>
Fri, 20 Dec 2002 22:38:04 +0000 (22:38 +0000)
* prof_int.h (SHARE_TREE_DATA): Define.
(struct _prf_file_t) [SHARE_TREE_DATA]: Make data field a pointer rather than
an array.
(struct global_shared_profile_data): New type, for profile library global
data.
(krb5int_profile_shared_data): Declare new variable.
(g_shared_trees): New macro, refers to a field in the global data.
(PROFILE_FILE_SHARED): New flag macro.
* prof_file.c (krb5int_profile_shared_data): Initialize here.
(profile_open_file) [SHARE_TREE_DATA]: Scan g_shared_trees for an entry with
the same filename.  If found, increment its reference count, update it, and
return it; otherwise, allocate a new one, and add it to the list after filling
it in.
(profile_dereference_data): New function.  Decrement reference count if
SHARE_TREE_DATA, and free the data if appropriate.
(profile_free_file): Call profile_dereference_data.
(profile_free_file_data) [SHARE_TREE_DATA]: If the SHARED flag is set, remove
it from the g_shared_trees list before freeing.  Free up the allocated space.
* prof_set.c (rw_setup) [SHARE_TREE_DATA]: If the object's data is shared, copy
it into a new data structure not in the global shared list, and dereference the
old one.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15060 dc483132-0cff-0310-8789-dd5450dbe970

src/util/profile/ChangeLog
src/util/profile/prof_file.c
src/util/profile/prof_int.h
src/util/profile/prof_set.c

index cf7c5360f2df33d63b0eea0ca80a35af6af79a0d..bcf9c2f106f80c8393fd83d1f5dd52e2c4e5be9c 100644 (file)
@@ -1,3 +1,28 @@
+2002-12-20  Ken Raeburn  <raeburn@mit.edu>
+
+       * prof_int.h (SHARE_TREE_DATA): Define.
+       (struct _prf_file_t) [SHARE_TREE_DATA]: Make data field a pointer
+       rather than an array.
+       (struct global_shared_profile_data): New type, for profile library
+       global data.
+       (krb5int_profile_shared_data): Declare new variable.
+       (g_shared_trees): New macro, refers to a field in the global data.
+       (PROFILE_FILE_SHARED): New flag macro.
+       * prof_file.c (krb5int_profile_shared_data): Initialize here.
+       (profile_open_file) [SHARE_TREE_DATA]: Scan g_shared_trees for an
+       entry with the same filename.  If found, increment its reference
+       count, update it, and return it; otherwise, allocate a new one,
+       and add it to the list after filling it in.
+       (profile_dereference_data): New function.  Decrement reference
+       count if SHARE_TREE_DATA, and free the data if appropriate.
+       (profile_free_file): Call profile_dereference_data.
+       (profile_free_file_data) [SHARE_TREE_DATA]: If the SHARED flag is
+       set, remove it from the g_shared_trees list before freeing.  Free
+       up the allocated space.
+       * prof_set.c (rw_setup) [SHARE_TREE_DATA]: If the object's data is
+       shared, copy it into a new data structure not in the global shared
+       list, and dereference the old one.
+
 2002-12-06  Ken Raeburn  <raeburn@mit.edu>
 
        * prof_int.h: Include Mac OS X versions of header files if
index 4ffe7e1384df538dd7ec5e40663f79dd154c8775..e9da626e3d13855fa2db5e1a1840c05ce85201c4 100644 (file)
 #define stat _stat
 #endif
 
+#ifdef SHARE_TREE_DATA
+struct global_shared_profile_data krb5int_profile_shared_data = {
+    0
+};
+#endif
+
 #ifndef PROFILE_USES_PATHS
 #include <FSp_fopen.h>
 
 static OSErr GetMacOSTempFilespec (
        const   FSSpec* inFilespec,
                        FSSpec* outFilespec);
-
 #endif
 
 static int rw_access(filespec)
@@ -80,7 +85,36 @@ errcode_t profile_open_file(filespec, ret_prof)
        if (!prf)
                return ENOMEM;
        memset(prf, 0, sizeof(struct _prf_file_t));
+       prf->magic = PROF_MAGIC_FILE;
+
+#ifdef SHARE_TREE_DATA
+       for (data = g_shared_trees; data; data = data->next) {
+           if (!strcmp(data->filespec, filespec)
+               /* Check that current uid has read access.  */
+               && access(data->filespec, R_OK) == 0)
+               break;
+       }
+       if (data) {
+           retval = profile_update_file_data(data);
+           data->refcount++;
+           prf->data = data;
+           *ret_prof = prf;
+           return retval;
+       }
+       data = malloc(sizeof(struct _prf_data_t));
+       if (data == NULL) {
+           free(prf);
+           return ENOMEM;
+       }
+       memset(data, 0, sizeof(*data));
+       prf->data = data;
+#else
        data = prf->data;
+#endif
+
+       data->magic = PROF_MAGIC_FILE_DATA;
+       data->refcount = 1;
+       data->comment = 0;
 
        len = strlen(filespec)+1;
        if (filespec[0] == '~' && filespec[1] == '/') {
@@ -98,9 +132,6 @@ errcode_t profile_open_file(filespec, ret_prof)
                strcat(data->filespec, filespec+1);
        } else
                strcpy(data->filespec, filespec);
-       prf->magic = PROF_MAGIC_FILE;
-       data->magic = PROF_MAGIC_FILE_DATA;
-       data->refcount = 1;
 
        retval = profile_update_file(prf);
        if (retval) {
@@ -108,6 +139,12 @@ errcode_t profile_open_file(filespec, ret_prof)
                return retval;
        }
 
+#ifdef SHARE_TREE_DATA
+       data->next = g_shared_trees;
+       data->flags |= PROFILE_FILE_SHARED;
+       g_shared_trees = data;
+#endif
+
        *ret_prof = prf;
        return 0;
 }
@@ -276,16 +313,47 @@ errout:
 }
 
 
+void profile_dereference_data(prf_data_t data)
+{
+#ifdef SHARE_TREE_DATA
+    data->refcount--;
+    if (data->refcount == 0)
+       profile_free_file_data(data);
+#else
+    profile_free_file_data(data);
+#endif
+}
+
 void profile_free_file(prf)
        prf_file_t prf;
 {
-       profile_free_file_data(prf->data);
-       free(prf);
+    profile_dereference_data(prf->data);
+    free(prf);
 }
 
 void profile_free_file_data(data)
        prf_data_t data;
 {
+#ifdef SHARE_TREE_DATA
+    if (data->flags & PROFILE_FILE_SHARED) {
+       /* Remove from linked list.  */
+       if (g_shared_trees == data)
+           g_shared_trees = data->next;
+       else {
+           prf_data_t prev, next;
+           prev = g_shared_trees;
+           next = prev->next;
+           while (next) {
+               if (next == data) {
+                   prev->next = next->next;
+                   break;
+               }
+               prev = next;
+               next = next->next;
+           }
+       }
+    }
+#endif
 #ifdef PROFILE_USES_PATHS
        if (data->filespec)
                free(data->filespec);
@@ -295,6 +363,9 @@ void profile_free_file_data(data)
        if (data->comment)
                free(data->comment);
        data->magic = 0;
+#ifdef SHARE_TREE_DATA
+       free(data);
+#endif
 }
 
 errcode_t profile_close_file(prf)
@@ -308,4 +379,3 @@ errcode_t profile_close_file(prf)
        profile_free_file(prf);
        return 0;
 }
-
index 00fd2847b1b3295c5ea007491771fb22ef8a4b43..ead23dc3a26da83bae10d2132aa848d516987afc 100644 (file)
@@ -30,6 +30,8 @@
 
 typedef long prf_magic_t;
 
+#define SHARE_TREE_DATA
+
 /*
  * This is the structure which stores the profile information for a
  * particular configuration file.
@@ -50,17 +52,31 @@ typedef struct _prf_data_t *prf_data_t;
 
 struct _prf_file_t {
        prf_magic_t     magic;
+#ifdef SHARE_TREE_DATA
+       struct _prf_data_t      *data;
+#else
        struct _prf_data_t      data[1];
+#endif
        struct _prf_file_t *next;
 };
 
 typedef struct _prf_file_t *prf_file_t;
 
+#ifdef SHARE_TREE_DATA
+struct global_shared_profile_data {
+       /* This is the head of the global list of shared trees */
+       prf_data_t trees;
+};
+extern struct global_shared_profile_data krb5int_profile_shared_data;
+#define g_shared_trees         (krb5int_profile_shared_data.trees)
+#endif /* SHARE_TREE_DATA */
+
 /*
  * The profile flags
  */
 #define PROFILE_FILE_RW                0x0001
 #define PROFILE_FILE_DIRTY     0x0002
+#define PROFILE_FILE_SHARED    0x0004
 
 /*
  * This structure defines the high-level, user visible profile_t
index 4c6ccb29d5e48159440a2638965882c1ac9fde75..5abf5ec9afabc700de099cf09138d16268f299ca 100644 (file)
@@ -24,7 +24,7 @@ static errcode_t rw_setup(profile)
        profile_t       profile;
 {
        prf_file_t      file;
-       errcode_t       retval;
+       errcode_t       retval = 0;
 
        if (!profile)
                return PROF_NO_PROFILE;
@@ -39,7 +39,39 @@ static errcode_t rw_setup(profile)
        /* Don't update the file if we've already made modifications */
        if (file->data->flags & PROFILE_FILE_DIRTY)
                return 0;
-                       
+
+#ifdef SHARE_TREE_DATA
+       if ((file->data->flags & PROFILE_FILE_SHARED) != 0) {
+           prf_data_t new_data;
+           new_data = malloc(sizeof(struct _prf_data_t));
+           if (new_data == NULL) {
+               retval = ENOMEM;
+           } else {
+               *new_data = *file->data;
+               /* We can blow away the information because update
+                  will be called further down */
+               new_data->comment = NULL;
+               new_data->root = NULL;
+               new_data->flags &= ~PROFILE_FILE_SHARED;
+               new_data->timestamp = 0;
+               /* copy the file spec */
+               new_data->filespec = malloc(strlen(file->data->filespec) + 1);
+               if (new_data->filespec == NULL) {
+                   retval = ENOMEM;
+               } else {
+                   strcpy (new_data->filespec, file->data->filespec);
+               }
+           }
+
+           if (retval != 0) {
+               free(new_data);
+               return retval;
+           }
+           profile_dereference_data(file->data);
+           file->data = new_data;
+       }
+#endif /* SHARE_TREE_DATA */
+
        retval = profile_update_file(file);
        
        return retval;