Skip to content

Commit 7374ac8

Browse files
authored
Merge pull request #14 from couchbase/feature/issue_1375
Fixed https://github.com/couchbase/couchbase-lite-java-core/issues/1375
2 parents c5d557d + fd32460 commit 7374ac8

File tree

3 files changed

+82
-60
lines changed

3 files changed

+82
-60
lines changed

src/main/java/com/couchbase/lite/javascript/ReplicationFilterBlockRhino.java

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
/**
2-
* Copyright (c) 2015 Couchbase, Inc All rights reserved.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5-
* except in compliance with the License. You may obtain a copy of the License at
6-
*
7-
* http://www.apache.org/licenses/LICENSE-2.0
8-
*
9-
* Unless required by applicable law or agreed to in writing, software distributed under the
10-
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11-
* either express or implied. See the License for the specific language governing permissions
12-
* and limitations under the License.
13-
*/
14-
1+
//
2+
// Copyright (c) 2016 Couchbase, Inc. All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5+
// except in compliance with the License. You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software distributed under the
10+
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
// either express or implied. See the License for the specific language governing permissions
12+
// and limitations under the License.
13+
//
1514
package com.couchbase.lite.javascript;
1615

1716
import com.couchbase.lite.ReplicationFilter;
@@ -30,14 +29,21 @@
3029
* Created by hideki on 10/28/15.
3130
*/
3231
public class ReplicationFilterBlockRhino implements ReplicationFilter {
33-
public static String TAG = "ReplicationFilterBlockRhino";
32+
public static String TAG = "JavaScriptEngine";
3433

3534
private static WrapFactory wrapFactory = new CustomWrapFactory();
3635
private Scriptable scope;
3736
private GlobalScope globalScope;
3837
private Function filterFunction;
3938

40-
public ReplicationFilterBlockRhino(String src){
39+
// NOTE: Scope is sharable with multiple threads, it seems `Function` is not.
40+
// Compiling javascript codes for every request makes slow.
41+
// It is reason current code base re-use compiled Function.
42+
// Instead of compiling for every request, use `synchronized` to protect Function
43+
// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scopes_and_Contexts
44+
private final Object lockFunction = new Object();
45+
46+
public ReplicationFilterBlockRhino(String src) {
4147
org.mozilla.javascript.Context ctx = org.mozilla.javascript.Context.enter();
4248
try {
4349
ctx.setOptimizationLevel(-1);
@@ -56,19 +62,18 @@ public boolean filter(SavedRevision revision, Map<String, Object> params) {
5662
try {
5763
ctx.setOptimizationLevel(-1);
5864
ctx.setWrapFactory(wrapFactory);
59-
6065
Scriptable localScope = ctx.newObject(scope);
6166
localScope.setPrototype(scope);
6267
localScope.setParentScope(null);
63-
6468
Object jsDocument = org.mozilla.javascript.Context.javaToJS(revision.getProperties(), localScope);
6569
Object jsParams = org.mozilla.javascript.Context.javaToJS(params, localScope);
6670

6771
try {
68-
Object result = filterFunction.call(ctx, localScope, null, new Object[]{jsDocument, jsParams});
69-
return ((Boolean)result).booleanValue();
72+
synchronized (lockFunction) {
73+
Object result = filterFunction.call(ctx, localScope, null, new Object[]{jsDocument, jsParams});
74+
return ((Boolean) result).booleanValue();
75+
}
7076
} catch (org.mozilla.javascript.RhinoException e) {
71-
// Error in the JavaScript view - CouchDB swallows the error and tries the next document
7277
Log.e(TAG, "Error in filterFunction.call()", e);
7378
return false;
7479
}

src/main/java/com/couchbase/lite/javascript/ViewMapBlockRhino.java

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
/**
2-
* Copyright (c) 2015 Couchbase, Inc All rights reserved.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5-
* except in compliance with the License. You may obtain a copy of the License at
6-
*
7-
* http://www.apache.org/licenses/LICENSE-2.0
8-
*
9-
* Unless required by applicable law or agreed to in writing, software distributed under the
10-
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11-
* either express or implied. See the License for the specific language governing permissions
12-
* and limitations under the License.
13-
*/
1+
//
2+
// Copyright (c) 2016 Couchbase, Inc. All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5+
// except in compliance with the License. You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software distributed under the
10+
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
// either express or implied. See the License for the specific language governing permissions
12+
// and limitations under the License.
13+
//
1414
package com.couchbase.lite.javascript;
1515

1616
import com.couchbase.lite.Emitter;
1717
import com.couchbase.lite.Mapper;
1818
import com.couchbase.lite.javascript.scopes.MapGlobalScope;
1919
import com.couchbase.lite.javascript.wrapper.CustomWrapFactory;
20+
import com.couchbase.lite.util.Log;
2021

2122
import org.mozilla.javascript.Function;
2223
import org.mozilla.javascript.Scriptable;
@@ -25,16 +26,22 @@
2526
import java.util.Map;
2627

2728
class ViewMapBlockRhino implements Mapper {
29+
private final static String TAG = "JavaScriptEngine";
2830

2931
private static WrapFactory wrapFactory = new CustomWrapFactory();
3032
private Scriptable globalScope;
3133
private MapGlobalScope mapGlobalScope;
3234
private Function mapFunction;
3335

34-
public ViewMapBlockRhino(String src) {
36+
// NOTE: Scope is sharable with multiple threads, it seems `Function` is not.
37+
// Compiling javascript codes for every request makes slow.
38+
// It is reason current code base re-use compiled Function.
39+
// Instead of compiling for every request, use `synchronized` to protect Function
40+
// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scopes_and_Contexts
41+
private final Object lockFunction = new Object();
3542

43+
public ViewMapBlockRhino(String src) {
3644
org.mozilla.javascript.Context ctx = org.mozilla.javascript.Context.enter();
37-
3845
try {
3946
ctx.setOptimizationLevel(-1);
4047
ctx.setWrapFactory(wrapFactory);
@@ -48,7 +55,6 @@ public ViewMapBlockRhino(String src) {
4855

4956
@Override
5057
public void map(Map<String, Object> document, Emitter emitter) {
51-
5258
mapGlobalScope.setEmitter(emitter);
5359

5460
org.mozilla.javascript.Context ctx = org.mozilla.javascript.Context.enter();
@@ -63,9 +69,11 @@ public void map(Map<String, Object> document, Emitter emitter) {
6369
Object jsDocument = org.mozilla.javascript.Context.javaToJS(document, localScope);
6470

6571
try {
66-
mapFunction.call(ctx, localScope, null, new Object[]{jsDocument});
72+
synchronized (lockFunction) {
73+
mapFunction.call(ctx, localScope, null, new Object[]{jsDocument});
74+
}
6775
} catch (org.mozilla.javascript.RhinoException e) {
68-
// Error in the JavaScript view - CouchDB swallows the error and tries the next document
76+
Log.e(TAG, "Error in calling JavaScript map function", e);
6977
return;
7078
}
7179
} finally {

src/main/java/com/couchbase/lite/javascript/ViewReduceBlockRhino.java

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
/**
2-
* Copyright (c) 2015 Couchbase, Inc All rights reserved.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5-
* except in compliance with the License. You may obtain a copy of the License at
6-
*
7-
* http://www.apache.org/licenses/LICENSE-2.0
8-
*
9-
* Unless required by applicable law or agreed to in writing, software distributed under the
10-
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11-
* either express or implied. See the License for the specific language governing permissions
12-
* and limitations under the License.
13-
*/
1+
//
2+
// Copyright (c) 2016 Couchbase, Inc. All rights reserved.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5+
// except in compliance with the License. You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software distributed under the
10+
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
11+
// either express or implied. See the License for the specific language governing permissions
12+
// and limitations under the License.
13+
//
1414
package com.couchbase.lite.javascript;
1515

1616
import com.couchbase.lite.Reducer;
1717
import com.couchbase.lite.javascript.scopes.ReduceGlobalScope;
1818
import com.couchbase.lite.javascript.wrapper.CustomWrapFactory;
19+
import com.couchbase.lite.util.Log;
1920

2021
import org.mozilla.javascript.Function;
2122
import org.mozilla.javascript.Scriptable;
@@ -25,20 +26,27 @@
2526
import java.util.List;
2627

2728
class ViewReduceBlockRhino implements Reducer {
29+
private final static String TAG = "JavaScriptEngine";
2830

2931
private static WrapFactory wrapFactory = new CustomWrapFactory();
3032
private final ReduceGlobalScope reduceGlobalScope;
3133
private final ScriptableObject globalScope;
3234
private final Function reduceFunction;
3335
private final NativReduceFunctions nativeReduce;
3436

37+
// NOTE: Scope is sharable with multiple threads, it seems `Function` is not.
38+
// Compiling javascript codes for every request makes slow.
39+
// It is reason current code base re-use compiled Function.
40+
// Instead of compiling for every request, use `synchronized` to protect Function
41+
// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scopes_and_Contexts
42+
private final Object lockFunction = new Object();
43+
3544
public ViewReduceBlockRhino(String src) {
3645

3746
nativeReduce = NativReduceFunctions.fromKey(src);
3847

3948
if (nativeReduce == NativReduceFunctions.DEFAULT) {
4049
org.mozilla.javascript.Context ctx = org.mozilla.javascript.Context.enter();
41-
4250
try {
4351
ctx.setOptimizationLevel(-1);
4452
ctx.setWrapFactory(wrapFactory);
@@ -58,7 +66,6 @@ public ViewReduceBlockRhino(String src) {
5866

5967
@Override
6068
public Object reduce(List<Object> keys, List<Object> values, boolean reReduce) {
61-
6269
switch (nativeReduce) {
6370
case SUM:
6471
return nativeSum(keys, values, reReduce);
@@ -76,16 +83,18 @@ public Object reduce(List<Object> keys, List<Object> values, boolean reReduce) {
7683
localScope.setParentScope(null);
7784

7885
Object[] args = new Object[3];
79-
8086
args[0] = org.mozilla.javascript.Context.javaToJS(keys, localScope);
8187
args[1] = org.mozilla.javascript.Context.javaToJS(values, localScope);
8288
args[2] = org.mozilla.javascript.Context.javaToJS(reReduce, localScope);
8389

84-
return reduceFunction.call(ctx, localScope, null, args);
85-
86-
} catch (org.mozilla.javascript.RhinoException e) {
87-
// TODO check couchdb behaviour on error in reduce function
88-
return null;
90+
try {
91+
synchronized (lockFunction) {
92+
return reduceFunction.call(ctx, localScope, null, args);
93+
}
94+
} catch (org.mozilla.javascript.RhinoException e) {
95+
Log.e(TAG, "Error in calling JavaScript reduce function", e);
96+
return null;
97+
}
8998
} finally {
9099
org.mozilla.javascript.Context.exit();
91100
}

0 commit comments

Comments
 (0)