Permalink
Browse files

Additional debug code for #2163

  • Loading branch information...
dmoagx committed Oct 4, 2015
1 parent 670758d commit 80f8cae8ea9db39c1d4d4dee0bd7ae3f756ad62f
Showing with 99 additions and 25 deletions.
  1. +3 −0 Source/SPDataStorage.h
  2. +96 −25 Source/SPDataStorage.m
@@ -47,6 +47,9 @@
NSUInteger numberOfColumns;
NSUInteger editedRowCount;
NSString *_debugInfo;
uint64_t _debugTime;
}
/* Setting result store */
@@ -32,13 +32,18 @@
#import "SPObjectAdditions.h"
#import <SPMySQL/SPMySQLStreamingResultStore.h>
#include <stdlib.h>
#include <mach/mach_time.h>
@interface SPDataStorage (Private_API)
- (void) _checkNewRow:(NSMutableArray *)aRow;
- (void)_recordClearingUnloadedColumnsAt:(uint64_t)now from:(NSArray *)callStack;
- (void)_assesUnloadedColumnsIsSet;
@end
static uint64_t _elapsedMilliSecondsSinceAbsoluteTime(uint64_t comparisonTime);
@implementation SPDataStorage
static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore, NSUInteger rowIndex)
@@ -60,7 +65,13 @@ - (void) setDataStorage:(SPMySQLStreamingResultStore *)newDataStorage updatingEx
NSUInteger i;
editedRowCount = 0;
SPClear(editedRows);
if (unloadedColumns) free(unloadedColumns), unloadedColumns = NULL;
@synchronized(self) {
if (unloadedColumns) {
[self _recordClearingUnloadedColumnsAt:mach_absolute_time() from:[NSThread callStackSymbols]];
free(unloadedColumns), unloadedColumns = NULL;
}
}
if (dataStorage) {
@@ -81,9 +92,11 @@ - (void) setDataStorage:(SPMySQLStreamingResultStore *)newDataStorage updatingEx
[self resultStoreDidFinishLoadingData:dataStorage];
}
unloadedColumns = calloc(numberOfColumns, sizeof(BOOL));
for (i = 0; i < numberOfColumns; i++) {
unloadedColumns[i] = NO;
@synchronized(self) {
unloadedColumns = calloc(numberOfColumns, sizeof(BOOL));
for (i = 0; i < numberOfColumns; i++) {
unloadedColumns[i] = NO;
}
}
}
@@ -110,10 +123,12 @@ - (NSMutableArray *) rowContentsAtIndex:(NSUInteger)anIndex
NSMutableArray *dataArray = SPMySQLResultStoreGetRow(dataStorage, anIndex);
// Modify unloaded cells as appropriate
for (NSUInteger i = 0; i < numberOfColumns; i++) {
NSAssert(unloadedColumns != NULL, @"unloadedColumns not loaded!");
if (unloadedColumns[i]) {
CFArraySetValueAtIndex((CFMutableArrayRef)dataArray, i, [SPNotLoaded notLoaded]);
@synchronized(self) {
[self _assesUnloadedColumnsIsSet];
for (NSUInteger i = 0; i < numberOfColumns; i++) {
if (unloadedColumns[i]) {
CFArraySetValueAtIndex((CFMutableArrayRef)dataArray, i, [SPNotLoaded notLoaded]);
}
}
}
@@ -140,9 +155,11 @@ - (id) cellDataAtRow:(NSUInteger)rowIndex column:(NSUInteger)columnIndex
}
// If the specified column is not loaded, return a SPNotLoaded reference
NSAssert(unloadedColumns != NULL, @"unloadedColumns not loaded!");
if (unloadedColumns[columnIndex]) {
return [SPNotLoaded notLoaded];
@synchronized(self) {
[self _assesUnloadedColumnsIsSet];
if (unloadedColumns[columnIndex]) {
return [SPNotLoaded notLoaded];
}
}
// Return the content
@@ -175,9 +192,11 @@ - (id) cellPreviewAtRow:(NSUInteger)rowIndex column:(NSUInteger)columnIndex prev
}
// If the specified column is not loaded, return a SPNotLoaded reference
NSAssert(unloadedColumns != NULL, @"unloadedColumns not loaded!");
if (unloadedColumns[columnIndex]) {
return [SPNotLoaded notLoaded];
@synchronized(self) {
[self _assesUnloadedColumnsIsSet];
if (unloadedColumns[columnIndex]) {
return [SPNotLoaded notLoaded];
}
}
// Return the content
@@ -203,9 +222,11 @@ - (BOOL) cellIsNullOrUnloadedAtRow:(NSUInteger)rowIndex column:(NSUInteger)colum
[NSException raise:NSRangeException format:@"Requested storage column (col %llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns];
}
NSAssert(unloadedColumns != NULL, @"unloadedColumns not loaded!");
if (unloadedColumns[columnIndex]) {
return YES;
@synchronized(self) {
[self _assesUnloadedColumnsIsSet];
if (unloadedColumns[columnIndex]) {
return YES;
}
}
return [dataStorage cellIsNullAtRow:rowIndex column:columnIndex];
@@ -236,10 +257,12 @@ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state object
targetRow = SPMySQLResultStoreGetRow(dataStorage, state->state);
// Modify unloaded cells as appropriate
for (NSUInteger i = 0; i < numberOfColumns; i++) {
NSAssert(unloadedColumns != NULL, @"unloadedColumns not loaded!");
if (unloadedColumns[i]) {
CFArraySetValueAtIndex((CFMutableArrayRef)targetRow, i, [SPNotLoaded notLoaded]);
@synchronized(self) {
[self _assesUnloadedColumnsIsSet];
for (NSUInteger i = 0; i < numberOfColumns; i++) {
if (unloadedColumns[i]) {
CFArraySetValueAtIndex((CFMutableArrayRef)targetRow, i, [SPNotLoaded notLoaded]);
}
}
}
}
@@ -397,8 +420,10 @@ - (void) setColumnAsUnloaded:(NSUInteger)columnIndex
if (columnIndex >= numberOfColumns) {
[NSException raise:NSRangeException format:@"Invalid column set as unloaded; requested column index (%llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns];
}
NSAssert(unloadedColumns != NULL, @"unloadedColumns not loaded!");
unloadedColumns[columnIndex] = YES;
@synchronized(self) {
[self _assesUnloadedColumnsIsSet];
unloadedColumns[columnIndex] = YES;
}
}
#pragma mark - Basic information
@@ -451,15 +476,29 @@ - (id) init {
numberOfColumns = 0;
editedRowCount = 0;
_debugInfo = nil;
_debugTime = mach_absolute_time();
}
return self;
}
- (void) dealloc {
SPClear(dataStorage);
SPClear(editedRows);
if (unloadedColumns) free(unloadedColumns), unloadedColumns = NULL;
@synchronized(self) {
if (unloadedColumns) {
[self _recordClearingUnloadedColumnsAt:mach_absolute_time() from:[NSThread callStackSymbols]];
free(unloadedColumns), unloadedColumns = NULL;
}
}
// this is very very unlikely, but if another thread had been waiting on the lock
// right before we free'd unloadedColumns, it should get it before we can release
// _debugInfo, too.
@synchronized(self) {
SPClear(_debugInfo);
}
[super dealloc];
}
@@ -474,5 +513,37 @@ - (void) _checkNewRow:(NSMutableArray *)aRow
}
}
// DO NOT CALL THIS METHOD UNLESS YOU CURRENTLY HAVE A LOCK ON SELF!!!
- (void)_recordClearingUnloadedColumnsAt:(uint64_t)now from:(NSArray *)callStack
{
_debugTime = now;
SPClear(_debugInfo);
_debugInfo = [[NSString alloc] initWithFormat:@"Thread: %@, Stack: %@",[NSThread currentThread],callStack];
}
// DO NOT CALL THIS METHOD UNLESS YOU CURRENTLY HAVE A LOCK ON SELF!!!
- (void)_assesUnloadedColumnsIsSet
{
if(unloadedColumns != NULL)
return;
uint64_t timeDiff = _elapsedMilliSecondsSinceAbsoluteTime(_debugTime);
NSString *msg;
if(!_debugInfo)
msg = [NSString stringWithFormat:@"unloadedColumns is not set and never has been since the object was created %llums ago.",timeDiff];
else
msg = [NSString stringWithFormat:@"unloadedColumns was last cleared %llums ago at %@",timeDiff,_debugInfo];
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:msg userInfo:nil];
}
@end
static uint64_t _elapsedMilliSecondsSinceAbsoluteTime(uint64_t comparisonTime)
{
uint64_t elapsedTime_t = mach_absolute_time() - comparisonTime;
Nanoseconds elapsedTime = AbsoluteToNanoseconds(*(AbsoluteTime *)&(elapsedTime_t));
return (UnsignedWideToUInt64(elapsedTime) / 1000000ULL);
}

0 comments on commit 80f8cae

Please sign in to comment.