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
+ / /
14
14
package com .couchbase .lite .javascript ;
15
15
16
16
import com .couchbase .lite .Reducer ;
17
17
import com .couchbase .lite .javascript .scopes .ReduceGlobalScope ;
18
18
import com .couchbase .lite .javascript .wrapper .CustomWrapFactory ;
19
+ import com .couchbase .lite .util .Log ;
19
20
20
21
import org .mozilla .javascript .Function ;
21
22
import org .mozilla .javascript .Scriptable ;
25
26
import java .util .List ;
26
27
27
28
class ViewReduceBlockRhino implements Reducer {
29
+ private final static String TAG = "JavaScriptEngine" ;
28
30
29
31
private static WrapFactory wrapFactory = new CustomWrapFactory ();
30
32
private final ReduceGlobalScope reduceGlobalScope ;
31
33
private final ScriptableObject globalScope ;
32
34
private final Function reduceFunction ;
33
35
private final NativReduceFunctions nativeReduce ;
34
36
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
+
35
44
public ViewReduceBlockRhino (String src ) {
36
45
37
46
nativeReduce = NativReduceFunctions .fromKey (src );
38
47
39
48
if (nativeReduce == NativReduceFunctions .DEFAULT ) {
40
49
org .mozilla .javascript .Context ctx = org .mozilla .javascript .Context .enter ();
41
-
42
50
try {
43
51
ctx .setOptimizationLevel (-1 );
44
52
ctx .setWrapFactory (wrapFactory );
@@ -58,36 +66,37 @@ public ViewReduceBlockRhino(String src) {
58
66
59
67
@ Override
60
68
public Object reduce (List <Object > keys , List <Object > values , boolean reReduce ) {
61
-
62
69
switch (nativeReduce ) {
63
70
case SUM :
64
71
return nativeSum (keys , values , reReduce );
65
72
case COUNT :
66
73
return nativeCount (keys , values , reReduce );
67
74
case DEFAULT :
68
75
default :
69
- org .mozilla .javascript .Context ctx = org .mozilla .javascript .Context .enter ();
70
- try {
71
- ctx .setOptimizationLevel (-1 );
72
- ctx .setWrapFactory (wrapFactory );
73
-
74
- Scriptable localScope = ctx .newObject (globalScope );
75
- localScope .setPrototype (globalScope );
76
- localScope .setParentScope (null );
77
-
78
- Object [] args = new Object [3 ];
79
-
80
- args [0 ] = org .mozilla .javascript .Context .javaToJS (keys , localScope );
81
- args [1 ] = org .mozilla .javascript .Context .javaToJS (values , localScope );
82
- args [2 ] = org .mozilla .javascript .Context .javaToJS (reReduce , localScope );
83
-
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 ;
89
- } finally {
90
- org .mozilla .javascript .Context .exit ();
76
+ synchronized (lockFunction ) {
77
+ org .mozilla .javascript .Context ctx = org .mozilla .javascript .Context .enter ();
78
+ try {
79
+ ctx .setOptimizationLevel (-1 );
80
+ ctx .setWrapFactory (wrapFactory );
81
+
82
+ Scriptable localScope = ctx .newObject (globalScope );
83
+ localScope .setPrototype (globalScope );
84
+ localScope .setParentScope (null );
85
+
86
+ Object [] args = new Object [3 ];
87
+ args [0 ] = org .mozilla .javascript .Context .javaToJS (keys , localScope );
88
+ args [1 ] = org .mozilla .javascript .Context .javaToJS (values , localScope );
89
+ args [2 ] = org .mozilla .javascript .Context .javaToJS (reReduce , localScope );
90
+
91
+ try {
92
+ return reduceFunction .call (ctx , localScope , null , args );
93
+ } catch (org .mozilla .javascript .RhinoException e ) {
94
+ Log .e (TAG , "Error in calling JavaScript reduce function" , e );
95
+ return null ;
96
+ }
97
+ } finally {
98
+ org .mozilla .javascript .Context .exit ();
99
+ }
91
100
}
92
101
}
93
102
}
0 commit comments