[launchd-changes] [23806] branches/PR-5063531/launchd/src/launchctl.c
source_changes at macosforge.org
source_changes at macosforge.org
Fri Feb 13 15:55:31 PST 2009
Revision: 23806
http://trac.macosforge.org/projects/launchd/changeset/23806
Author: dsorresso at apple.com
Date: 2009-02-13 15:55:29 -0800 (Fri, 13 Feb 2009)
Log Message:
-----------
Changed implementation to be more like kextcache, where you have to touch the parent directory to update the cache.
Modified Paths:
--------------
branches/PR-5063531/launchd/src/launchctl.c
Modified: branches/PR-5063531/launchd/src/launchctl.c
===================================================================
--- branches/PR-5063531/launchd/src/launchctl.c 2009-02-13 18:58:48 UTC (rev 23805)
+++ branches/PR-5063531/launchd/src/launchctl.c 2009-02-13 23:55:29 UTC (rev 23806)
@@ -82,6 +82,8 @@
#include <spawn.h>
#include <sys/syslimits.h>
#include <mach/mach_time.h>
+#include <stdint.h>
+#include <limits.h>
#if HAVE_LIBAUDITD
#include <bsm/auditd_lib.h>
@@ -111,7 +113,9 @@
launch_data_t pass1;
launch_data_t pass2;
char *session_type;
- bool editondisk:1, load:1, forceload:1;
+ bool editondisk:1, load:1, forceload:1, usecache:1;
+ launch_data_t cached_plist;
+ CFMutableDictionaryRef cache_line;
};
static void myCFDictionaryApplyFunction(const void *key, const void *value, void *context);
@@ -699,57 +703,76 @@
launch_data_t
read_plist_file(const char *file, bool editondisk, bool load)
{
+ bool add_to_cache = false, file_changed = false;
CFPropertyListRef plist = NULL;
- bool add_to_cache = false, file_changed = false;
+ CFMutableDictionaryRef cache_line = NULL;
+ CFStringRef key = NULL;
- CFStringRef key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), file);
-
- struct stat sb;
- if( assumes(stat(file, &sb) == 0) ) {
- file_changed = sb.st_mtimespec.tv_sec > g_cache_creation_time;
- }
-
- if( g_plist_cache && !file_changed ) {
- plist = CFDictionaryGetValue(g_plist_cache, key);
+ if( g_plist_cache ) {
+ key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), file);
- if( plist && CFGetTypeID(plist) == CFDictionaryGetTypeID() ) {
- CFRetain(plist);
+ CFStringRef cache_line_key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), dirname((char *)file));
+ cache_line = (CFMutableDictionaryRef)CFDictionaryGetValue(g_plist_cache, cache_line_key);
+ if( !cache_line ) {
+ cache_line = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ CFDictionarySetValue(g_plist_cache, cache_line_key, cache_line);
+ CFRelease(cache_line);
} else {
+ struct stat sb;
+ if( assumes(stat(file, &sb) == 0) ) {
+ file_changed = sb.st_mtimespec.tv_sec > g_cache_creation_time;
+ }
+ }
+
+ CFRelease(cache_line_key);
+
+ if( !file_changed ) {
+ plist = CFDictionaryGetValue(cache_line, key);
+
+ if( plist && CFGetTypeID(plist) == CFDictionaryGetTypeID() ) {
+ fprintf(stdout, "Using cache for %s.\n", file);
+ CFRetain(plist);
+ } else {
+ fprintf(stdout, "Invalidating cache for %s (file was not in cache).\n", file);
+ CFRetain(key);
+ add_to_cache = true;
+ plist = NULL;
+ }
+ } else {
+ fprintf(stdout, "Invalidating cache for %s (file was updated).\n", file);
+ CFRetain(key);
add_to_cache = true;
}
- } else if( g_plist_cache ) {
- add_to_cache = true;
+ CFRelease(key);
}
-
- if( !plist ) {
- plist = CreateMyPropertyListFromFile(file);
+
+ if( !plist && !(plist = CreateMyPropertyListFromFile(file)) ) {
+ fprintf(stderr, "%s: no plist was returned for: %s\n", getprogname(), file);
}
-
- launch_data_t r = NULL;
-
- if (NULL == plist) {
- fprintf(stderr, "%s: no plist was returned for: %s\n", getprogname(), file);
- return NULL;
- } else if( add_to_cache ) {
- CFDictionarySetValue(g_plist_cache, key, plist);
+
+ if( plist && add_to_cache ) {
+ fprintf(stdout, "\tAdding %s to cache.\n", file);
+ CFDictionarySetValue(cache_line, key, plist);
g_plist_cache_changes++;
+ CFRelease(key);
}
- CFRelease(key);
-
- if (editondisk) {
- if (load) {
- CFDictionaryRemoveValue((CFMutableDictionaryRef)plist, CFSTR(LAUNCH_JOBKEY_DISABLED));
- } else {
- CFDictionarySetValue((CFMutableDictionaryRef)plist, CFSTR(LAUNCH_JOBKEY_DISABLED), kCFBooleanTrue);
+ launch_data_t r = NULL;
+ if( plist ) {
+ if (editondisk) {
+ if (load) {
+ CFDictionaryRemoveValue((CFMutableDictionaryRef)plist, CFSTR(LAUNCH_JOBKEY_DISABLED));
+ } else {
+ CFDictionarySetValue((CFMutableDictionaryRef)plist, CFSTR(LAUNCH_JOBKEY_DISABLED), kCFBooleanTrue);
+ }
+ WriteMyPropertyListToFile(plist, file, false);
}
- WriteMyPropertyListToFile(plist, file, false);
+
+ r = CF2launch_data(plist);
+
+ CFRelease(plist);
}
- r = CF2launch_data(plist);
-
- CFRelease(plist);
-
return r;
}
@@ -804,8 +827,9 @@
gethostname(ourhostname, sizeof(ourhostname));
- if (NULL == (thejob = read_plist_file(what, lus->editondisk, lus->load))) {
- fprintf(stderr, "%s: no plist was returned for: %s\n", getprogname(), what);
+ thejob = lus->cached_plist ? lus->cached_plist : read_plist_file(what, lus->editondisk, lus->load);
+ if( !thejob ) {
+ fprintf(stderr, "%s: no plist was returned for: %s%s\n", getprogname(), lus->cached_plist ? "cached " : "", what);
return;
}
@@ -1002,6 +1026,37 @@
return true;
}
+static bool
+CFStringCopyUTF8BytesIntoBuffer(CFStringRef string, char *buff, size_t size)
+{
+ bool result = false;
+
+ CFIndex length = 0;
+ length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(string) + 1, kCFStringEncodingUTF8);
+
+ if( size < LONG_MAX && length < (CFIndex)size ) {
+ result = CFStringGetCString(string, buff, size, kCFStringEncodingUTF8);
+ }
+
+ return result;
+}
+
+static void
+slurp_from_cache(const void *key, const void *val, void *ctx)
+{
+ struct load_unload_state *lus = (struct load_unload_state *)ctx;
+ if( CFGetTypeID((CFTypeRef)key) == CFStringGetTypeID() && CFGetTypeID((CFTypeRef)val) == CFDictionaryGetTypeID() ) {
+ launch_data_t j = CF2launch_data(val);
+
+ char path[PATH_MAX];
+ CFStringCopyUTF8BytesIntoBuffer(key, path, sizeof(path));
+
+ lus->cached_plist = j;
+ readfile(path, lus);
+ lus->cached_plist = NULL;
+ }
+}
+
void
readpath(const char *what, struct load_unload_state *lus)
{
@@ -1021,24 +1076,39 @@
if (S_ISREG(sb.st_mode)) {
readfile(what, lus);
} else if (S_ISDIR(sb.st_mode)) {
- if ((d = opendir(what)) == NULL) {
- fprintf(stderr, "%s: opendir() failed to open the directory\n", getprogname());
- return;
+ CFMutableDictionaryRef cache_line = NULL;
+ if( g_plist_cache ) {
+ CFStringRef cfwhat = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), what);
+ cache_line = (CFMutableDictionaryRef)CFDictionaryGetValue(g_plist_cache, cfwhat);
+ CFRelease(cfwhat);
+
+ if( cache_line ) {
+ cache_line = CFGetTypeID(cache_line) == CFDictionaryGetTypeID() ? cache_line : NULL;
+ }
}
-
- while ((de = readdir(d))) {
- if ((de->d_name[0] == '.')) {
- continue;
+
+ if( cache_line && sb.st_mtimespec.tv_sec <= g_cache_creation_time ) {
+ CFDictionaryApplyFunction(cache_line, slurp_from_cache, lus);
+ } else {
+ if ((d = opendir(what)) == NULL) {
+ fprintf(stderr, "%s: opendir() failed to open the directory\n", getprogname());
+ return;
}
- snprintf(buf, sizeof(buf), "%s/%s", what, de->d_name);
-
- if (!path_goodness_check(buf, lus->forceload)) {
- continue;
+
+ while ((de = readdir(d))) {
+ if ((de->d_name[0] == '.')) {
+ continue;
+ }
+ snprintf(buf, sizeof(buf), "%s/%s", what, de->d_name);
+
+ if (!path_goodness_check(buf, lus->forceload)) {
+ continue;
+ }
+
+ readfile(buf, lus);
}
-
- readfile(buf, lus);
+ closedir(d);
}
- closedir(d);
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/launchd-changes/attachments/20090213/70c5a8e0/attachment-0001.html>
More information about the launchd-changes
mailing list