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