2011-02-06 26 views
1

Morphiaを使用しているMongoDBデータベースのすべての行(「ドキュメント」?)を繰り返し処理しようとしています。時折、私は、次のスタックトレースを取得する:Morphia/MongoDB:getmoreを実行できません

MongoDBのログファイルで
com.mongodb.MongoInternalException: can't do getmore 
    at com.mongodb.DBApiLayer$Result._advance(DBApiLayer.java:378) 
    at com.mongodb.DBApiLayer$Result.hasNext(DBApiLayer.java:356) 
    at com.mongodb.DBCursor._hasNext(DBCursor.java:436) 
    at com.mongodb.DBCursor.hasNext(DBCursor.java:456) 
    at com.google.code.morphia.query.MorphiaIterator.hasNext(MorphiaIterator.java:40) 
    at 

私は以下を参照してください。

$ grep "cursorid not found" output.log 
Sun Feb 6 12:14:35 [conn13] getMore: cursorid not found App 2079575931792020691 
Sun Feb 6 12:44:17 [conn19] getMore: cursorid not found App 8364953818630631317 
Sun Feb 6 13:08:42 [conn20] getMore: cursorid not found App 7142256996888968009 

反復のための私のコード非常に簡単です:

for (App app : datastore.createQuery(App.class).fetch()) 
    { 
     log.info("app: " + app.getId()); 
     // do stuff with app 
    } 

Morphiaのバグ? MongoDBのバグ?私のバグ?

更新:

私はまた私のGlassFishのログでこれを見ている:

[#|2011-02-16T15:39:58.029+0000|WARNING|glassfish3.0.1|com.mongodb.TRACE|_ThreadID=28;_ThreadName=Thread-1;|The log message is null. 
java.lang.NullPointerException 
    at com.mongodb.DBApiLayer._cleanCursors(DBApiLayer.java:113) 
    at com.mongodb.DBApiLayer$DBCleanerThread.run(DBApiLayer.java:494) 
    at java.lang.Thread.run(Thread.java:662) 

答えて

1

非常に大きなクエリを反復処理している間に同じ問題が発生しました。私は、このMorphiaのバグを発見した2011年3月21日に報告された:

http://code.google.com/p/morphia/issues/detail?id=251

号251:有効/無効タイムアウトが、それは

問題は、それが可能になると言う言うことの反対を行いますバージョン1.0で修正されました。新しいAPI disableCursorTimeout()は1.00-SNAPHSHOTに公開されています。私はの長いテストを実行して問題が解決したかどうかを確認します。

1

このthreadのMongoDBは、一定時間後にカーソルを解放して、あなたが見ることができるように。可能な解決策は、バッチ反復をエミュレートし、そのサイクルでカーソルを更新することです。

1

これは実際のコードですか?そのコードがその例外を生成する可能性は非常に低いようです。カーソルは、10分間使用しないとタイムアウトします。そのようなタイトなループでは不可能と思われる。

datastore.createQuery(App.class).disableTimeout()...を使用すると、Morphiaのカーソルタイムアウトを無効にすることができます。あなただけで満たされた@Idフィールドをしたい場合にもdatastore.createQuery(App.class).fetchEmptyEntities()を使用することができます

また

は、あなただけのようなforループでイテレータを使用したい場合は、明示的にfetch()を呼び出す必要はありません。フェッチは、イテレータを変数に格納して複数の場所で使用するが、1つのfor-loopでは使用しない場合にのみ必要です。

+0

私は質問をするときにできるだけコードを単純化しようとしたので、役に立つ可能性のある情報を除外していることは間違いありません。 「アプリケーションを使ってやる」の場合、Webサービスを照会し、結果をディスク上のファイルに保存します。これは典型的にはミリ秒で実行されますが、ループにいくつかのタイムチェックを追加し、タイムアウトの原因となっている異常な動作がないかどうかを確認します。ありがとう。 –

+0

ちょうど数回のテストを行い、45分の繰り返し処理がタイムアウトしていることを知りました。これは繰り返し可能です。私の反復ループを通る各パスは通常1秒未満であるため、Iterator.next()への各呼び出しの間の遅延ではなく、全体の反復プロセスではタイムアウトになるようです。 –

+0

それほど単純ではありません。カーソル、イテレーターは、サーバーからバッチでデータをフェッチしています。 next()への各呼び出しは、実際には(バッチサイズは200以上になる可能性があります)、サーバーと通信する必要があります。あなたはdisableTimeoutオプションを試しましたか? –

関連する問題