SQLite playlist store: Greatly improved performance of playlist sync operations
parent
33f3b4f5a0
commit
74cd0f7da9
|
@ -12,6 +12,7 @@
|
||||||
NSInteger index;
|
NSInteger index;
|
||||||
NSInteger shuffleIndex;
|
NSInteger shuffleIndex;
|
||||||
NSInteger dbIndex;
|
NSInteger dbIndex;
|
||||||
|
NSInteger entryId;
|
||||||
|
|
||||||
BOOL current;
|
BOOL current;
|
||||||
BOOL removed;
|
BOOL removed;
|
||||||
|
@ -86,6 +87,7 @@
|
||||||
@property NSInteger index;
|
@property NSInteger index;
|
||||||
@property NSInteger shuffleIndex;
|
@property NSInteger shuffleIndex;
|
||||||
@property NSInteger dbIndex;
|
@property NSInteger dbIndex;
|
||||||
|
@property NSInteger entryId;
|
||||||
|
|
||||||
@property(readonly) NSString *status;
|
@property(readonly) NSString *status;
|
||||||
@property(readonly) NSString *statusMessage;
|
@property(readonly) NSString *statusMessage;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
@synthesize index;
|
@synthesize index;
|
||||||
@synthesize shuffleIndex;
|
@synthesize shuffleIndex;
|
||||||
@synthesize dbIndex;
|
@synthesize dbIndex;
|
||||||
|
@synthesize entryId;
|
||||||
|
|
||||||
@synthesize current;
|
@synthesize current;
|
||||||
@synthesize removed;
|
@synthesize removed;
|
||||||
|
|
|
@ -747,7 +747,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc
|
||||||
|
|
||||||
for (i = 0; i < count; ++i)
|
for (i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
PlaylistEntry *pe = [store playlistGetItem:i];
|
PlaylistEntry *pe = [store playlistGetCachedItem:i];
|
||||||
|
|
||||||
pe.queuePosition = -1;
|
pe.queuePosition = -1;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
@private NSString *g_databasePath;
|
@private NSString *g_databasePath;
|
||||||
@private sqlite3 *g_database;
|
@private sqlite3 *g_database;
|
||||||
@private sqlite3_stmt *stmt[38];
|
@private sqlite3_stmt *stmt[38];
|
||||||
|
@private NSMutableArray *databaseMirror;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, readwrite) NSString *databasePath;
|
@property (nonatomic, readwrite) NSString *databasePath;
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
- (void)playlistRemoveTracks:(int64_t)index forCount:(int64_t)count progressCall:(void(^)(double progress))callback;
|
- (void)playlistRemoveTracks:(int64_t)index forCount:(int64_t)count progressCall:(void(^)(double progress))callback;
|
||||||
- (void)playlistRemoveTracksAtIndexes:(NSIndexSet *)indexes progressCall:(void(^)(double progress))callback;
|
- (void)playlistRemoveTracksAtIndexes:(NSIndexSet *)indexes progressCall:(void(^)(double progress))callback;
|
||||||
- (PlaylistEntry *)playlistGetItem:(int64_t)index;
|
- (PlaylistEntry *)playlistGetItem:(int64_t)index;
|
||||||
|
- (PlaylistEntry *)playlistGetCachedItem:(int64_t)index;
|
||||||
- (int64_t)playlistGetCount;
|
- (int64_t)playlistGetCount;
|
||||||
#if 0
|
#if 0
|
||||||
- (void)playlistMoveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex;
|
- (void)playlistMoveObjectsInArrangedObjectsFromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex;
|
||||||
|
|
|
@ -378,7 +378,7 @@ enum
|
||||||
select_playlist_out_track_id,
|
select_playlist_out_track_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * query_select_playlist = "SELECT entryid, trackid FROM playlist WHERE (entryindex = ?) LIMIT 1";
|
const char * query_select_playlist = "SELECT entryid, trackid FROM playlist WHERE (entryindex = ?)";
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -635,6 +635,16 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
}
|
}
|
||||||
#undef PREPARE
|
#undef PREPARE
|
||||||
|
|
||||||
|
size_t count = [self playlistGetCount];
|
||||||
|
|
||||||
|
databaseMirror = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
PlaylistEntry *pe = [self playlistGetItem:i];
|
||||||
|
[databaseMirror addObject:pe];
|
||||||
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1527,6 +1537,8 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[databaseMirror insertObjects:tracks atIndexes:indexes];
|
||||||
|
|
||||||
__block int64_t total_count = 0;
|
__block int64_t total_count = 0;
|
||||||
[indexes enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
[indexes enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||||
total_count += range.length;
|
total_count += range.length;
|
||||||
|
@ -1639,6 +1651,8 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[databaseMirror removeObjectsAtIndexes:indexes];
|
||||||
|
|
||||||
__block int64_t total_count = 0;
|
__block int64_t total_count = 0;
|
||||||
|
|
||||||
[indexes enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
[indexes enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||||
|
@ -1665,6 +1679,14 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
callback(-1);
|
callback(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (PlaylistEntry *)playlistGetCachedItem:(int64_t)index
|
||||||
|
{
|
||||||
|
if (index >= 0 && index < [databaseMirror count])
|
||||||
|
return [databaseMirror objectAtIndex:index];
|
||||||
|
else
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (PlaylistEntry *)playlistGetItem:(int64_t)index
|
- (PlaylistEntry *)playlistGetItem:(int64_t)index
|
||||||
{
|
{
|
||||||
PlaylistEntry *entry = [[PlaylistEntry alloc] init];
|
PlaylistEntry *entry = [[PlaylistEntry alloc] init];
|
||||||
|
@ -1687,8 +1709,10 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
if (rc == SQLITE_ROW)
|
if (rc == SQLITE_ROW)
|
||||||
{
|
{
|
||||||
int64_t trackId = sqlite3_column_int64(st, select_playlist_out_track_id);
|
int64_t trackId = sqlite3_column_int64(st, select_playlist_out_track_id);
|
||||||
|
int64_t entryId = sqlite3_column_int64(st, select_playlist_out_entry_id);
|
||||||
entry = [self getTrack:trackId];
|
entry = [self getTrack:trackId];
|
||||||
[entry setIndex:index];
|
[entry setIndex:index];
|
||||||
|
[entry setEntryId:entryId];
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_reset(st);
|
sqlite3_reset(st);
|
||||||
|
@ -1836,73 +1860,33 @@ static SQLiteStore *g_sharedStore = NULL;
|
||||||
callback(0);
|
callback(0);
|
||||||
|
|
||||||
double progress = 0;
|
double progress = 0;
|
||||||
double progressstep = 50.0 / (double)(count);
|
double progressstep = 100.0 / (double)(count);
|
||||||
|
|
||||||
NSMutableArray * entryIds = [[NSMutableArray alloc] init];
|
sqlite3_stmt *st = stmt[stmt_update_playlist];
|
||||||
NSMutableArray * entryIndexes = [[NSMutableArray alloc] init];
|
|
||||||
NSMutableArray * trackIds = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
sqlite3_stmt *st = stmt[stmt_select_playlist_all];
|
for (size_t i = 0; i < count; ++i)
|
||||||
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (sqlite3_reset(st) ||
|
|
||||||
(rc = sqlite3_step(st)) != SQLITE_ROW)
|
|
||||||
{
|
{
|
||||||
callback(-1);
|
PlaylistEntry * newpe = [entries objectAtIndex:i];
|
||||||
return;
|
PlaylistEntry * oldpe = [databaseMirror objectAtIndex:i];
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
int64_t entryId = sqlite3_column_int64(st, select_playlist_all_out_entry_id);
|
|
||||||
int64_t entryIndex = sqlite3_column_int64(st, select_playlist_all_out_entry_index);
|
|
||||||
int64_t trackId = sqlite3_column_int64(st, select_playlist_all_out_track_id);
|
|
||||||
|
|
||||||
[entryIds addObject:[NSNumber numberWithInteger:entryId]];
|
|
||||||
[entryIndexes addObject:[NSNumber numberWithInteger:entryIndex]];
|
|
||||||
[trackIds addObject:[NSNumber numberWithInteger:trackId]];
|
|
||||||
|
|
||||||
rc = sqlite3_step(st);
|
|
||||||
|
|
||||||
progress += progressstep;
|
|
||||||
callback(progress);
|
|
||||||
}
|
|
||||||
while (rc == SQLITE_ROW);
|
|
||||||
|
|
||||||
sqlite3_reset(st);
|
|
||||||
|
|
||||||
progress = 50;
|
|
||||||
callback(progress);
|
|
||||||
|
|
||||||
st = stmt[stmt_update_playlist];
|
|
||||||
|
|
||||||
int64_t i = 0;
|
|
||||||
|
|
||||||
for (PlaylistEntry *entry in entries)
|
|
||||||
{
|
|
||||||
int64_t entryId = [[entryIds objectAtIndex:i] integerValue];
|
|
||||||
int64_t entryIndex = [[entryIndexes objectAtIndex:i] integerValue];
|
|
||||||
int64_t trackId = [[trackIds objectAtIndex:i] integerValue];
|
|
||||||
|
|
||||||
++i;
|
|
||||||
progress += progressstep;
|
|
||||||
|
|
||||||
if ([entry index] == entryIndex &&
|
progress += progressstep;
|
||||||
[entry dbIndex] == trackId)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (sqlite3_reset(st) ||
|
if (([oldpe index] != i ||
|
||||||
sqlite3_bind_int64(st, update_playlist_in_entry_index, [entry index]) ||
|
[oldpe dbIndex] != [newpe dbIndex]) &&
|
||||||
sqlite3_bind_int64(st, update_playlist_in_track_id, [entry dbIndex]) ||
|
[oldpe entryId] == [newpe entryId]) {
|
||||||
sqlite3_bind_int64(st, update_playlist_in_id, entryId) ||
|
|
||||||
sqlite3_step(st) != SQLITE_DONE)
|
if (sqlite3_reset(st) ||
|
||||||
{
|
sqlite3_bind_int64(st, update_playlist_in_id, [oldpe entryId]) ||
|
||||||
callback(-1);
|
sqlite3_bind_int64(st, update_playlist_in_entry_index, i) ||
|
||||||
return;
|
sqlite3_bind_int64(st, update_playlist_in_track_id, [newpe dbIndex]) ||
|
||||||
|
sqlite3_step(st) != SQLITE_ROW ||
|
||||||
|
sqlite3_reset(st))
|
||||||
|
{
|
||||||
|
callback(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(progress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_reset(st);
|
sqlite3_reset(st);
|
||||||
|
|
Loading…
Reference in New Issue