|
|
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Добрый день! Есть файлы на google storage. Мне надо скачать его. Использую Код: sql 1. 2. 3. 4. 5. 6. 7. Обнаружил, что API может вернуть -1 РАНЬШЕ чем файл закончился (можно заранее получить размер и проверять скачанный объём). Поборол -при ошибке создаю объект заново и продолжаю с места, где меня обманули :) Теперь далее- файл это gz в котором текст с кучей строк. Мне удобнее читать сразу строки, без создания временного файла. Сделал так- свой наследний InputStream, который реализован поверх API и реализует разные read. Там всё просто: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. После этого поверх моего InputStream навернул Код: sql 1. 2. Вот только засада- "пересоздаём inputStream и пробуем получить ещё данных" никогда не вызывается, но закачивание так же ИНОГДА обрывается. Приходится (продолжить скачивание с места обрыва нереально) качать всё заново. При этом ошибок нет, просто получены не все строки. Куда копать? Куча обёрток сильно затрудняет отладку (да и пойсмать это очень сложно- надо час-другой работы). -- Алексей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 09:28 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey Tomin, [quot] Storage.Objects objects = GoogleStorageFetcherMapper.createStorage(accessToken).objects(); InputStream inputStream = objects.get(bucket, fileName).executeMediaAsInputStream(); byte[] buf = byte[1024*1024]; int size; while (size = inputStream.read(buf) >= 0) { .... } [quot] У Меня тоже (правда по сокетам такое наблюдалось) Мне помогло перед А попробуйте небольшую задержку сделать Код: java 1. 2. 3. Поставить задержку Код: java 1. 2. 3. 4. И данные подтягивались всегда...в чём была магия так и не понял. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 10:49 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Я бы остановил в дебаге и посмотрел что там за InputStream - напрямую ли читает из сокета или локально куда лезет. Ну и там дебаг можно настроить чтобы дампить HTTP. Есть смысл посмотреть на заголовки от сервера, чтобы понять, либо сервер только часть присылает, либо это таки правда бага в гугловом клиенте. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 11:10 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
[quot irbis_al]А попробуйте небольшую задержку сделать У Вас задержка перед while, а проблемы у меня- В while. Например скачалось 500Мб из 3Гб и пришло -1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 11:22 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
BlazkowiczЯ бы остановил в дебаге и посмотрел что там за InputStream - напрямую ли читает из сокета или локально куда лезет. Ну и там дебаг можно настроить чтобы дампить HTTP. Есть смысл посмотреть на заголовки от сервера, чтобы понять, либо сервер только часть присылает, либо это таки правда бага в гугловом клиенте. Клиент лезет по http. Видимо -1 это из-за особенности http, в котором размер файла как-бы неизвестен. Но это-то я победил. Вопрос скорее как разгребать ошибку, когда налету идёт gunzip... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 11:23 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey Tomin, Не очень понимаю зачем там GZIP. Гугловый HTTP клиент и так его поддерживает. Ну, предположим у вас по ТЗ файлы такие. Ладно. Тогда надо проверить что твой код воткнут до GZIPInputStream. Потому как считать можно байты прочитаные, а можно распакованые, которые, очевидно не то что нужно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 11:36 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
BlazkowiczНе очень понимаю зачем там GZIP. Гугловый HTTP клиент и так его поддерживает. Ну, предположим у вас по ТЗ файлы такие. Файлы не наши, это входные данные. На хадупе gzip плохо поддерживаются, поэтому я их пережимаю в gzip2. Быстрее всего это сделать "на лету". BlazkowiczТогда надо проверить что твой код воткнут до GZIPInputStream До. Код я приводил. Да и иначе быть не может- файлы очень большие, качаются по нескольку часов, а сессия на гугле час. Так что без моей прослойки большие файлы ввобще невозможно скачать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 11:49 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey Tomin, Ну, надо дебажить прерывание потока. Чтение же не само по себе отваливается. Либо исключение, либо -1, либо чтение идёт мимо метода, который ты переопределил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 11:58 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
BlazkowiczAlexey Tomin, Ну, надо дебажить прерывание потока. Чтение же не само по себе отваливается. Либо исключение, либо -1, либо чтение идёт мимо метода, который ты переопределил. Мимо- я не вижу куда. В InputStream три метода read - один (read(byte[])) перенаправляет рядом, а два других я перекрыл. skip и available не перекрывал- вроде и не надо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 12:47 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey Tomin, Если ошибку сложно повторить, чтобы продебажить, значит надо логов больше добавить. Оно же не по магии какой-то из метода выходит. И ещё я подозреваю что BufferedReader может раньше времени прерваться. Можно на Scanner переделать чтобы построчно читать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 13:18 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
BlazkowiczAlexey Tomin, Если ошибку сложно повторить, чтобы продебажить, значит надо логов больше добавить. Оно же не по магии какой-то из метода выходит. И ещё я подозреваю что BufferedReader может раньше времени прерваться. Можно на Scanner переделать чтобы построчно читать. А это, оказывается, бага в JDK . В контракте InputStream#available() сказано, что если файл кончился, то метод должен вернуть 0. Но обратное не верно- банально, если буфер пуст, но где-то там байты есть, то можно вернуть 0 (собственно ДОЛЖНО вернуть 0). Однако java.util.zip.GZIPInputStream#readTrailer считает, что если в "нужный" момент available() == 0 то файл кончился и можно уходить. Т.е., если он дочитал сжатый блок и в этот момент буфер потока пуст- то gzip всех кидает. В общем понятно- мне придётся никогда не возвращать 0, даже если реально буфер пуст. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 16:35 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey TominА это, оказывается, бага в JDK . Вот же негодяи! Я сам планировал так делать. А оказывается нельзя. Alexey TominВ общем понятно-мне придётся никогда не возвращать 0, даже если реально буфер пуст. Как вариант. А других реализаций GzipInputStream разве нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.12.2015, 17:10 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
BlazkowiczAlexey TominА это, оказывается, бага в JDK . Вот же негодяи! Я сам планировал так делать. А оказывается нельзя. Как? BlazkowiczAlexey TominВ общем понятно-мне придётся никогда не возвращать 0, даже если реально буфер пуст. Как вариант. А других реализаций GzipInputStream разве нет? Эта хоть и с багой, зато уже родная :) А что в других- неизвестно. В принципе мне всё равно, когда поток читать- эта штука проблем в итоге не создаёт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 07:43 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey TominКак? Тащить по сетке большие файлы через GZIP. У меня аналогичный код, но текстовые файлы поменьше. Читаю через Scanner вместо BufferedReader. На сервере лимит на размер файла. Пользователи хотят побольше. Вот, думал аналогичным образом gzip навернуть сверху. Но будет точно такой же косяк. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 09:49 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
BlazkowiczAlexey TominКак? Тащить по сетке большие файлы через GZIP. У меня аналогичный код, но текстовые файлы поменьше. Читаю через Scanner вместо BufferedReader. На сервере лимит на размер файла. Пользователи хотят побольше. Вот, думал аналогичным образом gzip навернуть сверху. Но будет точно такой же косяк. Во-первых они обещают, что уже поправили , но версию я не понял (в 1.8.66 воспроизводится) - так что может просто подождать. Во-вторых можно bzip2 использовать- он жмёт в 2 раза лучше (чем с гугла приходит- я, правда, не знаю, какой там алгоритм DoubleClick использует). В третьих можно обёртку написать, которая будет при вызове available пытаться получить данные :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 11:39 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey Tomin, Но это не совсем тот тикет. Первый, который ты привел всё ещё открыт. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 11:45 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Blazkowicz Но это не совсем тот тикет. Первый, который ты привел всё ещё открыт. Точно, есть разница. Кстати, чтобы что-нибудь туда допивать, надо платную техподдержку иметь? Support Identifier же только так получается? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 12:48 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey Tomin, Можно перейти на OpenJDK и свободно её пропатчить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 12:49 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Alexey TominОднако java.util.zip.GZIPInputStream#readTrailer считает, что если в "нужный" момент available() == 0 то файл кончился и можно уходить. Т.е., если он дочитал сжатый блок и в этот момент буфер потока пуст- то gzip всех кидаетЭто не совсем бага. gzip-поток может состоять из отдельных (независимых) кусков. Можно, например, сжать кучу файлов, а потом "склеить" их в один простым копированием, и это будет корректный архив - утилита gzip развернёт его в один файл, где точно так же будут "склеены" исходные файлы. Использовать в такой ситуации available - очень ненадёжно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 17:18 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovЭто не совсем бага. Использовать в такой ситуации available - очень ненадёжно. Так почему "не бага"? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 17:23 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Потому, что нельзя полагаться на available в определении конца данных. В некоторых случаях нельзя даже полагаться на то, что запросив "точно доступное" количество байт в read мы это количество получим - необходимо писать цикл с выходом по концу файла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 17:32 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovПотому, что нельзя полагаться на available в определении конца данных. В некоторых случаях нельзя даже полагаться на то, что запросив "точно доступное" количество байт в read мы это количество получим - необходимо писать цикл с выходом по концу файла. Правильно. А GZIPInputStream на него полагается и это бага. Ты что-то не допонял. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 17:48 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Да, блин: "Если вы утомлены, то лучше не летайте сегодня - отдохните" (ц) В.Каверин, "Два капитана" :) Но, тем не менее, ошибка, похоже, в InflaterInputStream.available() - возможна ситуация, когда распакованные данные закончились, а входной поток - ещё нет. По логике, available() должен возвращать 1 (что-то есть, но неизвестно, что именно), а он возвращает 0, основываясь на признаке конца распакованных данных. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 18:46 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Хотя, если ещё подумать, то ситуация сильно неоднозначная и лучше унаследоваться от InflaterInputStream, самостоятельно написав разбор существенных частей заголовков и пропуск ненужного ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.12.2015, 18:51 |
|
||
|
Google storage api - попытка обойти багу...
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovДа, блин: "Если вы утомлены, то лучше не летайте сегодня - отдохните" (ц) В.Каверин, "Два капитана" :) Но, тем не менее, ошибка, похоже, в InflaterInputStream.available() - возможна ситуация, когда распакованные данные закончились, а входной поток - ещё нет. При чём здесь это? InputStream#available() возвращает количество байт, которые можно получить из потока БЕЗ БЛОКИРОВОК. При этом оно int, т.е. заведомо меньше размера файла. Так вот- вполне нормальной является ситуация, что это значение 0, а поток ещё читать и читать. Другое дело (смотрим в кишки GZIPInputStream), что обычно до запроса available дело не доходит. Оно проверяется только если метод Inflater#inflateBytes вернул -1. Почему это происходит выяснить сложно- метод нативный, до чтения исходников JDK я пока не дошёл. Если локально читать с гуглостореджа, то это случается несколько раз в гигабайт, но локально мне вседа везло и Inflater#len в этом месте было больше волшебного числа 26. Basil A. SidorovПо логике, available() должен возвращать 1 (что-то есть, но неизвестно, что именно), а он возвращает 0, основываясь на признаке конца распакованных данных. Нет, возвращает 0 сетевой InputStream. Просто потому, что буфер в этот момент пуст. Хотя, если честно, мне просто было лень переопределять его (InputStream мой из-за протухания токена). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.12.2015, 08:29 |
|
||
|
|

start [/forum/search_topic.php?author=Mr_Garrison&author_mode=last_posts&do_search=1]: |
0ms |
get settings: |
9ms |
get forum list: |
19ms |
get settings: |
9ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
166ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
85ms |
get tp. blocked users: |
1ms |
| others: | 477ms |
| total: | 806ms |

| 0 / 0 |
