aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/SPMySQLFramework/Source/SPMySQLStreamingResultStore.m
diff options
context:
space:
mode:
Diffstat (limited to 'Frameworks/SPMySQLFramework/Source/SPMySQLStreamingResultStore.m')
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQLStreamingResultStore.m243
1 files changed, 121 insertions, 122 deletions
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLStreamingResultStore.m b/Frameworks/SPMySQLFramework/Source/SPMySQLStreamingResultStore.m
index 1a0b6b25..fdabe2e2 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQLStreamingResultStore.m
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQLStreamingResultStore.m
@@ -672,148 +672,147 @@ static inline void SPMySQLStreamingResultStoreFreeRowData(SPMySQLStreamingResult
*/
- (void)_downloadAllData
{
- NSAutoreleasePool *downloadPool = [[NSAutoreleasePool alloc] init];
- MYSQL_ROW theRow;
- unsigned long *fieldLengths;
- NSUInteger i, dataCopiedLength, rowDataLength;
- SPMySQLStreamingResultStoreRowData *newRowStore;
-
- [[NSThread currentThread] setName:@"SPMySQLStreamingResultStore data download thread"];
-
- size_t sizeOfMetadata, lengthOfMetadata;
- size_t lengthOfNullRecords = (size_t)(sizeof(BOOL) * numberOfFields);
- size_t sizeOfChar = sizeof(char);
-
- // Loop through the rows until the end of the data is reached - indicated via a NULL
- while (
- (*isConnectedPtr)(parentConnection, isConnectedSelector)
- && (theRow = mysql_fetch_row(resultSet))
- ) {
- // If the load has been cancelled, skip any processing - we're only interested
- // in ensuring that mysql_fetch_row is called for all rows.
- if (loadCancelled) {
- continue;
- }
+ @autoreleasepool {
+ MYSQL_ROW theRow;
+ unsigned long *fieldLengths;
+ NSUInteger i, dataCopiedLength, rowDataLength;
+ SPMySQLStreamingResultStoreRowData *newRowStore;
+
+ [[NSThread currentThread] setName:@"SPMySQLStreamingResultStore data download thread"];
+
+ size_t sizeOfMetadata, lengthOfMetadata;
+ size_t lengthOfNullRecords = (size_t)(sizeof(BOOL) * numberOfFields);
+ size_t sizeOfChar = sizeof(char);
+
+ // Loop through the rows until the end of the data is reached - indicated via a NULL
+ while (
+ (*isConnectedPtr)(parentConnection, isConnectedSelector)
+ && (theRow = mysql_fetch_row(resultSet))
+ ) {
+ // If the load has been cancelled, skip any processing - we're only interested
+ // in ensuring that mysql_fetch_row is called for all rows.
+ if (loadCancelled) {
+ continue;
+ }
- // The row store is a single block of memory. It's made up of four blocks of data:
- // Firstly, a single char containing the type of data used to store positions.
- // Secondly, a series of those types recording the *end position* of each field
- // Thirdly, a series of BOOLs recording whether the fields are NULLS - which can't just be from length
- // Finally, a char sequence comprising the actual cell data, which can be looked up by position/length.
-
- // Retrieve the lengths of the returned data, and calculate the overall length of data
- fieldLengths = mysql_fetch_lengths(resultSet);
- rowDataLength = 0;
- for (i = 0; i < numberOfFields; i++) {
- rowDataLength += fieldLengths[i];
- }
+ // The row store is a single block of memory. It's made up of four blocks of data:
+ // Firstly, a single char containing the type of data used to store positions.
+ // Secondly, a series of those types recording the *end position* of each field
+ // Thirdly, a series of BOOLs recording whether the fields are NULLS - which can't just be from length
+ // Finally, a char sequence comprising the actual cell data, which can be looked up by position/length.
- // Depending on the length of the row, vary the metadata size appropriately. This
- // makes defining the data processing much lengthier, but is worth it to reduce the
- // overhead for small rows.
- if (rowDataLength <= UCHAR_MAX) {
- sizeOfMetadata = SPMySQLStoreMetadataAsChar;
- } else if (rowDataLength <= USHRT_MAX) {
- sizeOfMetadata = SPMySQLStoreMetadataAsShort;
- } else {
- sizeOfMetadata = SPMySQLStoreMetadataAsLong;
- }
- lengthOfMetadata = sizeOfMetadata * numberOfFields;
+ // Retrieve the lengths of the returned data, and calculate the overall length of data
+ fieldLengths = mysql_fetch_lengths(resultSet);
+ rowDataLength = 0;
+ for (i = 0; i < numberOfFields; i++) {
+ rowDataLength += fieldLengths[i];
+ }
- // Allocate the memory for the row and set the type marker
- newRowStore = malloc_zone_malloc(storageMallocZone, 1 + lengthOfMetadata + lengthOfNullRecords + (rowDataLength * sizeOfChar));
- newRowStore[0] = sizeOfMetadata;
+ // Depending on the length of the row, vary the metadata size appropriately. This
+ // makes defining the data processing much lengthier, but is worth it to reduce the
+ // overhead for small rows.
+ if (rowDataLength <= UCHAR_MAX) {
+ sizeOfMetadata = SPMySQLStoreMetadataAsChar;
+ } else if (rowDataLength <= USHRT_MAX) {
+ sizeOfMetadata = SPMySQLStoreMetadataAsShort;
+ } else {
+ sizeOfMetadata = SPMySQLStoreMetadataAsLong;
+ }
+ lengthOfMetadata = sizeOfMetadata * numberOfFields;
+
+ // Allocate the memory for the row and set the type marker
+ newRowStore = malloc_zone_malloc(storageMallocZone, 1 + lengthOfMetadata + lengthOfNullRecords + (rowDataLength * sizeOfChar));
+ newRowStore[0] = sizeOfMetadata;
+
+ // Set the data end positions. Manually unroll the logic for the different cases; messy
+ // but again worth the large memory savings for smaller rows
+ rowDataLength = 0;
+ switch (sizeOfMetadata) {
+ case SPMySQLStoreMetadataAsLong:
+ for (i = 0; i < numberOfFields; i++) {
+ rowDataLength += fieldLengths[i];
+ ((unsigned long *)(newRowStore + 1))[i] = rowDataLength;
+ ((BOOL *)(newRowStore + 1 + lengthOfMetadata))[i] = (theRow[i] == NULL);
+ }
+ break;
+ case SPMySQLStoreMetadataAsShort:
+ for (i = 0; i < numberOfFields; i++) {
+ rowDataLength += fieldLengths[i];
+ ((unsigned short *)(newRowStore + 1))[i] = rowDataLength;
+ ((BOOL *)(newRowStore + 1 + lengthOfMetadata))[i] = (theRow[i] == NULL);
+ }
+ break;
+ case SPMySQLStoreMetadataAsChar:
+ for (i = 0; i < numberOfFields; i++) {
+ rowDataLength += fieldLengths[i];
+ ((unsigned char *)(newRowStore + 1))[i] = rowDataLength;
+ ((BOOL *)(newRowStore + 1 + lengthOfMetadata))[i] = (theRow[i] == NULL);
+ }
+ break;
+ }
- // Set the data end positions. Manually unroll the logic for the different cases; messy
- // but again worth the large memory savings for smaller rows
- rowDataLength = 0;
- switch (sizeOfMetadata) {
- case SPMySQLStoreMetadataAsLong:
- for (i = 0; i < numberOfFields; i++) {
- rowDataLength += fieldLengths[i];
- ((unsigned long *)(newRowStore + 1))[i] = rowDataLength;
- ((BOOL *)(newRowStore + 1 + lengthOfMetadata))[i] = (theRow[i] == NULL);
- }
- break;
- case SPMySQLStoreMetadataAsShort:
- for (i = 0; i < numberOfFields; i++) {
- rowDataLength += fieldLengths[i];
- ((unsigned short *)(newRowStore + 1))[i] = rowDataLength;
- ((BOOL *)(newRowStore + 1 + lengthOfMetadata))[i] = (theRow[i] == NULL);
- }
- break;
- case SPMySQLStoreMetadataAsChar:
+ // If the row has content, copy it in
+ if (rowDataLength) {
+ dataCopiedLength = 1 + lengthOfMetadata + lengthOfNullRecords;
for (i = 0; i < numberOfFields; i++) {
- rowDataLength += fieldLengths[i];
- ((unsigned char *)(newRowStore + 1))[i] = rowDataLength;
- ((BOOL *)(newRowStore + 1 + lengthOfMetadata))[i] = (theRow[i] == NULL);
- }
- break;
- }
-
- // If the row has content, copy it in
- if (rowDataLength) {
- dataCopiedLength = 1 + lengthOfMetadata + lengthOfNullRecords;
- for (i = 0; i < numberOfFields; i++) {
- if (theRow[i] != NULL) {
- memcpy(newRowStore + dataCopiedLength, theRow[i], fieldLengths[i]);
- dataCopiedLength += fieldLengths[i];
+ if (theRow[i] != NULL) {
+ memcpy(newRowStore + dataCopiedLength, theRow[i], fieldLengths[i]);
+ dataCopiedLength += fieldLengths[i];
+ }
}
}
- }
- // Lock the data mutex
- pthread_mutex_lock(&dataLock);
+ // Lock the data mutex
+ pthread_mutex_lock(&dataLock);
- // Ensure that sufficient capacity is available
- SPMySQLStreamingResultStoreEnsureCapacityForAdditionalRowCount(self, 1);
+ // Ensure that sufficient capacity is available
+ SPMySQLStreamingResultStoreEnsureCapacityForAdditionalRowCount(self, 1);
- // Add the newly allocated row to the storage
- if (rowDownloadIterator < numberOfRows) {
- SPMySQLStreamingResultStoreFreeRowData(dataStorage[rowDownloadIterator]);
- }
- dataStorage[rowDownloadIterator] = newRowStore;
- rowDownloadIterator++;
+ // Add the newly allocated row to the storage
+ if (rowDownloadIterator < numberOfRows) {
+ SPMySQLStreamingResultStoreFreeRowData(dataStorage[rowDownloadIterator]);
+ }
+ dataStorage[rowDownloadIterator] = newRowStore;
+ rowDownloadIterator++;
- // Update the total row count if exceeded
- if (rowDownloadIterator > numberOfRows) {
- numberOfRows++;
- }
+ // Update the total row count if exceeded
+ if (rowDownloadIterator > numberOfRows) {
+ numberOfRows++;
+ }
- // Unlock the mutex
- pthread_mutex_unlock(&dataLock);
- }
+ // Unlock the mutex
+ pthread_mutex_unlock(&dataLock);
+ }
- // Update the total number of rows in the result set now download
- // is complete, freeing extra rows from a previous result set
- if (numberOfRows > rowDownloadIterator) {
- pthread_mutex_lock(&dataLock);
- while (numberOfRows > rowDownloadIterator) {
- SPMySQLStreamingResultStoreFreeRowData(dataStorage[--numberOfRows]);
+ // Update the total number of rows in the result set now download
+ // is complete, freeing extra rows from a previous result set
+ if (numberOfRows > rowDownloadIterator) {
+ pthread_mutex_lock(&dataLock);
+ while (numberOfRows > rowDownloadIterator) {
+ SPMySQLStreamingResultStoreFreeRowData(dataStorage[--numberOfRows]);
+ }
+ pthread_mutex_unlock(&dataLock);
}
- pthread_mutex_unlock(&dataLock);
- }
- // Update the connection's error statuses to reflect any errors during the content download
- [parentConnection _updateLastErrorInfos];
+ // Update the connection's error statuses to reflect any errors during the content download
+ [parentConnection _updateLastErrorInfos];
- // Unlock the parent connection now all data has been retrieved
- [parentConnection _unlockConnection];
- connectionUnlocked = YES;
+ // Unlock the parent connection now all data has been retrieved
+ [parentConnection _unlockConnection];
+ connectionUnlocked = YES;
- // If the connection query may have been cancelled with a query kill, double-check connection
- if ([parentConnection lastQueryWasCancelled] && [parentConnection serverMajorVersion] < 5) {
- [parentConnection checkConnection];
- }
+ // If the connection query may have been cancelled with a query kill, double-check connection
+ if ([parentConnection lastQueryWasCancelled] && [parentConnection serverMajorVersion] < 5) {
+ [parentConnection checkConnection];
+ }
- dataDownloaded = YES;
+ dataDownloaded = YES;
- // Inform the delegate the download was completed
- if ([delegate respondsToSelector:@selector(resultStoreDidFinishLoadingData:)]) {
- [delegate resultStoreDidFinishLoadingData:self];
+ // Inform the delegate the download was completed
+ if ([delegate respondsToSelector:@selector(resultStoreDidFinishLoadingData:)]) {
+ [delegate resultStoreDidFinishLoadingData:self];
+ }
}
-
- [downloadPool drain];
}
/**