2011-02-06 6 views
1

Я пытаюсь перебрать все строки («документы»?) В базе данных MongoDB с помощью Morphia. Иногда я получаю следующую трассировку стека:Morphia/MongoDB: can not getmore

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 

В файле журнала MongoDB я вижу следующее:

$ 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? Моя ошибка?

Update:

Я также видел это в моих 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

Просто столкнулся с той же проблемой, итерации через очень большой запрос. Я нашел это морфий ошибку, сообщила 21 марта 2011 года:

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

Выпуск 251: Включение/отключение тайм-аута делает противоположное тому, что он говорит

Вопрос говорит, что это будет исправлено в версии 1.0. Новый API disableCursorTimeout() выставлен в 1.00-SNAPHSHOT. Я запускаю long, чтобы проверить, не устраняет проблему.

1

Как вы можете видеть в этом thread MongoDB выпускает курсор по истечении определенного периода времени. Возможным решением может быть эмулирование периодической итерации и обновление курсора в цикле и в цикле.

1

Это фактический код? Кажется очень маловероятным, что этот код создаст это исключение. Тайм-аут курсоров после 10 минут бездействия. С такой замкнутой петлей это кажется невозможным.

Вы можете использовать datastore.createQuery(App.class).disableTimeout()..., чтобы отключить тайм-аут курсора в Morphia. Вы можете также использовать datastore.createQuery(App.class).fetchEmptyEntities(), если вы просто хотите @Id поля заполненного в

Кроме того, нет необходимости явно вызывать fetch(), если вы просто хотите использовать итератор в для петли подобных. fetch нужен только тогда, когда вы хотите сохранить итератор в переменной и использовать его в нескольких местах, но не в одном for-loop.

+0

Я попытался как можно больше упростить код, задавая свой вопрос, поэтому вы правы, что я оставил потенциально полезную информацию. Что происходит в «do stuff with app»: запрос веб-службы и сохранение результатов в файл на диске. Обычно это выполняется в миллисекундах, но я добавлю некоторые проверки времени на цикл и посмотрю, нет ли там какого-либо аномального поведения, вызывающего таймаут. Благодарю. –

+0

Просто сделал несколько раундов тестирования и узнал, что тайм-аут происходит через 45 минут в процессе итерации, и это повторяемо. Обратите внимание, что каждый проход через мой цикл итерации обычно составляет <1 секунду, поэтому он, похоже, является таймаутом для общего процесса итерации, а не задержкой между каждым вызовом Iterator.next(). –

+0

Это не совсем так просто. Курсор, итератор, извлекает данные в пакетах с сервера; каждый вызов next() может или не может (размер партии может быть 200 +), должен разговаривать с сервером. Вы пробовали вариант disableTimeout? –