Skip to content

Commit

Permalink
CouchReplication now supports filters
Browse files Browse the repository at this point in the history
Also changed the CouchDatabase API for creating it -- the options are no longer passed in; instead you set them as properties afterwards.
To make this work I had to delay the call to -start so that the caller would have a chance to make these changes first.

Change-Id: I54ee42e6224607fb1be912dd4b18297d4ddb4aaf
  • Loading branch information
snej committed Jan 30, 2012
1 parent 428107c commit 039f264
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 42 deletions.
12 changes: 4 additions & 8 deletions Couch/CouchDatabase.h
Expand Up @@ -139,17 +139,13 @@ typedef NSString* (^CouchDocumentPathMap)(NSString* documentID);

/** Triggers replication from a source database, to this database.
@param sourceURL The URL of the database to replicate from.
@param options Zero or more option flags affecting the replication.
@return The CouchReplication object managing the replication. It will already have been started. */
- (CouchReplication*) pullFromDatabaseAtURL: (NSURL*)sourceURL
options: (CouchReplicationOptions)options;
@return The CouchReplication object managing the replication. You have a chance to customize its properties (like .continuous and .filter) before it starts. */
- (CouchReplication*) pullFromDatabaseAtURL: (NSURL*)sourceURL;

/** Triggers replication from this database to a target database.
@param targetURL The URL of the database to replicate to.
@param options Zero or more option flags affecting the replication.
@return The CouchReplication object managing the replication. It will already have been started. */
- (CouchReplication*) pushToDatabaseAtURL: (NSURL*)targetURL
options: (CouchReplicationOptions)options;
@return The CouchReplication object managing the replication. You have a chance to customize its properties (like .continuous and .filter) before it starts.*/
- (CouchReplication*) pushToDatabaseAtURL: (NSURL*)targetURL;

/** Configures this database to replicate bidirectionally (sync to and from) a database at the given URL.
@param otherURL The URL of the other database, or nil to indicate no replication.
Expand Down
19 changes: 5 additions & 14 deletions Couch/CouchDatabase.m
Expand Up @@ -296,24 +296,15 @@ - (CouchQuery*) slowQueryWithMap: (NSString*)map {
#pragma mark -
#pragma mark REPLICATION & SYNCHRONIZATION

- (CouchReplication*) pullFromDatabaseAtURL: (NSURL*)sourceURL
options: (CouchReplicationOptions)options {
CouchReplication* rep = [[[CouchReplication alloc] initWithDatabase: self
remote: sourceURL
pull: YES
options: options] autorelease];
[rep start];
- (CouchReplication*) pullFromDatabaseAtURL: (NSURL*)sourceURL {
CouchReplication* rep = [self pushToDatabaseAtURL: sourceURL];
rep.pull = YES;
return rep;
}

- (CouchReplication*) pushToDatabaseAtURL: (NSURL*)targetURL
options: (CouchReplicationOptions)options {
CouchReplication* rep = [[[CouchReplication alloc] initWithDatabase: self
remote: targetURL
pull: NO
options: options] autorelease];
[rep start];
return rep;
{
return [[[CouchReplication alloc] initWithDatabase: self remote: targetURL] autorelease];
}


Expand Down
5 changes: 2 additions & 3 deletions Couch/CouchInternal.h
Expand Up @@ -70,10 +70,9 @@ typedef void (^OnDatabaseChangeBlock)(CouchDocument*, BOOL externalChange);


@interface CouchReplication ()
@property (nonatomic, readwrite) bool pull;
- (id) initWithDatabase: (CouchDatabase*)database
remote: (NSURL*)remote
pull: (BOOL)pull
options: (CouchReplicationOptions)options;
remote: (NSURL*)remote;
@end


Expand Down
32 changes: 22 additions & 10 deletions Couch/CouchReplication.h
Expand Up @@ -18,28 +18,37 @@
@class CouchDatabase, RESTOperation;


/** Option flags for replication (push/pull). */
enum {
kCouchReplicationCreateTarget = 1, /**< Create the destination database if it doesn't exist */
kCouchReplicationContinuous = 2, /**< Continuous mode; remains active till canceled */
};
typedef NSUInteger CouchReplicationOptions;


/** Tracks a CouchDB replication. Can be used to observe its progress. */
@interface CouchReplication : NSObject
{
CouchDatabase* _database;
NSURL* _remote;
BOOL _pull;
CouchReplicationOptions _options;
bool _pull, _createTarget, _continuous;
NSString* _filter;
NSDictionary* _filterParams;
BOOL _running;
NSString* _taskID;
NSString* _status;
unsigned _completed, _total;
NSError* _error;
}

/** Should the target database be created if it doesn't already exist? (Defaults to NO). */
@property (nonatomic) bool createTarget;

/** Should the replication operate continuously, copying changes as soon as the source database is modified? (Defaults to NO). */
@property (nonatomic) bool continuous;

/** Path of an optional filter function to run on the source server.
Only documents for which the function returns true are replicated.
The path looks like "designdocname/filtername". */
@property (nonatomic, copy) NSString* filter;

/** Parameters to pass to the filter function.
Should be a JSON-compatible dictionary. */
@property (nonatomic, copy) NSDictionary* filterParams;


/** Starts the replication, asynchronously.
@return The operation to start replication, or nil if replication is already started. */
- (RESTOperation*) start;
Expand All @@ -49,6 +58,9 @@ typedef NSUInteger CouchReplicationOptions;

@property (nonatomic, readonly) NSURL* remoteURL;

/** Does the replication pull from (as opposed to push to) the target? */
@property (nonatomic, readonly) bool pull;

@property (nonatomic, readonly) BOOL running;

/** The current status string from the server, if active, else nil (observable).
Expand Down
24 changes: 17 additions & 7 deletions Couch/CouchReplication.m
Expand Up @@ -38,17 +38,15 @@ @implementation CouchReplication

- (id) initWithDatabase: (CouchDatabase*)database
remote: (NSURL*)remote
pull: (BOOL)pull
options: (CouchReplicationOptions)options
{
NSParameterAssert(remote);
self = [super init];
if (self) {
_database = [database retain];
_remote = [remote retain];
_pull = pull;
_options = options;

// Give the caller a chance to customize parameters like .filter before calling -start,
// but make sure -start will be run even if the caller doesn't call it.
[self performSelector: @selector(start) withObject: nil afterDelay: 0.0];
}
return self;
}
Expand All @@ -59,6 +57,8 @@ - (void)dealloc {
[_remote release];
[_database release];
[_error release];
[_filter release];
[_filterParams release];
[super dealloc];
}

Expand All @@ -69,17 +69,26 @@ - (NSString*) description {
}


@synthesize pull=_pull, createTarget=_createTarget, continuous=_continuous,
filter=_filter, filterParams=_filterParams;


- (RESTOperation*) operationToStart: (BOOL)start {
NSString* source = _pull ? _remote.absoluteString : _database.relativePath;
NSString* target = _pull ? _database.relativePath : _remote.absoluteString;
NSMutableDictionary* body = [NSMutableDictionary dictionaryWithObjectsAndKeys:
source, @"source",
target, @"target",
nil];
if (_options & kCouchReplicationCreateTarget)
if (_createTarget)
[body setObject: (id)kCFBooleanTrue forKey: @"create_target"];
if (_options & kCouchReplicationContinuous)
if (_continuous)
[body setObject: (id)kCFBooleanTrue forKey: @"continuous"];
if (_filter) {
[body setObject: _filter forKey: @"filter"];
if (_filterParams)
[body setObject: _filterParams forKey: @"query_params"];
}
if (!start)
[body setObject: (id)kCFBooleanTrue forKey: @"cancel"];
RESTResource* replicate = [[[RESTResource alloc] initWithParent: _database.server
Expand All @@ -89,6 +98,7 @@ - (RESTOperation*) operationToStart: (BOOL)start {


- (RESTOperation*) start {
[NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(start) object: nil];
if (_running)
return nil;
self.error = nil;
Expand Down

0 comments on commit 039f264

Please sign in to comment.