michaellukashov / Far-NetBox

SFTP/SCP/FTP/FTPS/WebDAV/S3 client for Far Manager 3 (http://farmanager.com/)
https://forum.farmanager.com/viewtopic.php?t=6317
GNU General Public License v2.0
159 stars 52 forks source link

Реализация работы с симлинками FTP. Текущая вызывает справедливые нарекания пользователей. #130

Open VictorVG opened 9 years ago

VictorVG commented 9 years ago

Текущая реализация механизма работы с симлинками FTP вызывает много справедливых нареканий пользователей поскольку трактовать любой симлинк как ссылку на файл было временным решением ставшим постоянным. Я поднял лог изменений FileZilla и в нём мы видим что в версии 3.1.5 это реализовано предельно просто и красиво:

Handle symbolic links on servers. If trying to access a symbolic link, FileZilla will first try to CWD into it, and if that fails, will treat it as a file instead. During recursive operations, any directory link encountered will not be followed, but file links will be downloaded.

любой симлинк сначала трактуем как симлинк на каталог и пробуем перейти по нему используя команду CWD <symlink> и проверяем ответ сервера. Если он отрицательный, то переход не произойдёт и симлинк трактуется как линк на файл который ставится в очередь на скачивание.

А почему бы и нам не использовать этот механизм тем более что его реализация не потребует чрезмерно больших накладных расходов? Мы не можем получить тип цели удалённого симлинка, но мы можем по умолчанию считать его ссылкой на каталог и в случае неудачного перехода в него выдать GET для скачивания файла:, а при удаче выдать в нём LIST:

cwd URL if server_responds equ error then get URL else list URL end

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

VictorVG commented 9 years ago

Замечатательно вышло! Вот как у нас всё выглядело в ь354 и в ь356:

netbox_b354_ws_b356

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

Тестовый комплект NetBox v2.1.40.356

https://yadi.sk/d/fDJFsgc3c6AaY - FarNetBox-2.1.40_Far3_x64.7z https://yadi.sk/d/DQkPLzo8cbvDP - FarNetBox-2.1.40_Far3_x86.7z

VictorVG commented 9 years ago

Новый инц я не стал открывать, а переоткрыл этот чтобы нам было проще отследить этапы работы. А как всё сделам закроем как полностью отработанную задачу не дробя её на фрагменты. Зачем нам путаница?

Ситуации приводящие к AV в Far.mainImpl()

Вылезла интересная особенность - если на FTP есть вложенные ссылки, то можем и AV получить со "странным" (мы его тут не ожидаем) предваряющим его сообщением об ошибке и зависанием Far до его возникновения, при этом вне зависимости от состояния опций запоминания изменений дерева и кэширования каталогов в момент сбоя в качестве удалённого в диалоге Папки -> Каталог на сервере запоминается (наша настройка перезаписывается) тот каталог где произошла ошибка и сбой повторяется сразу же при следующем подключении к этому серверу.

Я это случайно обнаружил на ftp://ftp.pcvsd.org/pub/ . В FileZilla мы там видим такую структуру каталогов:

tree

каталог /pub/mirror/9.1-RELEASE/amd64/ сам по себе представляет рекурусивную цепочку симлинков, и при получении LIST мы видим её уровни, на последнем из них наш алгоритм доходит до симлинков на файлы и пытается получить их размер что и вызывает его ошибку:

b356

приводящую в итоге к AV (по данным отладчика падаем на int 3, треды завершаются кодом 0х0):

b4176_nb_2140356

Возможное решение для устранения подобных ситуаций

А если нам чуть изменить логику алгоритма в случае если внизу дерева каталогов лежат симлинки на файлы ( не один, а несколько) - отказаться от получения размера файлов и просто выводить их тип как симлинк? Даст оператор команду - скачаем, не даст - просто выводим для них в дереве тип симлинк на панели.

Я думаю что это избавит нас от возникновения подобных AV, особенно на больших файлах, тем более что размеры DVD образов PC-BSD обычно больше 3 Гб (~ 3,5 Гб).

VictorVG commented 9 years ago

Это уже так, лирика - последовал совету выкинуть макрос отключавший FTP сессию для билдов ниже 350, но поскольку звать панель команд NetBox через F11 иной раз не успеваешь, то использовал то же имя файла NetBox.lua для иного скрипта:

-- По RAltBackSlash ("RAlt\") зовём меню команд NetBox-а не дёргая F11. v1.0
-- Скрипт работает только в панели NetBox-а чтобы другим не мешал (by design).
--
-- ©VictorVG, 19.11.2014 06:34:52 +0300
--

local NBID="42E4AEB1-A230-44F4-B33C-F195BB654931"
local NBCID="FE360D25-5004-40C1-97D5-54A2EED8E675"
local NBWID="42e4aeb1-a230-44f4-b33c-f195bb654931"

Macro{
  uid="BD77EA4F-C982-4ADB-BDE9-B4AD257ADC7E";
  area="Shell";
  key="RAltBackSlash";
  description="Show NetBox command panel";
  flags="NoFilePanels";
  condition=function() return APanel.Plugin and win.Uuid(panel.GetPanelInfo(nil, 1).OwnerGuid) == NBWID end;
  action=function() Plugin.Menu(NBID,NBCID) end;
}

а по мере нужды его возможности будут расширятся. Может где и он пользу принесёт, хотя проверки в Conditions и Falgs для надёжности специально сдублированы.

michaellukashov commented 9 years ago

Спасибо. Только что выложил изменение, которое как мне кажется решит проблему. Проверил на сайте ftp.hp.com - там тоже возникала ошибка.

VictorVG commented 9 years ago

Миша! Я сейчас вряд-ли смогу собрать - что-то странное с видеоподсистемой сразу на трёх машинах - произошла попытка обновления драйверов NVIDIA и результат не ясный - процесс зависает на установе HQ Audio декодера, после Х-ы перезапускаются на любую кнопку KBD с сообщением "Видеодрайвер перестал отвечать и был восстановлен". Попытался ОС поднять из бэкапа - бесполезно. Придётся все машины сегмента чистить нулями и ставить ОС и ПО заново. Этой работы мне не хватало.:(

VictorVG commented 9 years ago

Миша! Небольшое уточнение для README.md (хорошо я это вовремя заметил и у себя поправил) в пункте:

Either open src/NetBox/NetBox.sln in Visual Studio, or compile NetBox plugin on the command line as follows:

    cmd /c %VS100COMNTOOLS%\..\..\VC\vcvarsall.bat x86 && devenv NetBox.sln /Build "Release|Win32" /USEENV /Project "NetBox"
    cmd /c %VS100COMNTOOLS%\..\..\VC\vcvarsall.bat x86_amd64 && devenv NetBox.sln /Build "Release|x64" /USEENV /Project "NetBox"

фрагмент %VS100COMNTOOLS%\..\..\VC\vcvarsall.bat надо обязательно заключить в кавычки иначе если компилятор стоит в %ProgarmFiles% при запуске команды получим сообщение ОС об ошибке типа "Путь C:\Program не найден" - его вызовет пробел в имени каталога. Достаточно этот фрагмент изменить так:

cmd /c "%VS100COMNTOOLS%\..\..\VC\vcvarsall.bat" x86 && devenv NetBox.sln /Build "Release|Win32" /USEENV /Project "NetBox"
cmd /c "%VS100COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64 && devenv NetBox.sln /Build "Release|x64" /USEENV /Project "NetBox"

и ошибки не будет, ну а нас не будут спрашивать как её устранить.. :)

VictorVG commented 9 years ago

Угу, сумел собрать на другой машине b357 и посмотрел на PC-BSD и HP - AV нет, это мы устранили и в итоге видим файлы на ftp.pcbsd.com (упаковка ISO образов в тарбаллы у Криса давно стала обычным приёмом работы, иное дело что замена в PC-BSD 10 BTX на GRUB как загрузчика по умолчанию мне стоила одной из тестовых FreeBSD 9 систем - GRUB слайс положил, что BTX никогда бы не сделал. :( Я ещё буду там смотреть что он на диске натворил чтобы после обходить потенциально опасные места).

Вот что мы сейчас видим в "проблемном" каталоге:

far30b4187_netbox-2 1 40 357

так что наша идея после коррекции похоже работает. Есть правда одна настройка FTP которую стоит поправить:

1) поставить для FTP тайм-аут по умолчанию не 15 сек как сейчас, а 90 -120 сек т.к. механизм установления FTP соединения из-за применяемых для балансировки нагрузки на сервера ограничений скорости для каждого подключения в 90% -95% случаев не успевает отработать алгоритм подключения быстрее чем за 85 - 87 сек и при малом тайм-ауте мы получаем бесконечные реконнекты в сопровождении пугала "сервер не ответил вовремя", а увеличим тайм-аут - сервер ответил и алгоритм пошёл дальше, а у нас нет пугающего пользователя ошибочного сообщения о "недоступности" сервера. Я иной раз эту настройку и больше ставлю - до 130 - 150 секунд что помогает подключится к сильно загруженным серверам которые и по 100 - 120 сек могут не отвечать на входящий запрос соединения. Тут главное иметь запас по времени ожидания server-repond чуть больший (обычно + 5 - 10 секунд с учётом сквозной задержки сети достаточно, а более 20 сек запаса мне вообще ни разу не потребовалось выставлять) чем максимальное время его ответа.

И ещё что нам не надо менять - настройку по умолчанию что при создании нового FTP соединения b357 сам ставит имя пользователя "anonymouse" и пустой пароль. Если что сервер сам на пароль попросит. На это то же были нарекания, в т.ч. у меня в ПМ на руборде есть такие просьбы от ребят.

VictorVG commented 9 years ago

Изменения по тайм-ауту видел, погонял легонько - вроде всё более менее стабильно работает. С реадме спасибо.

P.S.

Частично починил своё железо - видеокарта полетела и по шине зацепила чипсет. Видеоплату переставил с другой машины, туда новую купил, а вот с чипсетом надо перепаивать - глючит PCI-E, да нет особого желания именно с этой мамкой возится.:)

P.P.S.

С мамкой поступил просто - купил у ребят взамен другую на P45 - дорога до мастерской и обратно день, пару часов перепаивать и не факт что заведётся - БП по +12V и чипсет и видеоплату поджарил.:) Решил что проще сделать по дороге крюк на полчаса и отдать за ASUS P5Q SE 1500 руб чем искать донора, отпаивать чипсет, сдувать тут дохлый, выставлять его на площадки и паять после волной с 10-ю шансами из 100 что работа окажется насмарку.

VictorVG commented 9 years ago

Ну вот, и вторую машину оживил - работает! Теперь софт переставляю с нуля - ось получив новое железо сдрапала в панику ядра.:) По возможностям новая машина стала много лучше - как никак P45 не чета G41 который там до этого стоял.:)

VictorVG commented 9 years ago

Миша! Тут при сборке х64 ошибка вылетает:

src\netbox\../core/FileOperationProgress.cpp(34) : error C2664
: TValueRestorer<T>::TValueRestorer(T &): невозможно преобразовать параметр 1 из "uintptr_t" в "uint32_t &"
        with
        [
            T=uint32_t
        ]
NMAKE : fatal error U1077: C:\PROGRA~1\MICROS~2.0\VC\bin\X86_AM~1\cl.exe : возвращенный код "0x2 Stop.
NMAKE : fatal error U1077: "C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN\nmake.exe" : возвращенный код "0x2" Stop.
NMAKE : fatal error U1077: "C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN\nmake.exe" : возвращенный код "0x2" Stop.

вот в этом фрагменте кода:

void TFileOperationProgressType::AssignButKeepSuspendState(const TFileOperationProgressType & Other)
{
  TValueRestorer<uint32_t > SuspendTimeRestorer(FSuspendTime);
  TValueRestorer<bool> SuspendedRestorer(Suspended);

  *this = Other;
}

попробовал поправить TValueRestorer<uint32_t > вместо TValueRestorer<uint32_t> но у меня х64 не собрался той же ошибкой. Значит я неверно думаю.