adium 3128:e909da27961b: AILoggerPreferences doesn't exist anymo...

commits at adium.im commits at adium.im
Thu Feb 18 06:14:38 UTC 2010


details:	http://hg.adium.im/adium/rev/e909da27961b
revision:	3128:e909da27961b
author:		Stephen Holt <sholt at adium.im>
date:		Wed Feb 17 21:21:21 2010 -0500

AILoggerPreferences doesn't exist anymore.  kill it.
Subject: adium 3129:e38f8690c55e: These methods were only ever called from within the plugin object itself.  Don't expose them to the world.

details:	http://hg.adium.im/adium/rev/e38f8690c55e
revision:	3129:e38f8690c55e
author:		Stephen Holt <sholt at adium.im>
date:		Wed Feb 17 21:39:43 2010 -0500

These methods were only ever called from within the plugin object itself.  Don't expose them to the world.
Subject: adium 3130:fd940fda651f: Adjust pauseIndexing/resumeIndexing to not care about pause counts.

details:	http://hg.adium.im/adium/rev/fd940fda651f
revision:	3130:fd940fda651f
author:		Stephen Holt <sholt at adium.im>
date:		Wed Feb 17 23:21:57 2010 -0500

Adjust pauseIndexing/resumeIndexing to not care about pause counts.
Subject: adium 3131:299c1fd8e248: The logClosingLock was only ever used when the logWritingLock was unlocked, essentially making it redundant.

details:	http://hg.adium.im/adium/rev/299c1fd8e248
revision:	3131:299c1fd8e248
author:		Stephen Holt <sholt at adium.im>
date:		Wed Feb 17 23:21:59 2010 -0500

The logClosingLock was only ever used when the logWritingLock was unlocked, essentially making it redundant.

Besides, a log index can't be written to when it's closing, so semantically it's still correct.
Subject: adium 3132:8eb163d36221: Streamline our entry points to operations that write to the log index, performing them in a serial operation queue.

details:	http://hg.adium.im/adium/rev/8eb163d36221
revision:	3132:8eb163d36221
author:		Stephen Holt <sholt at adium.im>
date:		Thu Feb 18 01:11:10 2010 -0500

Streamline our entry points to operations that write to the log index, performing them in a serial operation queue.

Hopefully this eliminates the need for some explicit locking, and resolves a deadlock experienced by rob-to86.

diffs (534 lines):

diff -r 63afe99d997e -r 8eb163d36221 Source/AILoggerPlugin.h
--- a/Source/AILoggerPlugin.h	Fri Feb 12 13:23:42 2010 -0500
+++ b/Source/AILoggerPlugin.h	Thu Feb 18 01:11:10 2010 -0500
@@ -15,61 +15,53 @@
  */
 
 
-#define PATH_LOGS                       @"/Logs"
-#define LOGGING_DEFAULT_PREFS           @"LoggingDefaults"
+#define PATH_LOGS                     @"/Logs"
+#define LOGGING_DEFAULT_PREFS         @"LoggingDefaults"
 
-#define PREF_GROUP_LOGGING              @"Logging"
-#define KEY_LOGGER_ENABLE               @"Enable Logging"
+#define PREF_GROUP_LOGGING            @"Logging"
+#define KEY_LOGGER_ENABLE             @"Enable Logging"
 
-#define PREF_KEYPATH_LOGGER_ENABLE		PREF_GROUP_LOGGING @"." KEY_LOGGER_ENABLE
+#define PREF_KEYPATH_LOGGER_ENABLE    PREF_GROUP_LOGGING @"." KEY_LOGGER_ENABLE
 
-#define XML_LOGGING_NAMESPACE		@"http://purl.org/net/ulf/ns/0.4-02"
+#define XML_LOGGING_NAMESPACE         @"http://purl.org/net/ulf/ns/0.4-02"
 
- at class AIAccount, AIHTMLDecoder, AIChat, AILoggerPreferences;
+ at class AIAccount, AIHTMLDecoder, AIChat;
 
- at interface AILoggerPlugin : AIPlugin {
-    AILoggerPreferences                 *preferences;
-    
-    //Current logging settings
-    BOOL				observingContent;
-    BOOL				logHTML;
-
-	NSMutableDictionary					*activeAppenders;
-	NSMutableDictionary					*appenderCloseTimers;
+ at interface AILoggerPlugin : AIPlugin {	
+	//Current logging settings
+	BOOL                 observingContent;
+	BOOL                 logHTML;
 	
-	AIHTMLDecoder						*xhtmlDecoder;
-	NSDictionary						*statusTranslation;
+	NSMutableDictionary *activeAppenders;
+	NSMutableDictionary *appenderCloseTimers;
 	
-    //Log viewer menu items
-    NSMenuItem                          *logViewerMenuItem;
-    NSMenuItem                          *viewContactLogsMenuItem;
-    NSMenuItem                          *viewContactLogsContextMenuItem;
-	NSMenuItem							*viewGroupLogsContextMenuItem;
-
-    //Log content search index
-	BOOL				logIndexingEnabled; //Does this system use log indexing?
-    SKIndexRef			index_Content;	
-
-    //Dirty all information (First build of the dirty cache)
-    BOOL				stopIndexingThreads;    //Set to YES to abort a dirty all or clean
-    BOOL				suspendDirtySetSaving;  //YES to prevent saving of the dirty index	
-	BOOL				isFlushingIndex;
-    NSLock				*indexingThreadLock;	//Locked by the plugin when a dirty all or clean thread is running
-
-	//Locked by the plugin while the index is being modified
-	NSConditionLock		*logWritingLock;
-	//Locked by the plugin while the index is being closed
-    NSConditionLock		*logClosingLock;
+	AIHTMLDecoder       *xhtmlDecoder;
+	NSDictionary        *statusTranslation;
 	
-    //Set of dirty logs / Logs that need re-indexing.  (Locked access)
-    NSMutableSet		*dirtyLogSet;
-    NSLock				*dirtyLogLock;
-    
-    //Indexing progress
-    NSInteger					logsToIndex;
-    NSInteger					logsIndexed;
-	NSInteger					logIndexingPauses;
-    
+	//Log viewer menu items
+	NSMenuItem          *logViewerMenuItem;
+	NSMenuItem          *viewContactLogsMenuItem;
+	NSMenuItem          *viewContactLogsContextMenuItem;
+	NSMenuItem          *viewGroupLogsContextMenuItem;
+	
+	//Log content search index
+	BOOL                 logIndexingEnabled; //Does this system use log indexing?
+	SKIndexRef           index_Content;	
+	
+	//Dirty all information (First build of the dirty cache)
+	BOOL                 indexingAllowed;    //Set to YES to abort a dirty all or clean
+	BOOL                 suspendDirtySetSaving;  //YES to prevent saving of the dirty index	
+	BOOL                 isFlushingIndex;
+	
+	//Set of dirty logs / Logs that need re-indexing.  (Locked access)
+	NSMutableSet        *dirtyLogSet;
+	NSLock              *dirtyLogLock;
+	
+	NSLock              *createIndexLock;
+	
+	//Indexing progress
+	NSInteger            logsToIndex;
+	NSInteger            logsIndexed;	
 }
 
 //Paths
@@ -79,23 +71,13 @@
 //Message History
 + (NSArray *)sortedArrayOfLogFilesForChat:(AIChat *)chat;
 
-//Log viewer
-- (void)showLogViewerAndReindex:(id)sender;
-- (void)showLogViewerToSelectedContact:(id)sender;
-- (void)showLogViewerToSelectedContextContact:(id)sender;
-
 //Log indexing
-- (void)initLogIndexing;
 - (void)prepareLogContentSearching;
 - (void)cleanUpLogContentSearching;
 - (SKIndexRef)logContentIndex;
-- (void)markLogDirtyAtPath:(NSString *)path forChat:(AIChat *)chat;
 - (void)markLogDirtyAtPath:(NSString *)path;
 - (BOOL)getIndexingProgress:(NSUInteger *)complete outOf:(NSUInteger *)total;
 
-- (void)stopIndexingThreads;
-- (void)dirtyAllLogs;
-- (void)cleanDirtyLogs;
 - (void)pauseIndexing;
 - (void)resumeIndexing;
 
diff -r 63afe99d997e -r 8eb163d36221 Source/AILoggerPlugin.m
--- a/Source/AILoggerPlugin.m	Fri Feb 12 13:23:42 2010 -0500
+++ b/Source/AILoggerPlugin.m	Thu Feb 18 01:11:10 2010 -0500
@@ -113,6 +113,18 @@
 - (void)showLogViewer:(id)sender;
 - (void)showLogViewerForGroupChat:(id)sender;
 - (void)_cleanDirtyLogsThread:(SKIndexRef)searchIndex;
+
+//Log viewer
+- (void)showLogViewerAndReindex:(id)sender;
+- (void)showLogViewerToSelectedContact:(id)sender;
+- (void)showLogViewerToSelectedContextContact:(id)sender;
+
+//Log indexing
+- (void)initLogIndexing;
+- (void)markLogDirtyAtPath:(NSString *)path forChat:(AIChat *)chat;
+
+- (void)dirtyAllLogs;
+- (void)cleanDirtyLogs;
 @end
 
 static NSString     *logBasePath = nil;     //The base directory of all logs
@@ -187,14 +199,13 @@
 
 	dirtyLogSet = [[NSMutableSet alloc] init];
 	index_Content = nil;
-	stopIndexingThreads = NO;
-	suspendDirtySetSaving = NO;		
-	indexingThreadLock = [[NSLock alloc] init];
-	[indexingThreadLock setName:@"LogIndexingThreadLock"];
+	indexingAllowed = YES;
+	suspendDirtySetSaving = NO;
 	dirtyLogLock = [[NSLock alloc] init];
 	[dirtyLogLock setName:@"DirtyLogLock"];
-	logWritingLock = [[NSConditionLock alloc] initWithCondition:AIIndexFileAvailable];
-	logClosingLock = [[NSConditionLock alloc] initWithCondition:AIIndexFileAvailable];
+	
+	createIndexLock = [[NSLock alloc] init];
+	[createIndexLock setName:@"createIndexLock"];
 
 	//Init index searching
 	[self initLogIndexing];
@@ -235,6 +246,7 @@
 		if(!OSAtomicCompareAndSwapPtrBarrier(nil, newQueue, (void *)&loggerQueue))
 			[newQueue release];
 		
+		[loggerQueue setMaxConcurrentOperationCount:1];
 		if([NSApp isOnSnowLeopardOrBetter])
 			[loggerQueue performSelector:@selector(setName:) withObject:@"AILoggerPluginOperationQueue"];
 	}
@@ -1092,21 +1104,34 @@
 	}
 
 	//Load the contentIndex immediately; this will clear dirtyLogSet if necessary
-	[self logContentIndex];
+	[[[self class] operationQueue] addOperation:
+	 [[NSInvocationOperation alloc] initWithTarget:self
+																				selector:@selector(logContentIndex)
+																					object:nil]];
+	[[[self class] operationQueue] waitUntilAllOperationsAreFinished];
 
-	stopIndexingThreads = NO;
+	indexingAllowed = YES;
+	NSInvocationOperation *op;
 	if (reindex) {
-		[self dirtyAllLogs];
+		op = [[NSInvocationOperation alloc] initWithTarget:self
+																							selector:@selector(dirtyAllLogs)
+																								object:nil];
 	} else {
-		[self cleanDirtyLogs];
+		op = [[NSInvocationOperation alloc] initWithTarget:self
+																							selector:@selector(cleanDirtyLogs)
+																								object:nil];
 	}
+	[[[self class] operationQueue] addOperation:op];
 }
 
 //Close down and clean up the log index  (Call when finished using the logSearchIndex)
 - (void)cleanUpLogContentSearching
 {
-	[self stopIndexingThreads];
-	[self closeLogIndex];
+	indexingAllowed = NO;
+	[[[self class] operationQueue] addOperation:
+	 [[NSInvocationOperation alloc] initWithTarget:self
+																				selector:@selector(closeLogIndex)
+																					object:nil]];
 }
 
 //Returns the Search Kit index for log content searching
@@ -1114,20 +1139,19 @@
 {
 	SKIndexRef	returnIndex;
 
-	AILogWithSignature(@"Got %@", logClosingLock);
 	/* We shouldn't have to lock here except in createLogIndex.  However, a 'window period' exists after an SKIndex has been closed via SKIndexClose()
 	 * in which an attempt to load the index from disk returns NULL (presumably because it's still being written-to asynchronously).  We therefore lock
 	 * around the full access to make the process reliable.  The documentation says that SKIndex is thread-safe, but that seems to assume that you keep
 	 * a single instance of SKIndex open at all times... which is a major memory hit for a large index of a significant number of logs. We only keep the index
 	 * open as long as the transcript viewer window is open.
 	 */
-	[logClosingLock lockWhenCondition:AIIndexFileAvailable];
 	[self cancelClosingLogIndex];
+	[createIndexLock lock];
 	if (!index_Content) {
 		index_Content = [self createLogIndex];
 	}
 	returnIndex = (SKIndexRef)[[(NSObject *)index_Content retain] autorelease];
-	[logClosingLock unlockWithCondition:AIIndexFileAvailable];
+	[createIndexLock unlock];
 
 	return returnIndex;
 }
@@ -1238,18 +1262,11 @@
 
 	} else {
 		//No writing or opening/closing while we call SKIndexClose()
-		[logWritingLock lockWhenCondition:AIIndexFileAvailable];
-		[logClosingLock lockWhenCondition:AIIndexFileAvailable];
-		
 		AILogWithSignature(@"finishClosingIndex: %p",index_Content);
-		
 		if (index_Content) {
 			SKIndexClose(index_Content);
 			index_Content = nil;
 		}
-		
-		[logWritingLock unlockWithCondition:AIIndexFileAvailable];
-		[logClosingLock unlockWithCondition:AIIndexFileAvailable];
 	}
 }
 	
@@ -1262,7 +1279,6 @@
 - (void)flushIndex:(SKIndexRef)inIndex
 {
     NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
-	[logWritingLock lockWhenCondition:AIIndexFileIsClosing];
 	if (inIndex) {
 		AILogWithSignature(@"**** Flushing index %p",inIndex);
 		CFRetain(inIndex);
@@ -1270,7 +1286,6 @@
 		CFRelease(inIndex);
 		AILogWithSignature(@"**** Finished flushing index %p, and released it",inIndex);
 	}
-	[logWritingLock unlockWithCondition:AIIndexFileAvailable];
 
 	[pool release];
 }
@@ -1286,28 +1301,13 @@
 					   withObject:nil
 					   afterDelay:30];
 		}
-		
-	} else {
-		[logWritingLock lockWhenCondition:AIIndexFileAvailable];
-		
+	} else {		
 		if (index_Content) {
 			AILogWithSignature(@"Triggerring the flushIndex thread and queuing index closing");
-			
-			[[AILoggerPlugin operationQueue] addOperation:
-			 [[NSInvocationOperation alloc] initWithTarget:self
-												  selector:@selector(flushIndex:)
-													object:(id)index_Content]];
-			
+			[self flushIndex:index_Content];
 			[self cancelClosingLogIndex];
-			[self performSelector:@selector(finishClosingIndex)
-					   withObject:nil
-					   afterDelay:30];
+			[self finishClosingIndex];
 		}
-		
-		/* Note that we're waiting on the index file to close.  An attempt to open the index file before
-		 * it closes will return nil and make us think that we have a corrupt index file.
-		 */
-		[logWritingLock unlockWithCondition:AIIndexFileIsClosing];
 	}
 }
 
@@ -1359,11 +1359,11 @@
 //Save the dirty lod set
 - (void)_saveDirtyLogSet
 {
+	[dirtyLogLock lock];
     if ([dirtyLogSet count] > 0 && !suspendDirtySetSaving) {
-		[dirtyLogLock lock];
-		[[dirtyLogSet allObjects] writeToFile:[self _dirtyLogSetPath] atomically:NO];
-		[dirtyLogLock unlock];
+			[[dirtyLogSet allObjects] writeToFile:[self _dirtyLogSetPath] atomically:NO];
     }
+	[dirtyLogLock unlock];
 }
 
 //Path of the dirty log set file
@@ -1375,39 +1375,29 @@
 
 //Threaded Indexing ----------------------------------------------------------------------------------------------------
 #pragma mark Threaded Indexing
-//Stop any indexing related threads
-- (void)stopIndexingThreads
-{
-    //Let any indexing threads know it's time to stop, and wait for them to finish.
-    stopIndexingThreads = YES;
-}
 
 //The following methods will be run in a separate thread to avoid blocking the interface during index operations
 //THREAD: Flag every log as dirty (Do this when there is no log index)
 - (void)dirtyAllLogs
 {
-    //Reset and rebuild the dirty set
+	//Reset and rebuild the dirty set
 	[dirtyLogLock lock];
-    [dirtyLogSet removeAllObjects];
+	[dirtyLogSet removeAllObjects];
 	[dirtyLogLock unlock];
-	//[self _dirtyAllLogsThread];
-	[[AILoggerPlugin operationQueue] addOperation:[[NSInvocationOperation alloc]
-												   initWithTarget:self
-												   selector:@selector(_dirtyAllLogsThread)
-												   object:nil]];
+	[self _dirtyAllLogsThread];
 }
+
 - (void)_dirtyAllLogsThread
 {
     NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
 
-    [indexingThreadLock lock];
     suspendDirtySetSaving = YES;    //Prevent saving of the dirty set until we're finished building it
     
     //Create a fresh dirty log set
-    [dirtyLogLock lock];
+	[dirtyLogLock lock];
     [dirtyLogSet removeAllObjects];
 	AILogWithSignature(@"Dirtying all logs.");
-    [dirtyLogLock unlock];
+	[dirtyLogLock unlock];
 	
     //Process each from folder
 	NSArray *fromNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self logBasePath]
@@ -1423,11 +1413,11 @@
 			for (AIChatLog *theLog in [toGroup logEnumerator]) {
 				//Add this log's path to our dirty set.  The dirty set is guarded with a lock
 				//since it will be accessed from outside this thread as well
-				[dirtyLogLock lock];
 				if (theLog != nil) {
+					[dirtyLogLock lock];
 					[dirtyLogSet addObject:[logBasePath stringByAppendingPathComponent:[theLog relativePath]]];
+					[dirtyLogLock unlock];
 				}
-				[dirtyLogLock unlock];
 			}
 			
 			//Flush our pool
@@ -1444,11 +1434,10 @@
 	suspendDirtySetSaving = NO; //Re-allow saving of the dirty set
     
     //Begin cleaning the logs (If the log viewer is open)
-    if (!stopIndexingThreads && [AILogViewerWindowController existingWindowController]) {
+    if (indexingAllowed && [AILogViewerWindowController existingWindowController]) {
 		[self cleanDirtyLogs];
     }
     
-    [indexingThreadLock unlock];
     [pool release];
 }
 
@@ -1460,25 +1449,24 @@
 - (void)cleanDirtyLogs
 {
 	//Do nothing if we're paused
-	if (logIndexingPauses) return;
+	if (!indexingAllowed) return;
 
     //Reset the cleaning progress
-    [dirtyLogLock lock];
+	[dirtyLogLock lock];
     logsToIndex = [dirtyLogSet count];
-    [dirtyLogLock unlock];
+	[dirtyLogLock unlock];
     logsIndexed = 0;
 	AILogWithSignature(@"cleanDirtyLogs: logsToIndex is %i",logsToIndex);
 	if (logsToIndex > 0) {
-		[[AILoggerPlugin operationQueue] addOperation:
-		 [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(_cleanDirtyLogsThread:) object:(id)[self logContentIndex]]];
+		[self _cleanDirtyLogsThread:[self logContentIndex]];
 	}
 }
 
 - (void)didCleanDirtyLogs
 {
 	[dirtyLogLock lock];
-    logsToIndex = [dirtyLogSet count];
-    [dirtyLogLock unlock];
+	logsToIndex = [dirtyLogSet count];
+	[dirtyLogLock unlock];
 
 	[[AILogViewerWindowController existingWindowController] logIndexingProgressUpdate];
 
@@ -1500,33 +1488,28 @@
 - (void)pauseIndexing
 {
 	if (logsToIndex) {
-		[self stopIndexingThreads];
+		indexingAllowed = NO;
 		logsToIndex = 0;
-		logIndexingPauses++;
-		AILogWithSignature(@"Pausing %i",logIndexingPauses);
+		AILogWithSignature(@"Paused Indexing");
 	}
 }
 
 - (void)resumeIndexing
 {
-	if (logIndexingPauses)
-		logIndexingPauses--;
-	AILogWithSignature(@"Told to resume; log indexing paauses is now %i",logIndexingPauses);
-	if (logIndexingPauses == 0) {
-		stopIndexingThreads = NO;
-		[self cleanDirtyLogs];
-	}
+	AILogWithSignature(@"Told to resume indexing");
+	indexingAllowed = YES;
+	[[[self class] operationQueue] addOperation:
+	 [[NSInvocationOperation alloc] initWithTarget:self
+																				selector:@selector(cleanDirtyLogs)
+																					object:nil]];
 }
 
 - (void)_cleanDirtyLogsThread:(SKIndexRef)searchIndex
 {
     NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
 
-	[indexingThreadLock lock];
-
 	//If log indexing was already in progress, we can just cancel since it is now complete
 	if (logsToIndex == 0) {
-		[indexingThreadLock unlock];
 		AILogWithSignature(@"Nothing to clean!");
 		[self performSelectorOnMainThread:@selector(didCleanDirtyLogs)
 							   withObject:nil
@@ -1536,7 +1519,6 @@
 	}
 
 	if (!searchIndex) {
-		[indexingThreadLock unlock];
 		AILogWithSignature(@"*** Warning: Called -[%@ _cleanDirtyLogsThread:] with a NULL searchIndex. That shouldn't happen!", self);
 		[pool release];
 		return;
@@ -1546,14 +1528,14 @@
     logsIndexed = 0;
 
     //Start cleaning (If we're still supposed to go)
-    if (!stopIndexingThreads) {
+    if (indexingAllowed) {
 		UInt32	lastUpdate = TickCount();
 		NSInteger		unsavedChanges = 0;
 
 		AILogWithSignature(@"Cleaning %i dirty logs", [dirtyLogSet count]);
 
 		//Scan until we're done or told to stop
-		while (!stopIndexingThreads) {
+		while (indexingAllowed) {
 			NSString	*logPath = nil;
 			
 			//Get the next dirty log
@@ -1620,12 +1602,10 @@
 		}
 
 		isFlushingIndex = YES;
-		[logWritingLock lockWhenCondition:AIIndexFileAvailable];
 		SKIndexFlush(searchIndex);
 		AILogWithSignature(@"After cleaning dirty logs, the search index has a max ID of %i and a count of %i",
 			  SKIndexGetMaximumDocumentID(searchIndex),
 			  SKIndexGetDocumentCount(searchIndex));
-		[logWritingLock unlockWithCondition:AIIndexFileAvailable];
 		isFlushingIndex = NO;
 		
 		[self performSelectorOnMainThread:@selector(didCleanDirtyLogs)
@@ -1635,7 +1615,6 @@
 
 	CFRelease(searchIndex);
 
-	[indexingThreadLock unlock];
 
     [pool release];
 }
@@ -1644,7 +1623,6 @@
 {
 	NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
 
-	[indexingThreadLock lock];
 
 	SKIndexRef logSearchIndex = (SKIndexRef)[userInfo objectForKey:@"SKIndexRef"];
 	
@@ -1656,8 +1634,6 @@
 		}
 	}
 
-	[indexingThreadLock unlock];
-
 	[pool release];
 }
 




More information about the commits mailing list