[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