Skip to content
This repository has been archived by the owner on Mar 9, 2022. It is now read-only.

Commit

Permalink
More change-tracker cleanup
Browse files Browse the repository at this point in the history
* Remove remaining support for continuous feed.
* Instantiate TDConnectionChangeTracker directly instead of having TDChangeTracker act as a class-cluster.
* Bump version number to 0.77
  • Loading branch information
snej committed May 25, 2012
1 parent f9b2085 commit b44e545
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 89 deletions.
8 changes: 3 additions & 5 deletions Source/ChangeTracker/TDChangeTracker.h
Expand Up @@ -26,12 +26,12 @@

typedef enum TDChangeTrackerMode {
kOneShot,
kLongPoll,
kContinuous
kLongPoll
} TDChangeTrackerMode;


/** Reads the continuous-mode _changes feed of a database, and sends the individual change entries to its client's -changeTrackerReceivedChange:. */
/** Reads the continuous-mode _changes feed of a database, and sends the individual change entries to its client's -changeTrackerReceivedChange:.
This class is abstract. Instantiate TDConnectionChangeTracker instead. */
@interface TDChangeTracker : NSObject <NSStreamDelegate>
{
@protected
Expand Down Expand Up @@ -74,8 +74,6 @@ typedef enum TDChangeTrackerMode {
// Protected
@property (readonly) NSString* changesFeedPath;
- (void) setUpstreamError: (NSString*)message;
- (BOOL) receivedChange: (NSDictionary*)change;
- (BOOL) receivedChunk: (NSData*)chunk;
- (NSInteger) receivedPollResponse: (NSData*)body;
- (void) stopped; // override this

Expand Down
23 changes: 1 addition & 22 deletions Source/ChangeTracker/TDChangeTracker.m
Expand Up @@ -43,18 +43,9 @@ - (id)initWithDatabaseURL: (NSURL*)databaseURL
client: (id<TDChangeTrackerClient>)client {
NSParameterAssert(databaseURL);
NSParameterAssert(client);
Assert([self class] != [TDChangeTracker class]); // abstract!
self = [super init];
if (self) {
if ([self class] == [TDChangeTracker class]) {
// TDChangeTracker is abstract -- instantiate concrete subclass instead:
[self release];
return [[TDConnectionChangeTracker alloc] initWithDatabaseURL: databaseURL
mode: mode
conflicts: includeConflicts
lastSequence: lastSequenceID
client: client];
}

_databaseURL = [databaseURL retain];
_client = client;
_mode = mode;
Expand Down Expand Up @@ -151,18 +142,6 @@ - (BOOL) receivedChange: (NSDictionary*)change {
return YES;
}

- (BOOL) receivedChunk: (NSData*)chunk {
LogTo(ChangeTrackerVerbose, @"CHUNK: %@ %@", self, [chunk my_UTF8ToString]);
if (chunk.length > 1) {
id change = [TDJSON JSONObjectWithData: chunk options: 0 error: NULL];
if (![self receivedChange: change]) {
Warn(@"Received unparseable change line from server: %@", [chunk my_UTF8ToString]);
return NO;
}
}
return YES;
}

- (NSInteger) receivedPollResponse: (NSData*)body {
if (!body)
return -1;
Expand Down
55 changes: 15 additions & 40 deletions Source/ChangeTracker/TDConnectionChangeTracker.m
Expand Up @@ -24,10 +24,6 @@ @implementation TDConnectionChangeTracker

- (BOOL) start {
[super start];
// For some reason continuous mode doesn't work with CFNetwork.
if (_mode == kContinuous)
_mode = kLongPoll;

_inputBuffer = [[NSMutableData alloc] init];

NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL: self.changesFeedURL];
Expand Down Expand Up @@ -81,23 +77,6 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
LogTo(ChangeTrackerVerbose, @"%@: Got %lu bytes", self, (unsigned long)data.length);
[_inputBuffer appendData: data];

if (_mode == kContinuous) {
// In continuous mode, break input into lines and parse each as JSON:
for (;;) {
const char* start = _inputBuffer.bytes;
const char* eol = memchr(start, '\n', _inputBuffer.length);
if (!eol)
break; // Wait till we have a complete line
ptrdiff_t lineLength = eol - start;
NSData* chunk = [[[NSData alloc] initWithBytes: start
length: lineLength] autorelease];
[_inputBuffer replaceBytesInRange: NSMakeRange(0, lineLength + 1)
withBytes: NULL length: 0];
// Finally! Send the line to the database to parse:
[self receivedChunk: chunk];
}
}
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
Expand All @@ -107,26 +86,22 @@ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)err
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (_mode != kContinuous) {
// In non-continuous mode, now parse the entire response as a JSON document:
NSData* input = [_inputBuffer retain];
LogTo(ChangeTracker, @"%@: Got entire body, %u bytes", self, (unsigned)input.length);
NSInteger numChanges = [self receivedPollResponse: input];
if (numChanges < 0)
[self setUpstreamError: @"Unparseable server response"];
[input release];

[self clearConnection];

// Poll again if there was no error, and either we're in longpoll mode or it looks like we
// ran out of changes due to a _limit rather than because we hit the end.
if (numChanges > 0 && (_mode == kLongPoll || numChanges == (NSInteger)_limit))
[self start]; // Next poll...
else
[self stopped];
} else {
// Now parse the entire response as a JSON document:
NSData* input = [_inputBuffer retain];
LogTo(ChangeTracker, @"%@: Got entire body, %u bytes", self, (unsigned)input.length);
NSInteger numChanges = [self receivedPollResponse: input];
if (numChanges < 0)
[self setUpstreamError: @"Unparseable server response"];
[input release];

[self clearConnection];

// Poll again if there was no error, and either we're in longpoll mode or it looks like we
// ran out of changes due to a _limit rather than because we hit the end.
if (numChanges > 0 && (_mode == kLongPoll || numChanges == (NSInteger)_limit))
[self start]; // Next poll...
else
[self stopped];
}
}

@end
8 changes: 4 additions & 4 deletions Source/TDChangeTracker_Tests.m
Expand Up @@ -17,7 +17,7 @@
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

#import "TDChangeTracker.h"
#import "TDConnectionChangeTracker.h"
#import "TDInternal.h"
#import "Test.h"
#import "MYURLUtils.h"
Expand Down Expand Up @@ -86,7 +86,7 @@ static void addTemporaryCredential(NSURL* url, NSString* realm,
TestCase(TDChangeTracker) {
TDChangeTrackerTester* tester = [[[TDChangeTrackerTester alloc] init] autorelease];
NSURL* url = [NSURL URLWithString: @"http://snej.iriscouch.com/tdpuller_test1"];
TDChangeTracker* tracker = [[[TDChangeTracker alloc] initWithDatabaseURL: url mode:kContinuous conflicts: NO lastSequence: nil client: tester] autorelease];
TDChangeTracker* tracker = [[[TDConnectionChangeTracker alloc] initWithDatabaseURL: url mode: kOneShot conflicts: NO lastSequence: nil client: tester] autorelease];
NSArray* expected = $array($dict({@"seq", $object(1)},
{@"id", @"foo"},
{@"changes", $array($dict({@"rev", @"5-ca289aa53cbbf35a5f5c799b64b1f16f"}))}),
Expand All @@ -108,7 +108,7 @@ static void addTemporaryCredential(NSURL* url, NSString* realm,
// The only difference here is the "https:" scheme in the URL.
TDChangeTrackerTester* tester = [[[TDChangeTrackerTester alloc] init] autorelease];
NSURL* url = [NSURL URLWithString: @"https://snej.iriscouch.com/tdpuller_test1"];
TDChangeTracker* tracker = [[[TDChangeTracker alloc] initWithDatabaseURL: url mode:kContinuous conflicts: NO lastSequence: 0 client: tester] autorelease];
TDChangeTracker* tracker = [[[TDConnectionChangeTracker alloc] initWithDatabaseURL: url mode: kOneShot conflicts: NO lastSequence: 0 client: tester] autorelease];
NSArray* expected = $array($dict({@"seq", $object(1)},
{@"id", @"foo"},
{@"changes", $array($dict({@"rev", @"5-ca289aa53cbbf35a5f5c799b64b1f16f"}))}),
Expand All @@ -132,7 +132,7 @@ static void addTemporaryCredential(NSURL* url, NSString* realm,
NSURL* url = [NSURL URLWithString: @"https://dummy@snej.iriscouch.com/tdpuller_test2_auth"];
addTemporaryCredential(url, @"snejdom", @"dummy", @"dummy");

TDChangeTracker* tracker = [[[TDChangeTracker alloc] initWithDatabaseURL: url mode:kContinuous conflicts: NO lastSequence: 0 client: tester] autorelease];
TDChangeTracker* tracker = [[[TDConnectionChangeTracker alloc] initWithDatabaseURL: url mode: kOneShot conflicts: NO lastSequence: 0 client: tester] autorelease];
NSArray* expected = $array($dict({@"seq", $object(1)},
{@"id", @"something"},
{@"changes", $array($dict({@"rev", @"1-967a00dff5e02add41819138abb3284d"}))}) );
Expand Down
14 changes: 7 additions & 7 deletions Source/TDPuller.h
Expand Up @@ -17,13 +17,13 @@
@private
TDChangeTracker* _changeTracker;
NSString* _endingSequence; // Where to stop in noncontinuous pull
NSMutableArray* _seenSequences;
TDSequenceMap* _pendingSequences;
NSMutableArray* _revsToPull;
NSMutableArray* _deletedRevsToPull;
NSMutableArray* _bulkRevsToPull;
NSUInteger _httpConnectionCount;
TDBatcher* _downloadsToInsert;
NSMutableArray* _seenSequences; // Seq IDs received before _endingSequence is known
TDSequenceMap* _pendingSequences; // Received but not yet copied into local DB
NSMutableArray* _revsToPull; // Queue of TDPulledRevisions to download
NSMutableArray* _deletedRevsToPull; // Separate lower-priority of deleted TDPulledRevisions
NSMutableArray* _bulkRevsToPull; // TDPulledRevisions that can be fetched in bulk
NSUInteger _httpConnectionCount; // Number of active NSURLConnections
TDBatcher* _downloadsToInsert; // Queue of TDPulledRevisions, with bodies, to insert in DB
}

@end
Expand Down
16 changes: 7 additions & 9 deletions Source/TDPuller.m
Expand Up @@ -17,7 +17,7 @@
#import "TDDatabase+Insertion.h"
#import "TDDatabase+Replication.h"
#import <TouchDB/TDRevision.h>
#import "TDChangeTracker.h"
#import "TDConnectionChangeTracker.h"
#import "TDAuthorizer.h"
#import "TDBatcher.h"
#import "TDMultipartDownloader.h"
Expand All @@ -40,11 +40,9 @@


@interface TDPuller () <TDChangeTrackerClient>
- (void) pullRemoteRevisions;
- (void) pullRemoteRevision: (TDRevision*)rev;
- (void) insertDownloads: (NSArray*)downloads;
@end


static NSString* joinQuotedEscaped(NSArray* strings);


Expand Down Expand Up @@ -102,11 +100,11 @@ - (void) startChangeTracker {
TDChangeTrackerMode mode = _continuous ? kLongPoll : kOneShot;

LogTo(SyncVerbose, @"%@ starting ChangeTracker: mode=%d, since=%@", self, mode, _lastSequence);
_changeTracker = [[TDChangeTracker alloc] initWithDatabaseURL: _remote
mode: mode
conflicts: YES
lastSequence: _lastSequence
client: self];
_changeTracker = [[TDConnectionChangeTracker alloc] initWithDatabaseURL: _remote
mode: mode
conflicts: YES
lastSequence: _lastSequence
client: self];
// Limit the number of changes to return, so we can parse the feed in parts:
_changeTracker.limit = kChangesFeedLimit;
_changeTracker.filterName = _filterName;
Expand Down
4 changes: 2 additions & 2 deletions TouchDB.xcodeproj/project.pbxproj
Expand Up @@ -2264,7 +2264,7 @@
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CURRENT_PROJECT_VERSION = 0.76;
CURRENT_PROJECT_VERSION = 0.77;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
Expand All @@ -2285,7 +2285,7 @@
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CURRENT_PROJECT_VERSION = 0.76;
CURRENT_PROJECT_VERSION = 0.77;
GCC_C_LANGUAGE_STANDARD = c99;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
Expand Down

0 comments on commit b44e545

Please sign in to comment.