Pull to refresh

Допиливание exdupe.exe — шустрого дедуплицирующего архиватора

Reading time 3 min
Views 7.7K
Какое-то время назад я столкнулся с неприятной проблемой — понадобилось бэкапить несколько виртуальных машин. Надо сказать, что бэкапить для меня — значит иметь в результате не только архив с последней копией, а небольшую кучку этих архивов, сделанных по заданной схеме. Батничек для архивации, понятное дело, был написан быстро и работал без нареканий, но размер… Размер комплекта бэкапов получался огромным. Особенно печалило то, что это были почти одинаковые виртуалки, и почти одинаковые бэкапы этих виртуалок. Так я узнал слово «дедупликация» и «дифф» и начал подыскивать какую-нибудь утилиту для сжатия с дедупликацией.

Разные утилиты предлагали разные подходы к сжатию близких по содержанию файлов, но общим оказалось одно — выбираешь один исходный файл и натравливаешь утилиту на остальные — она определяет разницу между исходным и остальными и архивирует результат, а когда нужно развернуть — указываешь исходный файл и архив с диффом, утилита сама всё развернет.
Короче, исходник нужно было где-то иметь в развернутом виде. Всё время — и в момент архивации, и в момент разархивирования. То есть «картина маслом» — у меня пяток виртуалок, я хочу сегодня сделать архив с разницей между сегодняшними виртуалками и вчерашними — я должен:
— со вчера заготовить полную копию всего хозяйства,
— потом запустить утилиту, она сделает дифф и архив диффа.
Теперь я хочу куда-то скопировать всё это — я же не буду вчерашние данные (исходные) перетаскивать в несжатом виде — мне придется заархивировать и исходник. Если завтра мне понадобится сделать дифф между вчера и завтра — исходник должен быть доступен в несжатом и нетронутом виде — либо копия вчерашнего состояния, либо архив, который придется разворачивать. Если мне потребуется развернуть архив на новом хосте — сначала нужно развернуть исходник, потом развернуть сам дифф.
Ну ладно место на диске — можно купить, но время! Такая куча времени уходит на разархивирование исходника! Но нашелся он — архиватор, который умел делать всё правильно — загонять исходник в архив, причем с дедупликацией, а потом делать диффы прямо со сжатого исходника, причем скорость архивации/разархивирования упирается в скорость жесткого диска. Клёво! Но под Windows 2003 не работает. Как вы понимаете, если бы всё работало само — я бы эту статью не писал.

Итак, теперь — амбула.
Архиватор называется exdupe, он был типа фриварный, с частично доступным исходным кодом. Частично — потому что библиотека дедупликатора линковалась статически, а выложен был код на утилиту командной строки (сейчас выложен весь код). Всё лежит в виде проекта под Visual Studio 2012. Запускалось всё только под 64 битной версией винды (у меня — Win2003), и при запуске выдавало ошибку:
Entry Point Not Found
The procedure entry point VssFreeSnapshotPropertiesInternal could not be located in the dynamic link library VSSAPI.DLL.
image
Исходник был тут же скачан с сайта программы (я допиливал версию 0.5.0).
Причина ошибки — несовместимость версий библиотеки VSSAPI.dll у моей винды и у того либа, который был подключен в проекте.
Поковыряв исходник, я понял, что самый простой путь — просто отключить поддержку Shadow Copy — убрать вызовы библиотеки VSS и обкорнать функции, отвечающие за обращение к VSS. Надо сказать, код был написан прямыми руками, хоть и с ошибками, и функций оказалось всего две и находились они в файле «shadow\shadow.cpp».
Вот что мы делаем:
  1. находим функцию void unshadow(void)
  2. комментим строку 342:
    	  VssFreeSnapshotProperties(&prop.Obj.Snap);
    

    станет:
    	  //removing shadowing
    	  //VssFreeSnapshotProperties(&prop.Obj.Snap);
    
  3. перед строкой 330
     ULONG fetched = 0;
    


    добавляем:
    //remove shadowing
    return 1;
    

  4. находим функцию int shadow(vector volumes),
    комментим строку 177:
      hr = ::CreateVssBackupComponents(&comp);
    

    станет:
      //remove shadowing
      //hr = ::CreateVssBackupComponents(&comp);
    


    5. перед строкой 157:

      // Initialize COM and open ourselves wide for callbacks by
      // CoInitializeSecurity.
      HRESULT hr;
    


    втыкаем:
    //remove shadowing
    return 1;
    


  5. Перед сборкой — рекомендую поменять имя экзешника в свойствах проекта, чтобы не перепутать с авторским «exdupe.exe». Типа «exdupe-050-noshadow.exe».
    Собираем, запускаем — работает!
    Алгоритм реально шустрый, конечно отжирает память и грузит ядра, но это можно настроить — мне комфортно запускать в два потока с ключиком "-t2". На обычном жестком диске дедупликация исходника со сжатием:
    — 65.7 ГБ за 44 мин = 24.8 МБ/с
    — сжал до 24.1 ГБ = коэффициент сжатия 0.37
    дедупликация на следующий день
    — время обработки 10 мин. 20 с. = 106 МБ/с
    — дифф сжат до 2.1 ГБ

    Отдельно скажу, что ограничение на запуск только из-под 64-битных версий ОС введено искусственно, и может быть отключено, при этом архивы, созданные 64-битной программой нормально разворачиваются 32-битной, правда рекордных скоростей тут и близко нет (и ждать не надо).
    Бинарники и полные тексты проекта не выкладываю из-за ограничений лицензии.

    Сайт утилиты exdupe — www.exdupe.com
    Исходники: www.exdupe.com/old
Tags:
Hubs:
+3
Comments 6
Comments Comments 6

Articles