com.mongodb.MongoException$CursorNotFound: cursor not found on server

4,757 views
Skip to first unread message

Deepak Prasanna

unread,
May 17, 2012, 1:03:20 PM5/17/12
to mongod...@googlegroups.com
//tailer.scala

import com.mongodb._

object MongoOplog {
  def main(args: Array[String]) = {
    val mongoConn = new Mongo( "127.0.0.1" , 27018 );
    val db = mongoConn.getDB("local");
    val oplog = db.getCollection("oplog.$main")
    val cursor = oplog.find().addOption(Bytes.QUERYOPTION_NOTIMEOUT)
                              .addOption(Bytes.QUERYOPTION_TAILABLE)
                              .addOption(Bytes.QUERYOPTION_AWAITDATA)
    while(cursor.hasNext) {
      val doc = cursor.next
      println(doc)
    }
  }
}

This is the scala code I have written for tailing the oplog and printing the documents. When I run this, I do get some documents printed , but immediately the execution stops with this exception. I am using the java-mongo-driver.

[error] (run-main) com.mongodb.MongoException$CursorNotFound: cursor not found on server com.mongodb.MongoException$CursorNotFound: cursor not found on server at com.mongodb.DBApiLayer$Result.init(DBApiLayer.java:371) at com.mongodb.DBApiLayer$Result._advance(DBApiLayer.java:418) at com.mongodb.DBApiLayer$Result.hasNext(DBApiLayer.java:400) at com.mongodb.DBCursor._hasNext(DBCursor.java:489) at com.mongodb.DBCursor.hasNext(DBCursor.java:509) at MongoOplog$.main(tailer.scala:12) at MongoOplog.main(tailer.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) java.lang.RuntimeException: Nonzero exit code: 1 at scala.sys.package$.error(package.scala:27) [error] {file:/home/deepak/scala-mongo-oplog-watcher/}default-b16d47/compile:run: Nonzero exit code: 1 [error] Total time: 9 s, completed May 17, 2012 8:09:58 PM

When I googled I got a bunch of suggestion to use "(Bytes.QUERYOPTION_NOTIMEOUT)", I tried using it but still no luck.
Help is appreciated.

Thanks,
Deepak.

Bryan

unread,
May 21, 2012, 7:58:44 PM5/21/12
to mongodb-user
When using await data, the server hangs on to the server side cursor
for 300ms of inactivity before the cursor is subject to clean up. If
your write activity is low, the cursor you are following may have been
cleaned on the server. If you like to tail the oplog indefinitely,
your application will need to start a loop and remember where it last
read from the oplog so that it can continue tailing if the cursor is
lost. Here's a sample method, written in Java. Remember to sleep for a
reasonable period of time. You don't want to hit the server too often.




    public void tail(DB db){

        DBCollection oplog = db.getCollection("oplog.rs");

        BSONTimestamp ts = (BSONTimestamp)oplog.find().sort( new
BasicDBObject( "$natural" , -1 ) ).limit(1).next().get("ts");
        System.out.println(JSON.serialize(ts));

        while(true){
            BasicDBObject query = new BasicDBObject();
            query.put("ts", new BasicDBObject("$gte", ts));

            DBCursor cursor = oplog.find(query)
                .addOption(Bytes.QUERYOPTION_NOTIMEOUT)
                .addOption(Bytes.QUERYOPTION_TAILABLE)
                .addOption(Bytes.QUERYOPTION_AWAITDATA);

            while(cursor.hasNext()) {
                ts = (BSONTimestamp)cursor.next().get("ts");
                System.out.println(JSON.serialize(ts));
              }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
>         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImp l.java:43)

deepak prasanna

unread,
May 22, 2012, 5:35:38 AM5/22/12
to mongod...@googlegroups.com, ba...@systeminsights.com, em...@systeminsights.com, wi...@systeminsights.com, ath...@systeminsights.com

Thanks for the reply mate. I agree that I need an extra loop to keep polling, which makes me to change the script like this,
import com.mongodb._


object MongoOplog { def main(args: Array[String]) = { val mongoConn = new Mongo( "127.0.0.1" , 27018 ); val db = mongoConn.getDB("local"); val oplog = db.getCollection("oplog.$main") val cursor = oplog.find().addOption(Bytes.QUERYOPTION_NOTIMEOUT) .addOption(Bytes.QUERYOPTION_TAILABLE) .addOption(Bytes.QUERYOPTION_AWAITDATA) .batchSize(100) while(true) { while(cursor.hasNext) { println(cursor.next) } } } }

I hope this should just work but im still getting a cursor not found. The track of the last record written is something which is the job of a tailable cursor to remember, if I am right or that is what I understand of a cursor being tailable. Below is my respective code written in Ruby. This works perfect.
require "singleton" require "mongo" include Mongo class MongoSandBox include Singleton attr_accessor :tail def initialize @connection = Mongo::Connection.new("localhost", 27017) @db = @connection.db "local" @collection = @db["oplog.$main"] @tail = Cursor.new(@collection, :tailable => true, :order => [['$natural', 1]]) end end class MongoReplSet include Singleton attr_accessor :cursor def initialize @connection = Mongo::ReplSetConnection.new(["localhost:27018","localhost:27019","localhost:27020"]) @db = @connection.db "vimana-sandbox-dup" @cursor = @db["utilization.metrics.cycledowntime"] end def insert(oplog_record) return unless oplog_record["op"] == "i" return unless oplog_record["ns"] == "vimana-sandbox.utilization.metrics.cycledowntime" begin id = @cursor.insert(oplog_record["o"]) puts "Im listening the oplog and I just inserted #{id} into the replica." rescue Mongo::ConnectionFailure puts "Oops, He is dead Jim." end end end while true tail = MongoSandBox.instance.tail MongoReplSet.instance.insert(tail.next) if tail.has_next? end

I am trying to do the same exact thing. I never did any of the timestamp remembering stuff with the ruby driver. I also checked the source code of ruby driver, when I create tailable cursors it adds "OP_QUERY_TAILABLE" and nothing else which I am doing already here too. This is really weird! I hope I am missing something here again. Any takers?
Thanks,
Deepak.


--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To post to this group, send email to mongod...@googlegroups.com
To unsubscribe from this group, send email to
mongodb-user...@googlegroups.com
See also the IRC channel -- freenode.net#mongodb

Bryan

unread,
May 23, 2012, 7:15:34 PM5/23/12
to mongodb-user
What version of mongo and the driver are you using?

On May 22, 2:35 am, deepak prasanna <deepak...@gmail.com> wrote:
> Thanks for the reply mate. I agree that I need an extra loop to keep
> polling, which makes me to change the script like this,
>
> import com.mongodb._
>
> object MongoOplog {
>   def main(args: Array[String]) = {
>     val mongoConn = new Mongo( "127.0.0.1" , 27018 );
>     val db = mongoConn.getDB("local");
>     val oplog = db.getCollection("oplog.$main")
>     val cursor = oplog.find().addOption(Bytes.QUERYOPTION_NOTIMEOUT)
>                              .addOption(Bytes.QUERYOPTION_TAILABLE)
>                              .addOption(Bytes.QUERYOPTION_AWAITDATA)
>                              .batchSize(100)
>     while(true) {
>       while(cursor.hasNext) { println(cursor.next) }
>     }
>   }
>
> }
>
> I hope this should just work but im still getting a *cursor not
> found*. The track of the last record written is something which is the
> job of a tailable cursor to remember, if I am right or that is what I
> understand of a cursor being tailable. Below is my respective code
> written in Ruby. This works perfect.
> require "singleton"
> require "mongo"
> include Mongo
>
> class MongoSandBox
>   include Singleton
>   attr_accessor :tail
>   def initialize
>     @connection = Mongo::Connection.new("localhost", 27017)
>     @db = @connection.db "local"
>     @collection = @db["oplog.$main"]
>     @tail = Cursor.new(@collection, :tailable => true, :order =>
> [['$natural', 1]])
>   end
> end
>
> class MongoReplSet
>   include Singleton
>   attr_accessor :cursor
>   def initialize
>     @connection =
> Mongo::ReplSetConnection.new(["localhost:27018","localhost:27019","localhos t:27020"])
Reply all
Reply to author
Forward
0 new messages