Как стать автором
Обновить

Комментарии 53

Интересная статья. Итог охватывает любую сферу айти.
Но мне вот интересно, какой из вариантов был выбран по-дефолту все же?
При первом чтении, если вернулась ошибка, сразу перечитать список и вернуть полный, а дальше обращаться с сервером, как с медленным.
Как вариация: прочитать, встретить ошибку.
Перейти в медленный режим, прочитать «пропустив» первые 100 записей и продолжить возвращать правильные результаты.

+ «прозрачно» для пользователя.

— Пользователь о проблеме не узнает.
Решение: предупредить об этом пользователя, что соединение принудительно в медленный режим переводится, запомнить эту информацию для данного сеанса.
— Данные могут поменяться.
Решение: надо отдельно запоминать 100 записей и возвращать «не их».
Хорошо.

Но тогда подобный алгоритм должна реализовать каждая программа, которая пользуется апи сетевого клиента, а не только эксплорер.

Если же подобный алгоритм вставлять внутри сетевого клиента (прозрачно для остальных программ) см. мой комментарий в конеце статьи.
Да, модификация сетевого клиента.
Не подходит, потому что: сетевой клиент возвращает список не по завершению запроса, а частями, асинхронно, во время выполнения. Так что первая часть списка может быть возвращена (и использована программой-клиентом) еще до того, как сетевой клиент получит ошибку и поймет, что надо перечитать список.
Этот?
Поэтому мы при переходе в медленный режим возвращаем не все, а только то, что не вернулось в 1м чтении.
Итог — для программы все прозрачно, она и не знает что были проблемы, для нее это просто задержка.
окей, как вариант, принимается, хотя я думаю там слишком много тонкостей всплывет при реализации (например — недетерминированный порядок сортировки при выдаче файлов, то есть второй запрос вернет файлы в совсем другой первой сотней).

И опять же, стоит ради одного бага так усложнять основной код?
Согласен, вариант сложный в реализации и напоминает скорее заплатку, а не стройное и красивое решение.
И стоит ли? Это скорее зависит от конкретной ситуации: наличие свободного времени и политики компании по отношению к подобным вещам.
эм… а это уже проблема другой программы.
вот правда.
Ответы ещё не читал:
Реализовать этот очевидный вариант в Эксплорере, а для сторонних разработчиком описать вариант подобной реализации в KB
Еще один очевидный вариант, не описанный Реймондом в статье, но отвеченный в комментариях.

При первом чтении, если вернулась ошибка, сразу перечитать список и вернуть полный, а дальше обращаться с сервером, как с медленным.

Не подходит, потому что: сетевой клиент возвращает список не по завершению запроса, а частями, асинхронно, во время выполнения. Так что первая часть списка может быть возвращена (и использована программой-клиентом) еще до того, как сетевой клиент получит ошибку и поймет, что надо перечитать список.

раз асинхронный, тогда по факту обнаружения ошибки переключаемся в режим медленного запроса и делаем его ещё раз, при получении данных не пихаем в список уже существующие в списке файлы

а вообще труЪ способ решения — вариант настройки «только медленное соединение», база с настройками соединений, при обнаружении проблемы писать «ОЛО сервер УГ, почитайте наше КОВ где всё написанно, если хотите работать в медленном режиме нажмите [кнопку]»

труЪ linux way — по факту обнаружения бага написать 100500 гневных статей из серии «стандарты для идиотов, да?» и разместить где попало
производитель зафиксит бажину чтобы его не поливали дерьмом на форумах (опять таки никто в здравом уме не будет рекомендовать глючное железо) и к выходу вислы всё уже будет работать (WIN)

P.S.
я честно говоря не знаю как чувачки из редмонда(и индии) решили эту проблему, но учитывая сердечно любимый список кернел хаков для поддержки откровенно кривого, но популярного софта думаю что был выбран самый тупой вариант (в конце концов M$ и правильный подход к ПО вещи несовместимые)
баг в самбе был исправлен и закрыт до того, как его обнаружили в мсфт. проблема в том, что патч сложно доставить на все устройства, где его нет. на некоторые устройства его вообще нельзя доставить (прошивка не upgradable)
Креативный вариант: встретив данный код ошибки, выдавать клиенту дополнительный псевдоэлемент (каталог) типа «Show all files...»
Зайдя в него, пользователь будет получать полный список, т.к. система, встретив в пути этот псевдокаталог, его уберет и будет использовать медленный запрос.

Дополнительно можно воспользоваться 3-м способом (запоминать сервер и использовать в следующий раз другой тип запроса).
Собственно, вот он — правильный ответ.
НЛО прилетело и опубликовало эту надпись здесь
При обнаружении ошибки делать допольнительные запросы с offset.
НЛО прилетело и опубликовало эту надпись здесь
А я всетаки не понял где проблема.
Читаем блоками, отстукивая о выполнении очередного блока програме.
Полили ошибку, и хотим переиницилизироваться в медленном режиме, как писали выше, да не можем сбросить сиквенс.

Какие проблемы — врубиться в быстром режиме, запомнить 100 файлов что получается получиться, врубиться в медленном режиме, начать читать данные исключая файлы их блок листа(топ 100). Отрепортить клиента о новом блоке.

Если порядок четко соблюдается можно и не запоминать «топ 100», а просто отмотать ответ медленного варианта сразу до нужной позиции…
Блоков нет. Перемотки тоже нет. Есть API вида FindFirstFile/FindNextFile. В какой-то момент FindNext возвращает ошибку.
Запоминать файлы — не вариант, потому что придется запоминать уйму лишних данных на уровне драйвера на каждый запрос, а это очень накладно. Не запоминать — тоже не вариант, потому что альтернативный способ не обязан возвращать файлы в том же порядке, да и содержимое каталога может запросто измениться.
запоминать не уйму, а 100 записей, и можно не в драйвере а в юзерспейсе. И только если мы находимся в режиме востановления.
Перемотка == FindNextFile_inner без отстука.

Никак проблем нет. Даже если у вас сетевая карта уйдет в перегруз и на удаленном диске головка попадет на бэдблок — конечный автомат на пару стейтов и 4 ивента это пережует.
Ну, если мы говорим о фиксе в Explorer — тогда, конечно, просто. Если же о фиксе имплементации SMB в Vista, то все это драйвер, по идее, должен делать. Объем запоминаемых данных навскидку порядка 128 * sizeof(_WIN32_FIND_DATAW) ~= 74K, немало. И надо запоминать каждый раз, мы ж не знаем наперед, встретим ли ошибку.
Или вы предлагаете перечитывать в случае ошибки сначала быстрым способом, потом медленным? Хм. Во-первых, это может быть слишком долго. А, во-вторых, ненадежно. Например, сначала мы прочитали файлы с 1 по 127. На 128 получили ошибку. Перечитываем быстрым способом, получаем файлы 1, 3-128 (2й в это время удален), пропускаем их. Перечитываем медленным способом, выдаем пользователю файлы 129-500. 128-й теряется.
посему храним 128 * sizeof( _WIN32_HASH_ ) от этого самого FIND_DATAW
Да — именно это порождает проблему разряда просмотра ДВД с Белоснежкой. Но для случаев рескана директории отработает замечательно.
И да, я имел и виду что мы сваливаемся в медленный режим именно когда валимся.
Тоесть работали в быстром, упали, переключились в медленный и отработали востановление сиквенсов, продолжили в медленном.
Кстати да, хранить не _WIN32_FIND_DATAW а hash(_WIN32_FIND_DATAW)
Это всё хорошо, а если формат возвращаемых данных немного различается? Ну, допустим, в новом варианте дополнительно присутствуют пара свежих атрибутов? Или информация о файловых потоках (http://msdn.microsoft.com/en-us/library/aa364404(VS.85).aspx)?

Я не знаток SMB, просто предположение :)
В данном случае из контекса следует что имея одну точку входа(на поиск) мы умеем в ней отрабатывать оба варианта запроса в любом случае.
>Как бы вы решили такую проблему совместимости?
перестал пользоваться виндами.
Прислать патч разработчику неправильного сервера, если разработчик сервера откажется его принять, принять патч в основные дистрибутивы.

Oh, shi..., это же проприентарное ПО. Извините, извините. Еитесь сами.
Сказали же, что баг уже был пофикшен.
Просто куча железа уже продана с багом в firmware, кто должен всё это патчить?
samba — проприентарное ПО?

Вы бы читали бы что то дальше первой строчки.
Ты попутал, с самим патчем как раз проблем нет, проблема в то что есть устройства которые фиг пропатчишь, чисто технически.
1) Если есть возможность определить версию сервака. Перед запросом опрашивать эту версию, и если версия багнутая, использовать медленный вариант запросов. Информацию о багнутости/не багнутости сервера кешировать ограниченным кешем на месяц в черном списке.

2) Использовать быстрый вариант, при получении ошибки, перечитать медленным способом до последнего полученного быстрым вариантом элемента, далее отдавать клиенту.

3) Гибридный вариант 1 и 2. Регистрировать багнутость сервера в черном списке :)
А это не про Remote Differential Compression?
Ну так не честно. Я хочу знать ответ (зря статью прочитал чтоли?!), но я не специалист чтобы решать задачку :/
А нельзя сначало медленно и убедившись, что ошибки нет второй раз заходить быстро и занести в белый список *сказал делитант*
ответ будет, конечно же, но потом:)
параллельно посылаем быстрый и медленный запросы если ошибки нет игнорируем результаты меленного если ошибка возникает скрываем ее, отображаем первые сто файлов и используем результаты второго запроса для отображения остальных

минус — костыли это те ещё.
минус — реализовать можно только в приложении, но не в драйвере
все же мне кажется это проблема вендора и он должен ее решать новой прошивкой, коль уж есть обновление драйвера. Пользователи будут негодовать, конечно, но строго говоря вендор заслуживает тонн ненависти, если он не протестировал железку перед выпуском и тем более если сделал невозможным перепрошивку.
Логично, но в реальности то пользователи будут обвинять Майкрософт во всех грехах и именно им приходится делать костыли.
да не, в любом случае шишки на вендора. Если это домашний NAS — будет возврат по гарантии, если корпоративная закупка — разговор еще короче )
«А почему мой NAS работал в XP, а когда я поставил висту — перестал? Виста-отстой!»
Именно так. И фиг докажешь кому что проблема в NAS а не у MS.
Я даже не вижу смысла МС что-то доказывать. То что сотня хомячков поднимет вой не разобравшись — погоды не сделает, а впендюривать в свой код костыли, правящие чужие фейлы — верх маразма.
Делает это погоду, еще как делает. MS зарабатывает деньги на продаже софта, и если вдруг выяснится что чего то там не поддерживается просто многие не купят.
В топку «быстрые запросы» )
ну вот — я оказался прав
Читаем в быстром.
Встретили ошибку — переключились в медленный режим
Записали название сервера и работаем с ним в медленном режиме
Раз в минуту/час/день пробуем работать в быстром. Если работает — удаляем из списка.
Для серверов из списка включаем медленный режим.
Список известных серверов можно обновлять через интернет.
1. Поломать протокол — быстрый режим будем включать только на серверах, поддерживающих новый протокол. Минус — соснули пользователи не кривых nas со старым протоколом, корректно отрабатывающих быстрые запросы, выпуск кривых драйверов для сервера — и всё ломается.
2. База совместимости — всегда работаем с сервером в режиме медленных запросов, если он отсутствует в базе. Минус — очередной выпуск кривых драйверов для сервера — и капут.
3. API. Добавляем новый вызов апи(или флаг) — по умолчанию FindFile обращается по старому протоколу, если указан спец. флаг(или дёрнули FindFileEx) — ищем по быстрому методу. Плюс — старые приложения не ломаются, насрать на кривые сервера, минус — кривые дрова на сервере(апдейт) — и каюк, плюс старые приложения не получат новые возможности.
стоп-стоп-стоп… ms прогибается под баги самбы? ох нифига себе.
мс традиционно прогибается под все баги популярных устройств.
временами имеет от этого кучу проблем и потоки ненависти от адвансед юзеров, потому что прячет ошибки, а юзеры негодуют, наблюдая эту мистическую автомагию, и моляться на бубны.
с другой стороны, мс имеет н-ное количество счастливых домохозяек, которые даже не догадываются насколько китайский и кривой у них NAS.
Всегда работать в медленном режиме. После завершения вызова попробовать сделать быстрый запрос. Если он успешный, то предложить пользователю использовать быстрые вызовы для этого сервера в следующий раз. Если быстрый вызов завершился с ошибкой, то уведомить пользователя.
То же самое, но пользователю ничего не предлагать. Просто вести белый список и перепроверять сервера в фоне, по дефолту начиная общаться с «незнакомцами» в медленном режиме.
Минус — быстрое вытеснение хороших серверов из небесконечного белого списка. В итоге пользователь опять думает, что в Висте баг.
правильный варинт тот, который указали ему в комментариях
но не нужно выдавать данные пользователю пока не получили статуса ошибки или пока не удостоверились, что правильно получили от сервера полный список
есть только один минус: первый раз список будет получаться дольше, чем остальных разов, но этим минусом можно пренебречь
Интересный подход к решению проблемы.
Выглядит так: на одном из этажей подъезда (без лифта) жители заваливают площадку хламом, пройти невозможно. Варианты решения проблемы:
1. Ничего не делать
2. Повесить табличку с предупреждением перед входом на эту клетку.
3. Повесить табличку и нанять таджика для уборки.
4. Под потолком этой клетки подвесить перекладины, чтоб проходить клетку на руках. Пройти смогут только адвансед юзеры.
5. Просто нанять таджика, но скидываться на него придется даже тем, кто живет ниже злополучной клетки.

Неудивительно, что в итоге из ПО получается непонятная смесь, подпертая костылями со всех сторон. Зато для домохозяек — «работает», ага.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории