[Core Data] Add access locking
Apparently we need this to prevent Core Data from stomping on itself when another thread accesses it. Signed-off-by: Christopher Snowhill <kode54@gmail.com>xcode15
parent
faa546bc49
commit
051b86cbaf
|
@ -229,7 +229,9 @@ static AppController *kAppController = nil;
|
||||||
request.predicate = predicate;
|
request.predicate = predicate;
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[playlistController.persistentContainerLock lock];
|
||||||
NSArray *results = [playlistController.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [playlistController.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[playlistController.persistentContainerLock unlock];
|
||||||
|
|
||||||
if(results && [results count] == 1) {
|
if(results && [results count] == 1) {
|
||||||
PlaylistEntry *pe = results[0];
|
PlaylistEntry *pe = results[0];
|
||||||
|
@ -435,7 +437,9 @@ static AppController *kAppController = nil;
|
||||||
|
|
||||||
for(PlaylistEntry *pe in playlistController.arrangedObjects) {
|
for(PlaylistEntry *pe in playlistController.arrangedObjects) {
|
||||||
if(pe.deLeted) {
|
if(pe.deLeted) {
|
||||||
|
[playlistController.persistentContainerLock lock];
|
||||||
[moc deleteObject:pe];
|
[moc deleteObject:pe];
|
||||||
|
[playlistController.persistentContainerLock unlock];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if([artLeftovers objectForKey:pe.artHash]) {
|
if([artLeftovers objectForKey:pe.artHash]) {
|
||||||
|
@ -443,9 +447,11 @@ static AppController *kAppController = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[playlistController.persistentContainerLock lock];
|
||||||
for(NSString *key in artLeftovers) {
|
for(NSString *key in artLeftovers) {
|
||||||
[moc deleteObject:[artLeftovers objectForKey:key]];
|
[moc deleteObject:[artLeftovers objectForKey:key]];
|
||||||
}
|
}
|
||||||
|
[playlistController.persistentContainerLock unlock];
|
||||||
|
|
||||||
[playlistController commitPersistentStore];
|
[playlistController commitPersistentStore];
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ typedef NS_ENUM(NSInteger, URLOrigin) {
|
||||||
@property(retain) NSString *_Nullable totalTime;
|
@property(retain) NSString *_Nullable totalTime;
|
||||||
@property(retain) NSString *_Nullable currentStatus;
|
@property(retain) NSString *_Nullable currentStatus;
|
||||||
|
|
||||||
|
@property(strong, nonatomic, readonly) NSLock *_Nonnull persistentContainerLock;
|
||||||
@property(strong, nonatomic, readonly) NSPersistentContainer *_Nonnull persistentContainer;
|
@property(strong, nonatomic, readonly) NSPersistentContainer *_Nonnull persistentContainer;
|
||||||
@property(strong, nonatomic, readonly) NSMutableDictionary<NSString *, AlbumArtwork *> *_Nonnull persistentArtStorage;
|
@property(strong, nonatomic, readonly) NSMutableDictionary<NSString *, AlbumArtwork *> *_Nonnull persistentArtStorage;
|
||||||
|
|
||||||
|
@ -141,6 +142,7 @@ typedef NS_ENUM(NSInteger, URLOrigin) {
|
||||||
- (void)readShuffleListFromDataStore;
|
- (void)readShuffleListFromDataStore;
|
||||||
|
|
||||||
+ (NSPersistentContainer *_Nonnull)sharedPersistentContainer;
|
+ (NSPersistentContainer *_Nonnull)sharedPersistentContainer;
|
||||||
|
+ (NSLock *_Nonnull)sharedPersistentContainerLock;
|
||||||
|
|
||||||
// reload metadata of selection
|
// reload metadata of selection
|
||||||
- (IBAction)reloadTags:(id _Nullable)sender;
|
- (IBAction)reloadTags:(id _Nullable)sender;
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
extern BOOL kAppControllerShuttingDown;
|
extern BOOL kAppControllerShuttingDown;
|
||||||
|
|
||||||
|
NSLock *kPersistentContainerLock = nil;
|
||||||
|
|
||||||
NSPersistentContainer *kPersistentContainer = nil;
|
NSPersistentContainer *kPersistentContainer = nil;
|
||||||
|
|
||||||
@implementation PlaylistController
|
@implementation PlaylistController
|
||||||
|
@ -124,6 +126,10 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
kPersistentContainer = self.persistentContainer;
|
kPersistentContainer = self.persistentContainer;
|
||||||
|
|
||||||
|
_persistentContainerLock = [[NSLock alloc] init];
|
||||||
|
|
||||||
|
kPersistentContainerLock = self.persistentContainerLock;
|
||||||
|
|
||||||
self.persistentContainer.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
|
self.persistentContainer.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
|
||||||
|
|
||||||
|
@ -137,6 +143,10 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
return kPersistentContainer;
|
return kPersistentContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSLock *)sharedPersistentContainerLock {
|
||||||
|
return kPersistentContainerLock;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)awakeFromNib {
|
- (void)awakeFromNib {
|
||||||
[super awakeFromNib];
|
[super awakeFromNib];
|
||||||
|
|
||||||
|
@ -240,7 +250,9 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
|
|
||||||
- (void)commitPersistentStore {
|
- (void)commitPersistentStore {
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[self.persistentContainerLock lock];
|
||||||
[self.persistentContainer.viewContext save:&error];
|
[self.persistentContainer.viewContext save:&error];
|
||||||
|
[self.persistentContainerLock unlock];
|
||||||
if(error) {
|
if(error) {
|
||||||
ALog(@"Error committing playlist storage: %@", [error localizedDescription]);
|
ALog(@"Error committing playlist storage: %@", [error localizedDescription]);
|
||||||
}
|
}
|
||||||
|
@ -256,7 +268,9 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
pc.count += 1;
|
pc.count += 1;
|
||||||
pc.lastPlayed = [NSDate date];
|
pc.lastPlayed = [NSDate date];
|
||||||
} else {
|
} else {
|
||||||
|
[self.persistentContainerLock lock];
|
||||||
pc = [NSEntityDescription insertNewObjectForEntityForName:@"PlayCount" inManagedObjectContext:self.persistentContainer.viewContext];
|
pc = [NSEntityDescription insertNewObjectForEntityForName:@"PlayCount" inManagedObjectContext:self.persistentContainer.viewContext];
|
||||||
|
[self.persistentContainerLock unlock];
|
||||||
pc.count = 1;
|
pc.count = 1;
|
||||||
pc.firstSeen = pc.lastPlayed = [NSDate date];
|
pc.firstSeen = pc.lastPlayed = [NSDate date];
|
||||||
pc.album = pe.album;
|
pc.album = pe.album;
|
||||||
|
@ -272,7 +286,9 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
PlayCount *pc = pe.playCountItem;
|
PlayCount *pc = pe.playCountItem;
|
||||||
|
|
||||||
if(!pc) {
|
if(!pc) {
|
||||||
|
[self.persistentContainerLock lock];
|
||||||
pc = [NSEntityDescription insertNewObjectForEntityForName:@"PlayCount" inManagedObjectContext:self.persistentContainer.viewContext];
|
pc = [NSEntityDescription insertNewObjectForEntityForName:@"PlayCount" inManagedObjectContext:self.persistentContainer.viewContext];
|
||||||
|
[self.persistentContainerLock unlock];
|
||||||
pc.count = 0;
|
pc.count = 0;
|
||||||
pc.firstSeen = [NSDate date];
|
pc.firstSeen = [NSDate date];
|
||||||
pc.album = pe.album;
|
pc.album = pe.album;
|
||||||
|
@ -287,7 +303,9 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
PlayCount *pc = pe.playCountItem;
|
PlayCount *pc = pe.playCountItem;
|
||||||
|
|
||||||
if(!pc) {
|
if(!pc) {
|
||||||
|
[self.persistentContainerLock lock];
|
||||||
pc = [NSEntityDescription insertNewObjectForEntityForName:@"PlayCount" inManagedObjectContext:self.persistentContainer.viewContext];
|
pc = [NSEntityDescription insertNewObjectForEntityForName:@"PlayCount" inManagedObjectContext:self.persistentContainer.viewContext];
|
||||||
|
[self.persistentContainerLock unlock];
|
||||||
pc.count = 0;
|
pc.count = 0;
|
||||||
pc.firstSeen = [NSDate date];
|
pc.firstSeen = [NSDate date];
|
||||||
pc.album = pe.album;
|
pc.album = pe.album;
|
||||||
|
@ -1341,7 +1359,9 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
request.sortDescriptors = @[sortDescriptor];
|
request.sortDescriptors = @[sortDescriptor];
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[self.persistentContainerLock lock];
|
||||||
NSArray *results = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[self.persistentContainerLock unlock];
|
||||||
|
|
||||||
if(results && [results count] > 0) {
|
if(results && [results count] > 0) {
|
||||||
[queueList removeAllObjects];
|
[queueList removeAllObjects];
|
||||||
|
@ -1360,7 +1380,9 @@ static void *playlistControllerContext = &playlistControllerContext;
|
||||||
request.sortDescriptors = @[sortDescriptor];
|
request.sortDescriptors = @[sortDescriptor];
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[self.persistentContainerLock lock];
|
||||||
NSArray *results = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[self.persistentContainerLock unlock];
|
||||||
|
|
||||||
if(results && [results count] > 0) {
|
if(results && [results count] > 0) {
|
||||||
[shuffleList removeAllObjects];
|
[shuffleList removeAllObjects];
|
||||||
|
@ -1887,7 +1909,9 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SandboxToken"];
|
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SandboxToken"];
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[self.persistentContainerLock lock];
|
||||||
NSArray *results = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[self.persistentContainerLock unlock];
|
||||||
|
|
||||||
if(!results || [results count] < 1) return YES;
|
if(!results || [results count] < 1) return YES;
|
||||||
else return NO;
|
else return NO;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#import "SHA256Digest.h"
|
#import "SHA256Digest.h"
|
||||||
#import "SecondsFormatter.h"
|
#import "SecondsFormatter.h"
|
||||||
|
|
||||||
|
extern NSLock *kPersistentContainerLock;
|
||||||
extern NSPersistentContainer *kPersistentContainer;
|
extern NSPersistentContainer *kPersistentContainer;
|
||||||
extern NSMutableDictionary<NSString *, AlbumArtwork *> *kArtworkDictionary;
|
extern NSMutableDictionary<NSString *, AlbumArtwork *> *kArtworkDictionary;
|
||||||
|
|
||||||
|
@ -363,7 +364,9 @@ extern NSMutableDictionary<NSString *, AlbumArtwork *> *kArtworkDictionary;
|
||||||
self.artHash = imageCacheTag;
|
self.artHash = imageCacheTag;
|
||||||
|
|
||||||
if(![kArtworkDictionary objectForKey:imageCacheTag]) {
|
if(![kArtworkDictionary objectForKey:imageCacheTag]) {
|
||||||
|
[kPersistentContainerLock lock];
|
||||||
AlbumArtwork *art = [NSEntityDescription insertNewObjectForEntityForName:@"AlbumArtwork" inManagedObjectContext:kPersistentContainer.viewContext];
|
AlbumArtwork *art = [NSEntityDescription insertNewObjectForEntityForName:@"AlbumArtwork" inManagedObjectContext:kPersistentContainer.viewContext];
|
||||||
|
[kPersistentContainerLock unlock];
|
||||||
art.artHash = imageCacheTag;
|
art.artHash = imageCacheTag;
|
||||||
art.artData = albumArtInternal;
|
art.artData = albumArtInternal;
|
||||||
|
|
||||||
|
@ -586,7 +589,9 @@ NSURL *_Nullable urlForPath(NSString *_Nullable path) {
|
||||||
request.predicate = predicate;
|
request.predicate = predicate;
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[kPersistentContainerLock lock];
|
||||||
NSArray *results = [kPersistentContainer.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [kPersistentContainer.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[kPersistentContainerLock unlock];
|
||||||
|
|
||||||
if(!results || [results count] < 1) {
|
if(!results || [results count] < 1) {
|
||||||
NSPredicate *filenamePredicate = [NSPredicate predicateWithFormat:@"filename == %@", self.filenameFragment];
|
NSPredicate *filenamePredicate = [NSPredicate predicateWithFormat:@"filename == %@", self.filenameFragment];
|
||||||
|
@ -594,7 +599,9 @@ NSURL *_Nullable urlForPath(NSString *_Nullable path) {
|
||||||
request = [NSFetchRequest fetchRequestWithEntityName:@"PlayCount"];
|
request = [NSFetchRequest fetchRequestWithEntityName:@"PlayCount"];
|
||||||
request.predicate = filenamePredicate;
|
request.predicate = filenamePredicate;
|
||||||
|
|
||||||
|
[kPersistentContainerLock lock];
|
||||||
results = [kPersistentContainer.viewContext executeFetchRequest:request error:&error];
|
results = [kPersistentContainer.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[kPersistentContainerLock unlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!results || [results count] < 1) return nil;
|
if(!results || [results count] < 1) return nil;
|
||||||
|
|
|
@ -518,7 +518,9 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
__block PlaylistEntry *pe;
|
__block PlaylistEntry *pe;
|
||||||
|
|
||||||
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
[self->playlistController.persistentContainerLock lock];
|
||||||
pe = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:self->playlistController.persistentContainer.viewContext];
|
pe = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:self->playlistController.persistentContainer.viewContext];
|
||||||
|
[self->playlistController.persistentContainerLock unlock];
|
||||||
pe.url = url;
|
pe.url = url;
|
||||||
pe.index = index + i;
|
pe.index = index + i;
|
||||||
pe.rawTitle = [[url path] lastPathComponent];
|
pe.rawTitle = [[url path] lastPathComponent];
|
||||||
|
@ -540,7 +542,9 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
__block PlaylistEntry *pe;
|
__block PlaylistEntry *pe;
|
||||||
|
|
||||||
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
[self->playlistController.persistentContainerLock lock];
|
||||||
pe = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:self->playlistController.persistentContainer.viewContext];
|
pe = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:self->playlistController.persistentContainer.viewContext];
|
||||||
|
[self->playlistController.persistentContainerLock unlock];
|
||||||
[pe setValuesForKeysWithDictionary:entry];
|
[pe setValuesForKeysWithDictionary:entry];
|
||||||
pe.index = index + i;
|
pe.index = index + i;
|
||||||
pe.queuePosition = -1;
|
pe.queuePosition = -1;
|
||||||
|
@ -742,7 +746,9 @@ NSURL *_Nullable urlForPath(NSString *_Nullable path);
|
||||||
request.predicate = predicate;
|
request.predicate = predicate;
|
||||||
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
|
[playlistController.persistentContainerLock lock];
|
||||||
NSArray *results = [moc executeFetchRequest:request error:&error];
|
NSArray *results = [moc executeFetchRequest:request error:&error];
|
||||||
|
[playlistController.persistentContainerLock unlock];
|
||||||
|
|
||||||
if(results && [results count] > 0) {
|
if(results && [results count] > 0) {
|
||||||
for(PlaylistEntry *pe in results) {
|
for(PlaylistEntry *pe in results) {
|
||||||
|
@ -869,7 +875,9 @@ NSURL *_Nullable urlForPath(NSString *_Nullable path);
|
||||||
|
|
||||||
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"AlbumArtwork"];
|
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"AlbumArtwork"];
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[playlistController.persistentContainerLock lock];
|
||||||
NSArray *results = [moc executeFetchRequest:request error:&error];
|
NSArray *results = [moc executeFetchRequest:request error:&error];
|
||||||
|
[playlistController.persistentContainerLock unlock];
|
||||||
if(!results) {
|
if(!results) {
|
||||||
ALog(@"Error fetching AlbumArtwork objects: %@\n%@", [error localizedDescription], [error userInfo]);
|
ALog(@"Error fetching AlbumArtwork objects: %@\n%@", [error localizedDescription], [error userInfo]);
|
||||||
abort();
|
abort();
|
||||||
|
@ -885,7 +893,9 @@ NSURL *_Nullable urlForPath(NSString *_Nullable path);
|
||||||
|
|
||||||
request.sortDescriptors = @[sortDescriptor];
|
request.sortDescriptors = @[sortDescriptor];
|
||||||
|
|
||||||
|
[playlistController.persistentContainerLock lock];
|
||||||
results = [moc executeFetchRequest:request error:&error];
|
results = [moc executeFetchRequest:request error:&error];
|
||||||
|
[playlistController.persistentContainerLock unlock];
|
||||||
if(!results) {
|
if(!results) {
|
||||||
ALog(@"Error fetching PlaylistEntry objects: %@\n%@", [error localizedDescription], [error userInfo]);
|
ALog(@"Error fetching PlaylistEntry objects: %@\n%@", [error localizedDescription], [error userInfo]);
|
||||||
abort();
|
abort();
|
||||||
|
@ -899,7 +909,9 @@ NSURL *_Nullable urlForPath(NSString *_Nullable path);
|
||||||
for(PlaylistEntry *pe in resultsCopy) {
|
for(PlaylistEntry *pe in resultsCopy) {
|
||||||
if(pe.deLeted || !pe.urlString || [pe.urlString length] < 1) {
|
if(pe.deLeted || !pe.urlString || [pe.urlString length] < 1) {
|
||||||
[pruneSet addIndex:index];
|
[pruneSet addIndex:index];
|
||||||
|
[playlistController.persistentContainerLock lock];
|
||||||
[moc deleteObject:pe];
|
[moc deleteObject:pe];
|
||||||
|
[playlistController.persistentContainerLock unlock];
|
||||||
}
|
}
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
|
|
||||||
[pathsList removeObjects:[pathsList arrangedObjects]];
|
[pathsList removeObjects:[pathsList arrangedObjects]];
|
||||||
|
|
||||||
|
NSLock *lock = [NSClassFromString(@"PlaylistController") sharedPersistentContainerLock];
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
||||||
|
|
||||||
NSPredicate *hasUrlPredicate = [NSPredicate predicateWithFormat:@"urlString != nil && urlString != %@", @""];
|
NSPredicate *hasUrlPredicate = [NSPredicate predicateWithFormat:@"urlString != nil && urlString != %@", @""];
|
||||||
|
@ -66,7 +67,9 @@
|
||||||
request.predicate = predicate;
|
request.predicate = predicate;
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[lock lock];
|
||||||
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[lock unlock];
|
||||||
|
|
||||||
if(!results || [results count] < 1) return;
|
if(!results || [results count] < 1) return;
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,15 @@
|
||||||
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"path" ascending:YES];
|
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"path" ascending:YES];
|
||||||
[self setSortDescriptors:@[sortDescriptor]];
|
[self setSortDescriptors:@[sortDescriptor]];
|
||||||
|
|
||||||
|
NSLock *lock = [NSClassFromString(@"PlaylistController") sharedPersistentContainerLock];
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
||||||
|
|
||||||
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SandboxToken"];
|
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SandboxToken"];
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[lock lock];
|
||||||
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[lock unlock];
|
||||||
|
|
||||||
if(results && [results count] > 0) {
|
if(results && [results count] > 0) {
|
||||||
for(SandboxToken *token in results) {
|
for(SandboxToken *token in results) {
|
||||||
|
@ -57,14 +60,19 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSLock *lock = [NSClassFromString(@"PlaylistController") sharedPersistentContainerLock];
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
||||||
|
|
||||||
|
[lock lock];
|
||||||
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
||||||
|
[lock unlock];
|
||||||
|
|
||||||
if(token) {
|
if(token) {
|
||||||
token.path = [url path];
|
token.path = [url path];
|
||||||
token.bookmark = bookmark;
|
token.bookmark = bookmark;
|
||||||
|
[lock lock];
|
||||||
[pc.viewContext save:&err];
|
[pc.viewContext save:&err];
|
||||||
|
[lock unlock];
|
||||||
if(err) {
|
if(err) {
|
||||||
ALog(@"Error saving bookmark: %@", [err localizedDescription]);
|
ALog(@"Error saving bookmark: %@", [err localizedDescription]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,6 +82,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)removeToken:(id)token {
|
- (void)removeToken:(id)token {
|
||||||
|
NSLock *lock = [NSClassFromString(@"PlaylistController") sharedPersistentContainerLock];
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
||||||
|
|
||||||
NSArray *objects = [[self arrangedObjects] copy];
|
NSArray *objects = [[self arrangedObjects] copy];
|
||||||
|
@ -83,7 +92,9 @@
|
||||||
for(NSDictionary *obj in objects) {
|
for(NSDictionary *obj in objects) {
|
||||||
if([[obj objectForKey:@"token"] isEqualTo:token]) {
|
if([[obj objectForKey:@"token"] isEqualTo:token]) {
|
||||||
[self removeObject:obj];
|
[self removeObject:obj];
|
||||||
|
[lock lock];
|
||||||
[pc.viewContext deleteObject:token];
|
[pc.viewContext deleteObject:token];
|
||||||
|
[lock unlock];
|
||||||
updated = YES;
|
updated = YES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +102,9 @@
|
||||||
|
|
||||||
if(updated) {
|
if(updated) {
|
||||||
NSError *error;
|
NSError *error;
|
||||||
|
[lock lock];
|
||||||
[pc.viewContext save:&error];
|
[pc.viewContext save:&error];
|
||||||
|
[lock unlock];
|
||||||
if(error) {
|
if(error) {
|
||||||
ALog(@"Error deleting bookmark: %@", [error localizedDescription]);
|
ALog(@"Error deleting bookmark: %@", [error localizedDescription]);
|
||||||
}
|
}
|
||||||
|
@ -100,17 +113,22 @@
|
||||||
|
|
||||||
- (void)removeStaleEntries {
|
- (void)removeStaleEntries {
|
||||||
BOOL updated = NO;
|
BOOL updated = NO;
|
||||||
|
NSLock *lock = [NSClassFromString(@"PlaylistController") sharedPersistentContainerLock];
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
||||||
for(NSDictionary *entry in [[self arrangedObjects] copy]) {
|
for(NSDictionary *entry in [[self arrangedObjects] copy]) {
|
||||||
if([[entry objectForKey:@"valid"] isEqualToString:NSLocalizedPrefString(@"ValidNo")]) {
|
if([[entry objectForKey:@"valid"] isEqualToString:NSLocalizedPrefString(@"ValidNo")]) {
|
||||||
[self removeObject:entry];
|
[self removeObject:entry];
|
||||||
|
[lock lock];
|
||||||
[pc.viewContext deleteObject:[entry objectForKey:@"token"]];
|
[pc.viewContext deleteObject:[entry objectForKey:@"token"]];
|
||||||
|
[lock unlock];
|
||||||
updated = YES;
|
updated = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(updated) {
|
if(updated) {
|
||||||
NSError *error;
|
NSError *error;
|
||||||
|
[lock lock];
|
||||||
[pc.viewContext save:&error];
|
[pc.viewContext save:&error];
|
||||||
|
[lock unlock];
|
||||||
if(error) {
|
if(error) {
|
||||||
ALog(@"Error saving after removing stale bookmarks: %@", [error localizedDescription]);
|
ALog(@"Error saving after removing stale bookmarks: %@", [error localizedDescription]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// with format (entryKey, transformerName)
|
// with format (entryKey, transformerName)
|
||||||
static NSDictionary *importKeys;
|
static NSDictionary *importKeys;
|
||||||
|
|
||||||
|
extern NSLock *kPersistentContainerLock;
|
||||||
extern NSPersistentContainer *kPersistentContainer;
|
extern NSPersistentContainer *kPersistentContainer;
|
||||||
|
|
||||||
@implementation SpotlightPlaylistEntry
|
@implementation SpotlightPlaylistEntry
|
||||||
|
@ -37,7 +38,9 @@ extern NSPersistentContainer *kPersistentContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (PlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem {
|
+ (PlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem {
|
||||||
|
[kPersistentContainerLock lock];
|
||||||
PlaylistEntry *entry = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:kPersistentContainer.viewContext];
|
PlaylistEntry *entry = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:kPersistentContainer.viewContext];
|
||||||
|
[kPersistentContainerLock unlock];
|
||||||
|
|
||||||
entry.deLeted = YES;
|
entry.deLeted = YES;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#import "SHA256Digest.h"
|
#import "SHA256Digest.h"
|
||||||
|
|
||||||
|
extern NSLock *kPersistentContainerLock;
|
||||||
extern NSPersistentContainer *kPersistentContainer;
|
extern NSPersistentContainer *kPersistentContainer;
|
||||||
|
|
||||||
NSString *getDatabasePath(void) {
|
NSString *getDatabasePath(void) {
|
||||||
|
@ -1443,7 +1444,9 @@ static SQLiteStore *g_sharedStore = nil;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
- (PlaylistEntry *_Nonnull)getTrack:(int64_t)trackId {
|
- (PlaylistEntry *_Nonnull)getTrack:(int64_t)trackId {
|
||||||
|
[kPersistentContainerLock lock];
|
||||||
PlaylistEntry *entry = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:kPersistentContainer.viewContext];
|
PlaylistEntry *entry = [NSEntityDescription insertNewObjectForEntityForName:@"PlaylistEntry" inManagedObjectContext:kPersistentContainer.viewContext];
|
||||||
|
[kPersistentContainerLock unlock];
|
||||||
|
|
||||||
if(trackId < 0) {
|
if(trackId < 0) {
|
||||||
entry.error = YES;
|
entry.error = YES;
|
||||||
|
@ -1863,7 +1866,9 @@ static SQLiteStore *g_sharedStore = nil;
|
||||||
entry.index = index;
|
entry.index = index;
|
||||||
entry.entryId = entryId;
|
entry.entryId = entryId;
|
||||||
} else {
|
} else {
|
||||||
|
[kPersistentContainerLock lock];
|
||||||
[kPersistentContainer.viewContext deleteObject:entry];
|
[kPersistentContainer.viewContext deleteObject:entry];
|
||||||
|
[kPersistentContainerLock unlock];
|
||||||
entry = nil;
|
entry = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,10 @@ static SandboxBroker *kSharedSandboxBroker = nil;
|
||||||
return kSharedSandboxBroker;
|
return kSharedSandboxBroker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSLock *)sharedPersistentContainerLock {
|
||||||
|
return [NSClassFromString(@"PlaylistController") sharedPersistentContainerLock];
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSPersistentContainer *)sharedPersistentContainer {
|
+ (NSPersistentContainer *)sharedPersistentContainer {
|
||||||
return [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
return [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
||||||
}
|
}
|
||||||
|
@ -149,6 +153,7 @@ static SandboxBroker *kSharedSandboxBroker = nil;
|
||||||
- (SandboxEntry *)recursivePathTest:(NSURL *)url {
|
- (SandboxEntry *)recursivePathTest:(NSURL *)url {
|
||||||
SandboxEntry *ret = nil;
|
SandboxEntry *ret = nil;
|
||||||
|
|
||||||
|
NSLock *lock = [SandboxBroker sharedPersistentContainerLock];
|
||||||
NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer];
|
NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer];
|
||||||
|
|
||||||
NSPredicate *folderPredicate = [NSPredicate predicateWithFormat:@"folder == NO"];
|
NSPredicate *folderPredicate = [NSPredicate predicateWithFormat:@"folder == NO"];
|
||||||
|
@ -159,7 +164,9 @@ static SandboxBroker *kSharedSandboxBroker = nil;
|
||||||
request.predicate = predicate;
|
request.predicate = predicate;
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
|
[lock lock];
|
||||||
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
|
NSArray *results = [pc.viewContext executeFetchRequest:request error:&error];
|
||||||
|
[lock unlock];
|
||||||
if(results && [results count] > 0) {
|
if(results && [results count] > 0) {
|
||||||
ret = [[SandboxEntry alloc] initWithToken:results[0]];
|
ret = [[SandboxEntry alloc] initWithToken:results[0]];
|
||||||
}
|
}
|
||||||
|
@ -174,8 +181,9 @@ static SandboxBroker *kSharedSandboxBroker = nil;
|
||||||
request.predicate = predicate;
|
request.predicate = predicate;
|
||||||
|
|
||||||
error = nil;
|
error = nil;
|
||||||
|
[lock lock];
|
||||||
results = [pc.viewContext executeFetchRequest:request error:&error];
|
results = [pc.viewContext executeFetchRequest:request error:&error];
|
||||||
if(results) results = [results copy];
|
[lock unlock];
|
||||||
|
|
||||||
if(results && [results count] > 0) {
|
if(results && [results count] > 0) {
|
||||||
for(SandboxToken *token in results) {
|
for(SandboxToken *token in results) {
|
||||||
|
@ -240,9 +248,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSLock *lock = [SandboxBroker sharedPersistentContainerLock];
|
||||||
|
NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer];
|
||||||
|
|
||||||
|
[lock lock];
|
||||||
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
||||||
|
[lock unlock];
|
||||||
|
|
||||||
if(token) {
|
if(token) {
|
||||||
token.path = [folderUrl path];
|
token.path = [folderUrl path];
|
||||||
|
@ -283,10 +294,13 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSLock *lock = [SandboxBroker sharedPersistentContainerLock];
|
||||||
|
NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer];
|
||||||
|
|
||||||
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
dispatch_sync_reentrant(dispatch_get_main_queue(), ^{
|
||||||
|
[lock lock];
|
||||||
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
||||||
|
[lock unlock];
|
||||||
|
|
||||||
if(token) {
|
if(token) {
|
||||||
token.path = [url path];
|
token.path = [url path];
|
||||||
|
@ -335,9 +349,12 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSPersistentContainer *pc = [NSClassFromString(@"PlaylistController") sharedPersistentContainer];
|
NSLock *lock = [SandboxBroker sharedPersistentContainerLock];
|
||||||
|
NSPersistentContainer *pc = [SandboxBroker sharedPersistentContainer];
|
||||||
|
|
||||||
|
[lock lock];
|
||||||
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
SandboxToken *token = [NSEntityDescription insertNewObjectForEntityForName:@"SandboxToken" inManagedObjectContext:pc.viewContext];
|
||||||
|
[lock unlock];
|
||||||
|
|
||||||
if(token) {
|
if(token) {
|
||||||
token.path = [folderUrl path];
|
token.path = [folderUrl path];
|
||||||
|
|
Loading…
Reference in New Issue