diff options
Diffstat (limited to 'jstests/mr_killop.js')
-rw-r--r-- | jstests/mr_killop.js | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/jstests/mr_killop.js b/jstests/mr_killop.js new file mode 100644 index 0000000..899997d --- /dev/null +++ b/jstests/mr_killop.js @@ -0,0 +1,127 @@ +t = db.jstests_mr_killop; +t.drop(); +t2 = db.jstests_mr_killop_out; +t2.drop(); + +if ( typeof _threadInject == "undefined" ) { // don't run in v8 mode - SERVER-1900 + + function debug( x ) { +// printjson( x ); + } + + /** @return op code for map reduce op created by spawned shell, or that op's child */ + function op( where ) { + p = db.currentOp().inprog; + debug( p ); + for ( var i in p ) { + var o = p[ i ]; + if ( where ) { + if ( o.active && o.ns == "test.jstests_mr_killop" && o.query && o.query.$where ) { + return o.opid; + } + } else { + if ( o.active && o.query && o.query.mapreduce && o.query.mapreduce == "jstests_mr_killop" ) { + return o.opid; + } + } + } + return -1; + } + + /** + * Run one map reduce with the specified parameters in a parallel shell, kill the + * map reduce op or its child op with killOp, and wait for the map reduce op to + * terminate. + * @where - if true, a count $where op is killed rather than the map reduce op. + * This is necessay for a child count $where of a map reduce op because child + * ops currently mask parent ops in currentOp. + */ + function testOne( map, reduce, finalize, scope, where, wait ) { + t.drop(); + t2.drop(); + // Ensure we have 2 documents for the reduce to run + t.save( {a:1} ); + t.save( {a:1} ); + db.getLastError(); + + spec = + { + mapreduce:"jstests_mr_killop", + out:"jstests_mr_killop_out", + map: map, + reduce: reduce + }; + if ( finalize ) { + spec[ "finalize" ] = finalize; + } + if ( scope ) { + spec[ "scope" ] = scope; + } + + // Windows shell strips all double quotes from command line, so use + // single quotes. + stringifiedSpec = tojson( spec ).toString().replace( /\n/g, ' ' ).replace( /\"/g, "\'" ); + + // The assert below won't be caught by this test script, but it will cause error messages + // to be printed. + s = startParallelShell( "assert.commandWorked( db.runCommand( " + stringifiedSpec + " ) );" ); + + if ( wait ) { + sleep( 2000 ); + } + + o = null; + assert.soon( function() { o = op( where ); return o != -1 } ); + + db.killOp( o ); + debug( "did kill" ); + + // When the map reduce op is killed, the spawned shell will exit + s(); + debug( "parallel shell completed" ); + + assert.eq( -1, op( where ) ); + } + + /** Test using wait and non wait modes */ + function test( map, reduce, finalize, scope, where ) { + testOne( map, reduce, finalize, scope, where, false ); + testOne( map, reduce, finalize, scope, where, true ); + } + + /** Test looping in map and reduce functions */ + function runMRTests( loop, where ) { + test( loop, function( k, v ) { return v[ 0 ]; }, null, null, where ); + test( function() { emit( this.a, 1 ); }, loop, null, null, where ); + test( function() { loop(); }, function( k, v ) { return v[ 0 ] }, null, { loop: loop }, where ); + } + + /** Test looping in finalize function */ + function runFinalizeTests( loop, where ) { + test( function() { emit( this.a, 1 ); }, function( k, v ) { return v[ 0 ] }, loop, null, where ); + test( function() { emit( this.a, 1 ); }, function( k, v ) { return v[ 0 ] }, function( a, b ) { loop() }, { loop: loop }, where ); + } + + var loop = function() { + while( 1 ) { + ; + } + } + runMRTests( loop, false ); + runFinalizeTests( loop, false ); + + var loop = function() { + while( 1 ) { + db.jstests_mr_killop.count( { a:1 } ); + } + } + runMRTests( loop, false ); + // db can't be accessed from finalize() so not running that test + + /** Test that we can kill the child op of a map reduce op */ + var loop = function() { + db.jstests_mr_killop.find( {$where:function() { while( 1 ) { ; } }} ).toArray(); + } + runMRTests( loop, true ); + +} |