Skip to content

Commit 4864400

Browse files
committed
CBL-6907: add Start and Stop Listener API
Also, some thread safety in TestContext
1 parent 6ee096c commit 4864400

11 files changed

Lines changed: 264 additions & 128 deletions

File tree

File renamed without changes.

servers/jak/android/app/build.gradle

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ plugins {
2222

2323
ext {
2424
SERVER_VERSION = file("${ROOT_DIR}/version.txt").text.trim()
25-
SERVER_BUILD = "${getBuildId()}"
25+
SERVER_BUILD = "${getBuildId()}"
2626

2727
SPOTBUGS_VERSION = '4.7.3'
2828

@@ -36,13 +36,17 @@ ext {
3636
}
3737

3838
def COUCHBASE_LITE_VERSION = project.hasProperty("cblVersion") ? cblVersion : ""
39-
if (!(COUCHBASE_LITE_VERSION =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}([ab.]\d)?-/)) { throw new InvalidUserDataException ("!!! Bad Couchbase version: ${COUCHBASE_LITE_VERSION}") }
39+
if (!(COUCHBASE_LITE_VERSION =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}([ab.]\d)?-/)) {
40+
throw new InvalidUserDataException("!!! Bad Couchbase version: ${COUCHBASE_LITE_VERSION}")
41+
}
4042

4143
// If it is a snapshot, it is in maven local
4244
def USE_LOCAL_MAVEN = COUCHBASE_LITE_VERSION.endsWith("SNAPSHOT")
4345

4446
def DATASET_VERSION = project.hasProperty("datasetVersion") ? datasetVersion : ""
45-
if (!(DATASET_VERSION =~ /^\d{1,2}\.\d{1,2}/)) { throw new InvalidUserDataException ("!!! Bad dataset version: ${DATASET_VERSION}") }
47+
if (!(DATASET_VERSION =~ /^\d{1,2}\.\d{1,2}/)) {
48+
throw new InvalidUserDataException("!!! Bad dataset version: ${DATASET_VERSION}")
49+
}
4650
def ASSETS_DIR = "${ASSETS_ROOT}/${DATASET_VERSION}"
4751

4852
println "Building test server ${SERVER_VERSION}@${SERVER_BUILD} for CBL Android ${COUCHBASE_LITE_VERSION} with ${DATASET_VERSION} data"
@@ -126,7 +130,10 @@ android {
126130
repositories {
127131
if (USE_LOCAL_MAVEN) { mavenLocal() }
128132
else {
129-
maven { url 'https://proget.sc.couchbase.com/maven2/internalmaven' }
133+
maven {
134+
url 'https://proget.sc.couchbase.com/maven2/internalmaven'
135+
content { includeGroupByRegex "com\\.couchbase\\.lite.*" }
136+
}
130137
}
131138

132139
// Home of NanoHTTP
@@ -136,7 +143,6 @@ repositories {
136143
mavenCentral()
137144
}
138145

139-
configurations.all { resolutionStrategy.cacheChangingModulesFor 1, 'seconds' }
140146
dependencies {
141147
compileOnly "com.github.spotbugs:spotbugs-annotations:${SPOTBUGS_VERSION}"
142148

@@ -154,7 +160,7 @@ dependencies {
154160

155161
implementation 'org.nanohttpd:nanohttpd:2.3.2-SNAPSHOT'
156162

157-
implementation ("com.couchbase.lite:couchbase-lite-android-ee-ktx:${COUCHBASE_LITE_VERSION}") { changing = true }
163+
implementation "com.couchbase.lite:couchbase-lite-android-ee-ktx:${COUCHBASE_LITE_VERSION}"
158164

159165
testImplementation 'junit:junit:4.13.2'
160166

@@ -287,15 +293,15 @@ def getVersionCode(version) {
287293
def getBuildId() {
288294
def hostname = "rogue"
289295
try { hostname = "hostname".execute().text.trim() }
290-
catch (Exception ignore) { }
296+
catch (Exception ignore) {}
291297

292298
return "${getCommit().substring(0, 10)} on ${hostname}"
293299
}
294300

295301
def getCommit() {
296302
def commit = "unofficial"
297303
try { commit = "git rev-parse HEAD".execute().text.trim() }
298-
catch (Exception ignore) { }
304+
catch (Exception ignore) {}
299305
return commit
300306
}
301307

servers/jak/desktop/app/build.gradle

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,17 @@ ext {
4242
OKHTTP_VERSION = '4.12.0'
4343
}
4444
def COUCHBASE_LITE_VERSION = project.hasProperty("cblVersion") ? cblVersion : ""
45-
if (!(COUCHBASE_LITE_VERSION =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}([ab.]\d)?-/)) { throw new InvalidUserDataException ("!!! Bad Couchbase version: ${COUCHBASE_LITE_VERSION}") }
46-
45+
if (!(COUCHBASE_LITE_VERSION =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}([ab.]\d)?-/)) {
46+
throw new InvalidUserDataException("!!! Bad Couchbase version: ${COUCHBASE_LITE_VERSION}")
47+
}
48+
4749
// If it is a snapshot, it is in maven local
4850
def USE_LOCAL_MAVEN = COUCHBASE_LITE_VERSION.endsWith("SNAPSHOT")
49-
51+
5052
def DATASET_VERSION = project.hasProperty("datasetVersion") ? datasetVersion : ""
51-
if (!(DATASET_VERSION =~ /^\d{1,2}\.\d{1,2}/)) { throw new InvalidUserDataException ("!!! Bad dataset version: ${DATASET_VERSION}") }
53+
if (!(DATASET_VERSION =~ /^\d{1,2}\.\d{1,2}/)) {
54+
throw new InvalidUserDataException("!!! Bad dataset version: ${DATASET_VERSION}")
55+
}
5256
def ASSETS_DIR = "${ASSETS_ROOT}/${DATASET_VERSION}"
5357

5458
// Set -Pverbose to get full console logs for tests

servers/jak/shared/common/main/java/com/couchbase/lite/mobiletest/PostDispatcher.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
import java.io.InputStream;
2323
import java.util.Map;
2424

25+
import com.couchbase.lite.mobiletest.endpoints.v1.EndptListenerManager;
2526
import com.couchbase.lite.mobiletest.endpoints.v1.GetAllDocs;
2627
import com.couchbase.lite.mobiletest.endpoints.v1.GetDocument;
27-
import com.couchbase.lite.mobiletest.endpoints.v1.ListenerManager;
2828
import com.couchbase.lite.mobiletest.endpoints.v1.Logger;
2929
import com.couchbase.lite.mobiletest.endpoints.v1.PerformMaintenance;
3030
import com.couchbase.lite.mobiletest.endpoints.v1.ReplicatorManager;
@@ -73,11 +73,13 @@ public PostDispatcher(@NonNull TestApp app) {
7373
addEndpoint(
7474
1,
7575
"/startListener",
76-
(c, r) -> new ListenerManager(app.getDbSvc(), app.getListenerService()).createListener(app.getSession(c), r));
76+
(c, r) -> new EndptListenerManager(app.getDbSvc(), app.getListenerService())
77+
.startListener(app.getSession(c), r));
7778
addEndpoint(
7879
1,
7980
"/stopListener",
80-
(c, r) -> new ListenerManager(app.getDbSvc(), app.getListenerService()).stopListener(app.getSession(c), r));
81+
(c, r) -> new EndptListenerManager(app.getDbSvc(), app.getListenerService())
82+
.stopListener(app.getSession(c), r));
8183
addEndpoint(1, "/snapshotDocuments", (c, r) -> new SnapshotDocs(app.getDbSvc()).snapshot(app.getSession(c), r));
8284
addEndpoint(1, "/verifyDocuments", (c, r) -> new VerifyDocs(app.getDbSvc()).verify(app.getSession(c), r));
8385
addEndpoint(

servers/jak/shared/common/main/java/com/couchbase/lite/mobiletest/TestContext.java

Lines changed: 96 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,26 @@ public final class TestContext implements AutoCloseable {
4141
@Nullable
4242
private Map<String, Replicator> openRepls;
4343
@Nullable
44-
private Map<String, DocReplListener> openListeners;
44+
private Map<String, DocReplListener> openDocListeners;
4545
@Nullable
4646
private Map<String, Snapshot> openSnapshots;
47+
@Nullable
48+
private Map<String, URLEndpointListener> openEndptListeners;
4749

4850
TestContext(@NonNull String client) { this.client = client; }
4951

5052
@Override
5153
public void close() {
5254
// belt
53-
openListeners = null;
55+
openDocListeners = null;
5456

5557
// ... and suspenders...
5658
openSnapshots = null;
5759

5860
stopRepls();
5961

62+
stopEndptListeners();
63+
6064
closeCollections();
6165

6266
deleteDbs();
@@ -82,107 +86,148 @@ public void setDbDir(@NonNull File dbDir) {
8286
@SuppressFBWarnings("NP_NULL_ON_SOME_PATH")
8387
public void addDb(@NonNull String name, @NonNull Database db) {
8488
Log.p(TAG, "Adding database to context: " + name);
85-
if (openDbs == null) { openDbs = new HashMap<>(); }
86-
if (openDbs.containsKey(name)) { throw new ClientError("Attempt to replace an open database"); }
87-
openDbs.put(name, db);
89+
Map<String, Database> dbs = openDbs;
90+
if (dbs == null) {
91+
dbs = new HashMap<>();
92+
openDbs = dbs;
93+
}
94+
if (dbs.containsKey(name)) { throw new ClientError("Attempt to replace an open database"); }
95+
dbs.put(name, db);
8896
}
8997

9098
@Nullable
91-
public Database getDb(@NonNull String name) { return (openDbs == null) ? null : openDbs.get(name); }
92-
93-
@Nullable
94-
public Database removeDb(@NonNull String name) { return (openDbs == null) ? null : openDbs.remove(name); }
95-
96-
public void addListener(@NonNull String id, @NonNull URLEndpointListener listener) {
97-
// TODO: implement
98-
throw new UnsupportedOperationException("Not implemented");
99-
}
100-
101-
public void removeListener(@NonNull String id) {
102-
// TODO: implement
103-
throw new UnsupportedOperationException("Not implemented");
99+
public Database getDb(@NonNull String name) {
100+
final Map<String, Database> dbs = openDbs;
101+
return (dbs == null) ? null : dbs.get(name);
104102
}
105103

106104
@Nullable
107-
public URLEndpointListener getListener(@NonNull String id) {
108-
// TODO: implement
109-
throw new UnsupportedOperationException("Not implemented");
105+
public Database removeDb(@NonNull String name) {
106+
final Map<String, Database> dbs = openDbs;
107+
return (dbs == null) ? null : dbs.remove(name);
110108
}
111109

112110
@Nullable
113111
public Collection getOpenCollection(@NonNull String collFqn) {
114-
return (openCollections == null) ? null : openCollections.get(collFqn);
112+
final Map<String, Collection> collections = openCollections;
113+
return (collections == null) ? null : collections.get(collFqn);
115114
}
116115

117116
public void addOpenCollection(@NonNull Collection collection) {
118-
if (openCollections == null) { openCollections = new HashMap<>(); }
119-
openCollections.put(DatabaseService.getCollectionFQN(collection), collection);
117+
Map<String, Collection> collections = openCollections;
118+
if (collections == null) {
119+
collections = new HashMap<>();
120+
openCollections = collections;
121+
}
122+
collections.put(DatabaseService.getCollectionFQN(collection), collection);
120123
}
121124

122125
@SuppressFBWarnings("NP_NULL_ON_SOME_PATH")
123126
public void addRepl(@NonNull String id, @NonNull Replicator repl) {
124-
if (openRepls == null) { openRepls = new HashMap<>(); }
125-
if (openRepls.containsKey(id)) { throw new ClientError("Attempt to replace an existing replicator"); }
126-
openRepls.put(id, repl);
127+
Map<String, Replicator> repls = openRepls;
128+
if (repls == null) {
129+
repls = new HashMap<>();
130+
openRepls = repls;
131+
}
132+
if (repls.containsKey(id)) { throw new ClientError("Attempt to replace an existing replicator"); }
133+
repls.put(id, repl);
127134
}
128135

129136
@Nullable
130-
public Replicator getRepl(@NonNull String name) { return (openRepls == null) ? null : openRepls.get(name); }
137+
public Replicator getRepl(@NonNull String name) {
138+
final Map<String, Replicator> repls = openRepls;
139+
return (repls == null) ? null : repls.get(name);
140+
}
131141

132142
@SuppressFBWarnings("NP_NULL_ON_SOME_PATH")
133143
public void addDocReplListener(@NonNull String replId, @NonNull DocReplListener listener) {
134-
if (openListeners == null) { openListeners = new HashMap<>(); }
135-
if (openListeners.containsKey(replId)) { throw new ClientError("Attempt to replace an existing doc listener"); }
136-
openListeners.put(replId, listener);
144+
Map<String, DocReplListener> docListeners = openDocListeners;
145+
if (openDocListeners == null) {
146+
docListeners = new HashMap<>();
147+
openDocListeners = docListeners;
148+
}
149+
if (docListeners.containsKey(replId)) { throw new ClientError("Attempt to replace an existing doc listener"); }
150+
docListeners.put(replId, listener);
137151
}
138152

139153
@Nullable
140154
public DocReplListener getDocReplListener(@NonNull String id) {
141-
return (openListeners == null) ? null : openListeners.get(id);
155+
final Map<String, DocReplListener> docListeners = openDocListeners;
156+
return (docListeners == null) ? null : docListeners.get(id);
142157
}
143158

144159
@NonNull
145160
public String addSnapshot(@NonNull Snapshot snapshot) {
146161
final String snapshotId = UUID.randomUUID().toString();
147-
if (openSnapshots == null) { openSnapshots = new HashMap<>(); }
148-
openSnapshots.put(snapshotId, snapshot);
162+
Map<String, Snapshot> snapshots = openSnapshots;
163+
if (openSnapshots == null) {
164+
snapshots = new HashMap<>();
165+
openSnapshots = snapshots;
166+
}
167+
snapshots.put(snapshotId, snapshot);
149168
return snapshotId;
150169
}
151170

152171
@NonNull
153172
public Snapshot getSnapshot(@NonNull String id) {
154-
if (openSnapshots != null) {
155-
final Snapshot snapshot = openSnapshots.get(id);
173+
final Map<String, Snapshot> shapshots = openSnapshots;
174+
if (shapshots != null) {
175+
final Snapshot snapshot = shapshots.get(id);
156176
if (snapshot != null) { return snapshot; }
157177
}
158178
throw new ClientError("No such snapshot: " + id);
159179
}
160180

181+
public void addEndptListener(@NonNull String id, @NonNull URLEndpointListener listener) {
182+
Map<String, URLEndpointListener> endptListeners = openEndptListeners;
183+
if (endptListeners == null) {
184+
endptListeners = new HashMap<>();
185+
openEndptListeners = endptListeners;
186+
}
187+
if (endptListeners.containsKey(id)) { throw new ClientError("Attempt to replace an existing listener"); }
188+
endptListeners.put(id, listener);
189+
}
190+
191+
@Nullable
192+
public URLEndpointListener getEndptListener(@NonNull String id) {
193+
final Map<String, URLEndpointListener> endptListeners = openEndptListeners;
194+
return (endptListeners == null) ? null : endptListeners.get(id);
195+
}
196+
161197
private void stopRepls() {
162-
final Map<String, Replicator> liveRepls = this.openRepls;
163-
this.openRepls = null;
198+
final Map<String, Replicator> liveRepls = openRepls;
199+
openRepls = null;
164200
if (liveRepls == null) { return; }
165201
for (Replicator repl: liveRepls.values()) {
166202
if (repl != null) { repl.stop(); }
167203
}
168204
}
169205

206+
private void stopEndptListeners() {
207+
final Map<String, URLEndpointListener> liveEndptListeners = openEndptListeners;
208+
openEndptListeners = null;
209+
if (liveEndptListeners == null) { return; }
210+
for (URLEndpointListener listener: liveEndptListeners.values()) {
211+
if (listener != null) { listener.stop(); }
212+
}
213+
}
214+
170215
private void closeCollections() {
171-
final Map<String, Collection> openColls = openCollections;
172-
this.openCollections = null;
173-
if (openColls == null) { return; }
174-
for (Collection collection: openColls.values()) { collection.close(); }
216+
final Map<String, Collection> liveCollections = openCollections;
217+
openCollections = null;
218+
if (liveCollections == null) { return; }
219+
for (Collection collection: liveCollections.values()) { collection.close(); }
175220
}
176221

177222
private void deleteDbs() {
178-
final File dbDir = this.dbDir;
179-
this.dbDir = null;
223+
final File liveDbDir = dbDir;
224+
dbDir = null;
180225

181-
final Map<String, Database> openDbs = this.openDbs;
182-
this.openDbs = null;
226+
final Map<String, Database> liveDbs = openDbs;
227+
openDbs = null;
183228

184-
if (openDbs != null) {
185-
for (Map.Entry<String, Database> entry: openDbs.entrySet()) {
229+
if (liveDbs != null) {
230+
for (Map.Entry<String, Database> entry: liveDbs.entrySet()) {
186231
final Database db = entry.getValue();
187232
if (db == null) {
188233
Log.err(TAG, "Attempt to close non-existent database: " + entry.getKey());
@@ -192,13 +237,13 @@ private void deleteDbs() {
192237
final String dbName = db.getName();
193238
try { db.close(); }
194239
catch (CouchbaseLiteException e) {
195-
throw new CblApiFailure("Failed closing database: " + dbName + " in " + dbDir, e);
240+
throw new CblApiFailure("Failed closing database: " + dbName + " in " + liveDbDir, e);
196241
}
197242
}
198243
}
199244

200-
if ((dbDir != null) && !new FileUtils().deleteRecursive(dbDir)) {
201-
Log.err(TAG, "Failed deleting db dir on reset: " + dbDir);
245+
if ((liveDbDir != null) && !new FileUtils().deleteRecursive(liveDbDir)) {
246+
Log.err(TAG, "Failed deleting db dir on reset: " + liveDbDir);
202247
}
203248
}
204249
}

0 commit comments

Comments
 (0)