From 7c28091d5daeb6431e6e76aeeca9ba1d33665d66 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Fri, 20 Dec 2002 22:38:04 +0000 Subject: [PATCH] Merge in data tree sharing, minus locking support, plus a bugfix or two * 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 | 25 +++++++++++ src/util/profile/prof_file.c | 84 +++++++++++++++++++++++++++++++++--- src/util/profile/prof_int.h | 16 +++++++ src/util/profile/prof_set.c | 36 +++++++++++++++- 4 files changed, 152 insertions(+), 9 deletions(-) diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog index cf7c5360f..bcf9c2f10 100644 --- a/src/util/profile/ChangeLog +++ b/src/util/profile/ChangeLog @@ -1,3 +1,28 @@ +2002-12-20 Ken Raeburn + + * 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 * prof_int.h: Include Mac OS X versions of header files if diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c index 4ffe7e138..e9da626e3 100644 --- a/src/util/profile/prof_file.c +++ b/src/util/profile/prof_file.c @@ -28,13 +28,18 @@ #define stat _stat #endif +#ifdef SHARE_TREE_DATA +struct global_shared_profile_data krb5int_profile_shared_data = { + 0 +}; +#endif + #ifndef PROFILE_USES_PATHS #include 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; } - diff --git a/src/util/profile/prof_int.h b/src/util/profile/prof_int.h index 00fd2847b..ead23dc3a 100644 --- a/src/util/profile/prof_int.h +++ b/src/util/profile/prof_int.h @@ -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 diff --git a/src/util/profile/prof_set.c b/src/util/profile/prof_set.c index 4c6ccb29d..5abf5ec9a 100644 --- a/src/util/profile/prof_set.c +++ b/src/util/profile/prof_set.c @@ -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; -- 2.26.2