backup_engine_test.cc 182 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #if !defined(OS_WIN)
  10. #include "rocksdb/utilities/backup_engine.h"
  11. #include <algorithm>
  12. #include <array>
  13. #include <atomic>
  14. #include <cstddef>
  15. #include <cstdint>
  16. #include <exception>
  17. #include <limits>
  18. #include <memory>
  19. #include <random>
  20. #include <stdexcept>
  21. #include <string>
  22. #include <utility>
  23. #include "db/db_impl/db_impl.h"
  24. #include "db/db_test_util.h"
  25. #include "env/composite_env_wrapper.h"
  26. #include "env/env_chroot.h"
  27. #include "file/filename.h"
  28. #include "port/port.h"
  29. #include "port/stack_trace.h"
  30. #include "rocksdb/advanced_options.h"
  31. #include "rocksdb/env.h"
  32. #include "rocksdb/file_checksum.h"
  33. #include "rocksdb/rate_limiter.h"
  34. #include "rocksdb/statistics.h"
  35. #include "rocksdb/transaction_log.h"
  36. #include "rocksdb/types.h"
  37. #include "rocksdb/utilities/options_util.h"
  38. #include "rocksdb/utilities/stackable_db.h"
  39. #include "test_util/sync_point.h"
  40. #include "test_util/testharness.h"
  41. #include "test_util/testutil.h"
  42. #include "util/cast_util.h"
  43. #include "util/mutexlock.h"
  44. #include "util/random.h"
  45. #include "util/rate_limiter_impl.h"
  46. #include "util/stderr_logger.h"
  47. #include "util/string_util.h"
  48. #include "utilities/backup/backup_engine_impl.h"
  49. namespace ROCKSDB_NAMESPACE {
  50. namespace {
  51. using ShareFilesNaming = BackupEngineOptions::ShareFilesNaming;
  52. const auto kLegacyCrc32cAndFileSize =
  53. BackupEngineOptions::kLegacyCrc32cAndFileSize;
  54. const auto kUseDbSessionId = BackupEngineOptions::kUseDbSessionId;
  55. const auto kFlagIncludeFileSize = BackupEngineOptions::kFlagIncludeFileSize;
  56. const auto kNamingDefault = kUseDbSessionId | kFlagIncludeFileSize;
  57. class DummyDB : public StackableDB {
  58. public:
  59. /* implicit */
  60. DummyDB(const Options& options, const std::string& dbname)
  61. : StackableDB(nullptr),
  62. options_(options),
  63. dbname_(dbname),
  64. deletions_enabled_(true),
  65. sequence_number_(0) {}
  66. SequenceNumber GetLatestSequenceNumber() const override {
  67. return ++sequence_number_;
  68. }
  69. const std::string& GetName() const override { return dbname_; }
  70. Env* GetEnv() const override { return options_.env; }
  71. using DB::GetOptions;
  72. Options GetOptions(ColumnFamilyHandle* /*column_family*/) const override {
  73. return options_;
  74. }
  75. DBOptions GetDBOptions() const override { return DBOptions(options_); }
  76. Status EnableFileDeletions() override {
  77. EXPECT_TRUE(!deletions_enabled_);
  78. deletions_enabled_ = true;
  79. return Status::OK();
  80. }
  81. Status DisableFileDeletions() override {
  82. EXPECT_TRUE(deletions_enabled_);
  83. deletions_enabled_ = false;
  84. return Status::OK();
  85. }
  86. ColumnFamilyHandle* DefaultColumnFamily() const override { return nullptr; }
  87. Status GetLiveFilesStorageInfo(
  88. const LiveFilesStorageInfoOptions& opts,
  89. std::vector<LiveFileStorageInfo>* files) override {
  90. uint64_t number;
  91. FileType type;
  92. files->clear();
  93. for (auto& f : live_files_) {
  94. bool success = ParseFileName(f, &number, &type);
  95. if (!success) {
  96. return Status::InvalidArgument("Bad file name: " + f);
  97. }
  98. files->emplace_back();
  99. LiveFileStorageInfo& info = files->back();
  100. info.relative_filename = f;
  101. info.directory = dbname_;
  102. info.file_number = number;
  103. info.file_type = type;
  104. if (type == kDescriptorFile) {
  105. info.size = 100; // See TestFs::GetChildrenFileAttributes below
  106. info.trim_to_size = true;
  107. } else if (type == kCurrentFile) {
  108. info.size = 0;
  109. info.trim_to_size = true;
  110. } else {
  111. info.size = 200; // See TestFs::GetChildrenFileAttributes below
  112. }
  113. if (opts.include_checksum_info) {
  114. info.file_checksum = kUnknownFileChecksum;
  115. info.file_checksum_func_name = kUnknownFileChecksumFuncName;
  116. }
  117. }
  118. return Status::OK();
  119. }
  120. // To avoid FlushWAL called on stacked db which is nullptr
  121. using DB::FlushWAL;
  122. Status FlushWAL(bool /*sync*/) override { return Status::OK(); }
  123. std::vector<std::string> live_files_;
  124. private:
  125. Options options_;
  126. std::string dbname_;
  127. bool deletions_enabled_;
  128. mutable SequenceNumber sequence_number_;
  129. }; // DummyDB
  130. class TestFs : public FileSystemWrapper {
  131. public:
  132. explicit TestFs(const std::shared_ptr<FileSystem>& t)
  133. : FileSystemWrapper(t) {}
  134. const char* Name() const override { return "TestFs"; }
  135. class DummySequentialFile : public FSSequentialFile {
  136. public:
  137. explicit DummySequentialFile(bool fail_reads)
  138. : FSSequentialFile(), rnd_(5), fail_reads_(fail_reads) {}
  139. IOStatus Read(size_t n, const IOOptions&, Slice* result, char* scratch,
  140. IODebugContext*) override {
  141. if (fail_reads_) {
  142. return IOStatus::IOError();
  143. }
  144. size_t read_size = (n > size_left) ? size_left : n;
  145. for (size_t i = 0; i < read_size; ++i) {
  146. scratch[i] = rnd_.Next() & 255;
  147. }
  148. *result = Slice(scratch, read_size);
  149. size_left -= read_size;
  150. return IOStatus::OK();
  151. }
  152. IOStatus Skip(uint64_t n) override {
  153. size_left = (n > size_left) ? size_left - n : 0;
  154. return IOStatus::OK();
  155. }
  156. private:
  157. size_t size_left = 200;
  158. Random rnd_;
  159. bool fail_reads_;
  160. };
  161. class CheckIOOptsSequentialFile : public FSSequentialFileOwnerWrapper {
  162. public:
  163. CheckIOOptsSequentialFile(std::unique_ptr<FSSequentialFile>&& f,
  164. const std::string& file_name)
  165. : FSSequentialFileOwnerWrapper(std::move(f)) {
  166. is_sst_file_ = file_name.find(".sst") != std::string::npos;
  167. }
  168. IOStatus Read(size_t n, const IOOptions& options, Slice* result,
  169. char* scratch, IODebugContext* dbg) override {
  170. // Backup currently associates only SST read with rate limiter priority
  171. assert(!is_sst_file_ || options.rate_limiter_priority ==
  172. kExpectedBackupReadRateLimiterPri);
  173. IOStatus rv = target()->Read(n, options, result, scratch, dbg);
  174. return rv;
  175. }
  176. IOStatus PositionedRead(uint64_t offset, size_t n, const IOOptions& options,
  177. Slice* result, char* scratch,
  178. IODebugContext* dbg) override {
  179. // Backup currently associates only SST read with rate limiter priority
  180. assert(!is_sst_file_ || options.rate_limiter_priority ==
  181. kExpectedBackupReadRateLimiterPri);
  182. IOStatus rv =
  183. target()->PositionedRead(offset, n, options, result, scratch, dbg);
  184. return rv;
  185. }
  186. private:
  187. static const Env::IOPriority kExpectedBackupReadRateLimiterPri =
  188. Env::IO_LOW;
  189. bool is_sst_file_;
  190. };
  191. IOStatus NewSequentialFile(const std::string& f, const FileOptions& file_opts,
  192. std::unique_ptr<FSSequentialFile>* r,
  193. IODebugContext* dbg) override {
  194. MutexLock l(&mutex_);
  195. if (dummy_sequential_file_) {
  196. r->reset(
  197. new TestFs::DummySequentialFile(dummy_sequential_file_fail_reads_));
  198. return IOStatus::OK();
  199. } else if (check_iooptions_sequential_file_) {
  200. std::unique_ptr<FSSequentialFile> file;
  201. IOStatus s =
  202. FileSystemWrapper::NewSequentialFile(f, file_opts, &file, dbg);
  203. if (s.ok()) {
  204. r->reset(new TestFs::CheckIOOptsSequentialFile(std::move(file), f));
  205. }
  206. return s;
  207. } else {
  208. IOStatus s = FileSystemWrapper::NewSequentialFile(f, file_opts, r, dbg);
  209. if (s.ok()) {
  210. if ((*r)->use_direct_io()) {
  211. ++num_direct_seq_readers_;
  212. }
  213. ++num_seq_readers_;
  214. }
  215. return s;
  216. }
  217. }
  218. IOStatus NewWritableFile(const std::string& f, const FileOptions& file_opts,
  219. std::unique_ptr<FSWritableFile>* r,
  220. IODebugContext* dbg) override {
  221. MutexLock l(&mutex_);
  222. written_files_.push_back(f);
  223. if (limit_written_files_ == 0) {
  224. return IOStatus::NotSupported("Limit on written files reached");
  225. }
  226. limit_written_files_--;
  227. IOStatus s = FileSystemWrapper::NewWritableFile(f, file_opts, r, dbg);
  228. if (s.ok()) {
  229. if ((*r)->use_direct_io()) {
  230. ++num_direct_writers_;
  231. }
  232. ++num_writers_;
  233. }
  234. return s;
  235. }
  236. IOStatus NewRandomAccessFile(const std::string& f,
  237. const FileOptions& file_opts,
  238. std::unique_ptr<FSRandomAccessFile>* r,
  239. IODebugContext* dbg) override {
  240. MutexLock l(&mutex_);
  241. IOStatus s = FileSystemWrapper::NewRandomAccessFile(f, file_opts, r, dbg);
  242. if (s.ok()) {
  243. if ((*r)->use_direct_io()) {
  244. ++num_direct_rand_readers_;
  245. }
  246. ++num_rand_readers_;
  247. }
  248. return s;
  249. }
  250. IOStatus DeleteFile(const std::string& f, const IOOptions& options,
  251. IODebugContext* dbg) override {
  252. MutexLock l(&mutex_);
  253. if (fail_delete_files_) {
  254. return IOStatus::IOError();
  255. }
  256. EXPECT_GT(limit_delete_files_, 0U);
  257. limit_delete_files_--;
  258. return FileSystemWrapper::DeleteFile(f, options, dbg);
  259. }
  260. IOStatus DeleteDir(const std::string& d, const IOOptions& options,
  261. IODebugContext* dbg) override {
  262. MutexLock l(&mutex_);
  263. if (fail_delete_files_) {
  264. return IOStatus::IOError();
  265. }
  266. return FileSystemWrapper::DeleteDir(d, options, dbg);
  267. }
  268. void AssertWrittenFiles(std::vector<std::string>& should_have_written) {
  269. MutexLock l(&mutex_);
  270. std::sort(should_have_written.begin(), should_have_written.end());
  271. std::sort(written_files_.begin(), written_files_.end());
  272. ASSERT_EQ(should_have_written, written_files_);
  273. }
  274. void ClearWrittenFiles() {
  275. MutexLock l(&mutex_);
  276. written_files_.clear();
  277. }
  278. void SetLimitWrittenFiles(uint64_t limit) {
  279. MutexLock l(&mutex_);
  280. limit_written_files_ = limit;
  281. }
  282. void SetLimitDeleteFiles(uint64_t limit) {
  283. MutexLock l(&mutex_);
  284. limit_delete_files_ = limit;
  285. }
  286. void SetDeleteFileFailure(bool fail) {
  287. MutexLock l(&mutex_);
  288. fail_delete_files_ = fail;
  289. }
  290. void SetDummySequentialFile(bool dummy_sequential_file) {
  291. MutexLock l(&mutex_);
  292. dummy_sequential_file_ = dummy_sequential_file;
  293. }
  294. void SetDummySequentialFileFailReads(bool dummy_sequential_file_fail_reads) {
  295. MutexLock l(&mutex_);
  296. dummy_sequential_file_fail_reads_ = dummy_sequential_file_fail_reads;
  297. }
  298. void SetCheckIOOptionsSequentialFile(bool check_iooptions_sequential_file) {
  299. MutexLock l(&mutex_);
  300. check_iooptions_sequential_file_ = check_iooptions_sequential_file;
  301. }
  302. void SetGetChildrenFailure(bool fail) { get_children_failure_ = fail; }
  303. IOStatus GetChildren(const std::string& dir, const IOOptions& io_opts,
  304. std::vector<std::string>* r,
  305. IODebugContext* dbg) override {
  306. if (get_children_failure_) {
  307. return IOStatus::IOError("SimulatedFailure");
  308. }
  309. return FileSystemWrapper::GetChildren(dir, io_opts, r, dbg);
  310. }
  311. // Some test cases do not actually create the test files (e.g., see
  312. // DummyDB::live_files_) - for those cases, we mock those files' attributes
  313. // so CreateNewBackup() can get their attributes.
  314. void SetFilenamesForMockedAttrs(const std::vector<std::string>& filenames) {
  315. filenames_for_mocked_attrs_ = filenames;
  316. }
  317. IOStatus GetChildrenFileAttributes(const std::string& dir,
  318. const IOOptions& options,
  319. std::vector<FileAttributes>* result,
  320. IODebugContext* dbg) override {
  321. if (filenames_for_mocked_attrs_.size() > 0) {
  322. for (const auto& filename : filenames_for_mocked_attrs_) {
  323. uint64_t size_bytes = 200; // Match TestFs
  324. if (filename.find("MANIFEST") == 0) {
  325. size_bytes = 100; // Match DummyDB::GetLiveFiles
  326. }
  327. result->push_back({dir + "/" + filename, size_bytes});
  328. }
  329. return IOStatus::OK();
  330. }
  331. return FileSystemWrapper::GetChildrenFileAttributes(dir, options, result,
  332. dbg);
  333. }
  334. IOStatus GetFileSize(const std::string& f, const IOOptions& options,
  335. uint64_t* s, IODebugContext* dbg) override {
  336. if (filenames_for_mocked_attrs_.size() > 0) {
  337. auto fname = f.substr(f.find_last_of('/') + 1);
  338. auto filename_iter = std::find(filenames_for_mocked_attrs_.begin(),
  339. filenames_for_mocked_attrs_.end(), fname);
  340. if (filename_iter != filenames_for_mocked_attrs_.end()) {
  341. *s = 200; // Match TestFs
  342. if (fname.find("MANIFEST") == 0) {
  343. *s = 100; // Match DummyDB::GetLiveFiles
  344. }
  345. return IOStatus::OK();
  346. }
  347. return IOStatus::NotFound(fname);
  348. }
  349. return FileSystemWrapper::GetFileSize(f, options, s, dbg);
  350. }
  351. void SetCreateDirIfMissingFailure(bool fail) {
  352. create_dir_if_missing_failure_ = fail;
  353. }
  354. IOStatus CreateDirIfMissing(const std::string& d, const IOOptions& options,
  355. IODebugContext* dbg) override {
  356. if (create_dir_if_missing_failure_) {
  357. return IOStatus::IOError("SimulatedFailure");
  358. }
  359. return FileSystemWrapper::CreateDirIfMissing(d, options, dbg);
  360. }
  361. void SetNewDirectoryFailure(bool fail) { new_directory_failure_ = fail; }
  362. IOStatus NewDirectory(const std::string& name, const IOOptions& io_opts,
  363. std::unique_ptr<FSDirectory>* result,
  364. IODebugContext* dbg) override {
  365. if (new_directory_failure_) {
  366. return IOStatus::IOError("SimulatedFailure");
  367. }
  368. return FileSystemWrapper::NewDirectory(name, io_opts, result, dbg);
  369. }
  370. void ClearFileOpenCounters() {
  371. MutexLock l(&mutex_);
  372. num_rand_readers_ = 0;
  373. num_direct_rand_readers_ = 0;
  374. num_seq_readers_ = 0;
  375. num_direct_seq_readers_ = 0;
  376. num_writers_ = 0;
  377. num_direct_writers_ = 0;
  378. }
  379. int num_rand_readers() { return num_rand_readers_; }
  380. int num_direct_rand_readers() { return num_direct_rand_readers_; }
  381. int num_seq_readers() { return num_seq_readers_; }
  382. int num_direct_seq_readers() { return num_direct_seq_readers_; }
  383. int num_writers() { return num_writers_; }
  384. // FIXME(?): unused
  385. int num_direct_writers() { return num_direct_writers_; }
  386. private:
  387. port::Mutex mutex_;
  388. bool dummy_sequential_file_ = false;
  389. bool dummy_sequential_file_fail_reads_ = false;
  390. bool check_iooptions_sequential_file_ = false;
  391. std::vector<std::string> written_files_;
  392. std::vector<std::string> filenames_for_mocked_attrs_;
  393. uint64_t limit_written_files_ = 1000000;
  394. uint64_t limit_delete_files_ = 1000000;
  395. bool fail_delete_files_ = false;
  396. bool get_children_failure_ = false;
  397. bool create_dir_if_missing_failure_ = false;
  398. bool new_directory_failure_ = false;
  399. // Keeps track of how many files of each type were successfully opened, and
  400. // out of those, how many were opened with direct I/O.
  401. std::atomic<int> num_rand_readers_{};
  402. std::atomic<int> num_direct_rand_readers_{};
  403. std::atomic<int> num_seq_readers_{};
  404. std::atomic<int> num_direct_seq_readers_{};
  405. std::atomic<int> num_writers_{};
  406. std::atomic<int> num_direct_writers_{};
  407. }; // TestFs
  408. class FileManager : public EnvWrapper {
  409. public:
  410. explicit FileManager(Env* t) : EnvWrapper(t), rnd_(5) {}
  411. const char* Name() const override { return "FileManager"; }
  412. Status GetRandomFileInDir(const std::string& dir, std::string* fname,
  413. uint64_t* fsize) {
  414. std::vector<FileAttributes> children;
  415. auto s = GetChildrenFileAttributes(dir, &children);
  416. if (!s.ok()) {
  417. return s;
  418. } else if (children.size() <= 2) { // . and ..
  419. return Status::NotFound("Empty directory: " + dir);
  420. }
  421. assert(fname != nullptr);
  422. while (true) {
  423. int i = rnd_.Next() % children.size();
  424. fname->assign(dir + "/" + children[i].name);
  425. *fsize = children[i].size_bytes;
  426. return Status::OK();
  427. }
  428. // should never get here
  429. assert(false);
  430. return Status::NotFound("");
  431. }
  432. Status DeleteRandomFileInDir(const std::string& dir) {
  433. std::vector<std::string> children;
  434. Status s = GetChildren(dir, &children);
  435. if (!s.ok()) {
  436. return s;
  437. }
  438. while (true) {
  439. int i = rnd_.Next() % children.size();
  440. return DeleteFile(dir + "/" + children[i]);
  441. }
  442. // should never get here
  443. assert(false);
  444. return Status::NotFound("");
  445. }
  446. Status AppendToRandomFileInDir(const std::string& dir,
  447. const std::string& data) {
  448. std::vector<std::string> children;
  449. Status s = GetChildren(dir, &children);
  450. if (!s.ok()) {
  451. return s;
  452. }
  453. while (true) {
  454. int i = rnd_.Next() % children.size();
  455. return WriteToFile(dir + "/" + children[i], data);
  456. }
  457. // should never get here
  458. assert(false);
  459. return Status::NotFound("");
  460. }
  461. Status CorruptFile(const std::string& fname, uint64_t bytes_to_corrupt) {
  462. std::string file_contents;
  463. Status s = ReadFileToString(this, fname, &file_contents);
  464. if (!s.ok()) {
  465. return s;
  466. }
  467. s = DeleteFile(fname);
  468. if (!s.ok()) {
  469. return s;
  470. }
  471. for (uint64_t i = 0; i < bytes_to_corrupt; ++i) {
  472. std::string tmp = rnd_.RandomString(1);
  473. file_contents[rnd_.Next() % file_contents.size()] = tmp[0];
  474. }
  475. return WriteToFile(fname, file_contents);
  476. }
  477. Status CorruptFileStart(const std::string& fname) {
  478. std::string to_xor = "blah";
  479. std::string file_contents;
  480. Status s = ReadFileToString(this, fname, &file_contents);
  481. if (!s.ok()) {
  482. return s;
  483. }
  484. s = DeleteFile(fname);
  485. if (!s.ok()) {
  486. return s;
  487. }
  488. for (size_t i = 0; i < to_xor.size(); ++i) {
  489. file_contents[i] ^= to_xor[i];
  490. }
  491. return WriteToFile(fname, file_contents);
  492. }
  493. Status CorruptFileMiddle(const std::string& fname) {
  494. std::string to_xor = "blah";
  495. std::string file_contents;
  496. Status s = ReadFileToString(this, fname, &file_contents);
  497. if (!s.ok()) {
  498. return s;
  499. }
  500. s = DeleteFile(fname);
  501. if (!s.ok()) {
  502. return s;
  503. }
  504. size_t middle = file_contents.size() / 2;
  505. for (size_t i = 0; i < to_xor.size(); ++i) {
  506. file_contents[middle + i] ^= to_xor[i];
  507. }
  508. return WriteToFile(fname, file_contents);
  509. }
  510. Status CorruptChecksum(const std::string& fname, bool appear_valid) {
  511. std::string metadata;
  512. Status s = ReadFileToString(this, fname, &metadata);
  513. if (!s.ok()) {
  514. return s;
  515. }
  516. s = DeleteFile(fname);
  517. if (!s.ok()) {
  518. return s;
  519. }
  520. auto pos = metadata.find("private");
  521. if (pos == std::string::npos) {
  522. return Status::Corruption("private file is expected");
  523. }
  524. pos = metadata.find(" crc32 ", pos + 6);
  525. if (pos == std::string::npos) {
  526. return Status::Corruption("checksum not found");
  527. }
  528. if (metadata.size() < pos + 7) {
  529. return Status::Corruption("bad CRC32 checksum value");
  530. }
  531. if (appear_valid) {
  532. if (metadata[pos + 8] == '\n') {
  533. // single digit value, safe to insert one more digit
  534. metadata.insert(pos + 8, 1, '0');
  535. } else {
  536. metadata.erase(pos + 8, 1);
  537. }
  538. } else {
  539. metadata[pos + 7] = 'a';
  540. }
  541. return WriteToFile(fname, metadata);
  542. }
  543. Status WriteToFile(const std::string& fname, const std::string& data) {
  544. std::unique_ptr<WritableFile> file;
  545. EnvOptions env_options;
  546. env_options.use_mmap_writes = false;
  547. Status s = EnvWrapper::NewWritableFile(fname, &file, env_options);
  548. if (!s.ok()) {
  549. return s;
  550. }
  551. return file->Append(Slice(data));
  552. }
  553. private:
  554. Random rnd_;
  555. }; // FileManager
  556. // utility functions
  557. namespace {
  558. enum FillDBFlushAction {
  559. kFlushMost,
  560. kFlushAll,
  561. kAutoFlushOnly,
  562. };
  563. // Many tests in this file expect FillDB to write at least one sst file,
  564. // so the default behavior (if not kAutoFlushOnly) of FillDB is to force
  565. // a flush. But to ensure coverage of the WAL file case, we also (by default)
  566. // do one Put after the Flush (kFlushMost).
  567. size_t FillDB(DB* db, int from, int to,
  568. FillDBFlushAction flush_action = kFlushMost) {
  569. size_t bytes_written = 0;
  570. for (int i = from; i < to; ++i) {
  571. std::string key = "testkey" + std::to_string(i);
  572. std::string value = "testvalue" + std::to_string(i);
  573. bytes_written += key.size() + value.size();
  574. EXPECT_OK(db->Put(WriteOptions(), Slice(key), Slice(value)));
  575. if (flush_action == kFlushMost && i == to - 2) {
  576. EXPECT_OK(db->Flush(FlushOptions()));
  577. }
  578. }
  579. if (flush_action == kFlushAll) {
  580. EXPECT_OK(db->Flush(FlushOptions()));
  581. }
  582. return bytes_written;
  583. }
  584. void AssertExists(DB* db, int from, int to) {
  585. for (int i = from; i < to; ++i) {
  586. std::string key = "testkey" + std::to_string(i);
  587. std::string value;
  588. ASSERT_OK(db->Get(ReadOptions(), Slice(key), &value));
  589. ASSERT_EQ(value, "testvalue" + std::to_string(i));
  590. }
  591. }
  592. void AssertEmpty(DB* db, int from, int to) {
  593. for (int i = from; i < to; ++i) {
  594. std::string key = "testkey" + std::to_string(i);
  595. std::string value = "testvalue" + std::to_string(i);
  596. Status s = db->Get(ReadOptions(), Slice(key), &value);
  597. ASSERT_TRUE(s.IsNotFound());
  598. }
  599. }
  600. } // namespace
  601. class BackupEngineTest : public testing::Test {
  602. public:
  603. enum ShareOption {
  604. kNoShare,
  605. kShareNoChecksum,
  606. kShareWithChecksum,
  607. };
  608. const std::vector<ShareOption> kAllShareOptions = {kNoShare, kShareNoChecksum,
  609. kShareWithChecksum};
  610. BackupEngineTest() {
  611. // set up files
  612. std::string db_chroot = test::PerThreadDBPath("db_for_backup");
  613. std::string backup_chroot = test::PerThreadDBPath("db_backups");
  614. EXPECT_OK(Env::Default()->CreateDirIfMissing(db_chroot));
  615. EXPECT_OK(Env::Default()->CreateDirIfMissing(backup_chroot));
  616. dbname_ = "/tempdb";
  617. backupdir_ = "/tempbk";
  618. latest_backup_ = backupdir_ + "/LATEST_BACKUP";
  619. // set up FileSystem & Envs
  620. db_chroot_fs_ = NewChrootFileSystem(FileSystem::Default(), db_chroot);
  621. backup_chroot_fs_ =
  622. NewChrootFileSystem(FileSystem::Default(), backup_chroot);
  623. test_db_fs_ = std::make_shared<TestFs>(db_chroot_fs_);
  624. test_backup_fs_ = std::make_shared<TestFs>(backup_chroot_fs_);
  625. SetEnvsFromFileSystems();
  626. // set up db options
  627. options_.create_if_missing = true;
  628. options_.paranoid_checks = true;
  629. options_.write_buffer_size = 1 << 17; // 128KB
  630. options_.wal_dir = dbname_;
  631. options_.enable_blob_files = true;
  632. // The sync option is not easily testable in unit tests, but should be
  633. // smoke tested across all the other backup tests. However, it is
  634. // certainly not worth doubling the runtime of backup tests for it.
  635. // Thus, we can enable sync for one of our alternate testing
  636. // configurations.
  637. constexpr bool kUseSync =
  638. #ifdef ROCKSDB_MODIFY_NPHASH
  639. true;
  640. #else
  641. false;
  642. #endif // ROCKSDB_MODIFY_NPHASH
  643. // set up backup db options
  644. engine_options_.reset(new BackupEngineOptions(
  645. backupdir_, test_backup_env_.get(), /*share_table_files*/ true,
  646. logger_.get(), kUseSync));
  647. // most tests will use multi-threaded backups
  648. engine_options_->max_background_operations = 7;
  649. // delete old files in db
  650. DestroyDBWithoutCheck(dbname_, options_);
  651. // delete old LATEST_BACKUP file, which some tests create for compatibility
  652. // testing.
  653. backup_chroot_env_->DeleteFile(latest_backup_).PermitUncheckedError();
  654. }
  655. void SetEnvsFromFileSystems() {
  656. db_chroot_env_.reset(
  657. new CompositeEnvWrapper(Env::Default(), db_chroot_fs_));
  658. backup_chroot_env_.reset(
  659. new CompositeEnvWrapper(Env::Default(), backup_chroot_fs_));
  660. test_db_env_.reset(new CompositeEnvWrapper(Env::Default(), test_db_fs_));
  661. options_.env = test_db_env_.get();
  662. test_backup_env_.reset(
  663. new CompositeEnvWrapper(Env::Default(), test_backup_fs_));
  664. if (engine_options_) {
  665. engine_options_->backup_env = test_backup_env_.get();
  666. }
  667. file_manager_.reset(new FileManager(backup_chroot_env_.get()));
  668. db_file_manager_.reset(new FileManager(db_chroot_env_.get()));
  669. // Create logger
  670. DBOptions logger_options;
  671. logger_options.env = db_chroot_env_.get();
  672. ASSERT_OK(CreateLoggerFromOptions(dbname_, logger_options, &logger_));
  673. }
  674. DB* OpenDB() {
  675. DB* db;
  676. EXPECT_OK(DB::Open(options_, dbname_, &db));
  677. return db;
  678. }
  679. void CloseAndReopenDB(bool read_only = false) {
  680. // Close DB
  681. db_.reset();
  682. // Open DB
  683. test_db_fs_->SetLimitWrittenFiles(1000000);
  684. DB* db;
  685. if (read_only) {
  686. ASSERT_OK(DB::OpenForReadOnly(options_, dbname_, &db));
  687. } else {
  688. ASSERT_OK(DB::Open(options_, dbname_, &db));
  689. }
  690. db_.reset(db);
  691. }
  692. void InitializeDBAndBackupEngine(bool dummy = false) {
  693. // reset all the db env defaults
  694. test_db_fs_->SetLimitWrittenFiles(1000000);
  695. test_db_fs_->SetDummySequentialFile(dummy);
  696. DB* db;
  697. if (dummy) {
  698. dummy_db_ = new DummyDB(options_, dbname_);
  699. db = dummy_db_;
  700. } else {
  701. ASSERT_OK(DB::Open(options_, dbname_, &db));
  702. }
  703. db_.reset(db);
  704. }
  705. virtual void OpenDBAndBackupEngine(
  706. bool destroy_old_data = false, bool dummy = false,
  707. ShareOption shared_option = kShareNoChecksum) {
  708. InitializeDBAndBackupEngine(dummy);
  709. // reset backup env defaults
  710. test_backup_fs_->SetLimitWrittenFiles(1000000);
  711. engine_options_->destroy_old_data = destroy_old_data;
  712. engine_options_->share_table_files = shared_option != kNoShare;
  713. engine_options_->share_files_with_checksum =
  714. shared_option == kShareWithChecksum;
  715. OpenBackupEngine(destroy_old_data);
  716. }
  717. void CloseDBAndBackupEngine() {
  718. db_.reset();
  719. backup_engine_.reset();
  720. }
  721. void OpenBackupEngine(bool destroy_old_data = false) {
  722. engine_options_->destroy_old_data = destroy_old_data;
  723. engine_options_->info_log = logger_.get();
  724. BackupEngine* backup_engine;
  725. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), *engine_options_,
  726. &backup_engine));
  727. backup_engine_.reset(backup_engine);
  728. }
  729. void CloseBackupEngine() { backup_engine_.reset(nullptr); }
  730. // cross-cutting test of GetBackupInfo
  731. void AssertBackupInfoConsistency(bool allow_excluded = false) {
  732. std::vector<BackupInfo> backup_info;
  733. backup_engine_->GetBackupInfo(&backup_info, /*with file details*/ true);
  734. std::map<std::string, uint64_t> file_sizes;
  735. // Find the files that are supposed to be there
  736. for (auto& backup : backup_info) {
  737. uint64_t sum_for_backup = 0;
  738. for (auto& file : backup.file_details) {
  739. auto e = file_sizes.find(file.relative_filename);
  740. if (e == file_sizes.end()) {
  741. // fprintf(stderr, "Adding %s -> %u\n",
  742. // file.relative_filename.c_str(), (unsigned)file.size);
  743. file_sizes[file.relative_filename] = file.size;
  744. } else {
  745. ASSERT_EQ(file_sizes[file.relative_filename], file.size);
  746. }
  747. sum_for_backup += file.size;
  748. }
  749. ASSERT_EQ(backup.size, sum_for_backup);
  750. if (!allow_excluded) {
  751. ASSERT_EQ(backup.excluded_files.size(), 0);
  752. }
  753. }
  754. std::vector<BackupID> corrupt_backup_ids;
  755. backup_engine_->GetCorruptedBackups(&corrupt_backup_ids);
  756. bool has_corrupt = corrupt_backup_ids.size() > 0;
  757. // Compare with what's in backup dir
  758. std::vector<std::string> child_dirs;
  759. ASSERT_OK(
  760. test_backup_env_->GetChildren(backupdir_ + "/private", &child_dirs));
  761. for (auto& dir : child_dirs) {
  762. dir = "private/" + dir;
  763. }
  764. child_dirs.emplace_back("shared"); // might not exist
  765. child_dirs.emplace_back("shared_checksum"); // might not exist
  766. for (auto& dir : child_dirs) {
  767. std::vector<std::string> children;
  768. test_backup_env_->GetChildren(backupdir_ + "/" + dir, &children)
  769. .PermitUncheckedError();
  770. // fprintf(stderr, "ls %s\n", (backupdir_ + "/" + dir).c_str());
  771. for (auto& file : children) {
  772. uint64_t size;
  773. size = UINT64_MAX; // appease clang-analyze
  774. std::string rel_file = dir + "/" + file;
  775. // fprintf(stderr, "stat %s\n", (backupdir_ + "/" + rel_file).c_str());
  776. ASSERT_OK(
  777. test_backup_env_->GetFileSize(backupdir_ + "/" + rel_file, &size));
  778. auto e = file_sizes.find(rel_file);
  779. if (e == file_sizes.end()) {
  780. // The only case in which we should find files not reported
  781. ASSERT_TRUE(has_corrupt);
  782. } else {
  783. ASSERT_EQ(e->second, size);
  784. file_sizes.erase(e);
  785. }
  786. }
  787. }
  788. // Everything should have been matched
  789. ASSERT_EQ(file_sizes.size(), 0);
  790. }
  791. // restores backup backup_id and asserts the existence of
  792. // [start_exist, end_exist> and not-existence of
  793. // [end_exist, end>
  794. //
  795. // if backup_id == 0, it means restore from latest
  796. // if end == 0, don't check AssertEmpty
  797. void AssertBackupConsistency(BackupID backup_id, uint32_t start_exist,
  798. uint32_t end_exist, uint32_t end = 0,
  799. bool keep_log_files = false) {
  800. RestoreOptions restore_options(keep_log_files);
  801. bool opened_backup_engine = false;
  802. if (backup_engine_.get() == nullptr) {
  803. opened_backup_engine = true;
  804. OpenBackupEngine();
  805. }
  806. AssertBackupInfoConsistency();
  807. // Now perform restore
  808. if (backup_id > 0) {
  809. ASSERT_OK(backup_engine_->RestoreDBFromBackup(backup_id, dbname_, dbname_,
  810. restore_options));
  811. } else {
  812. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_,
  813. restore_options));
  814. }
  815. DB* db = OpenDB();
  816. // Check DB contents
  817. AssertExists(db, start_exist, end_exist);
  818. if (end != 0) {
  819. AssertEmpty(db, end_exist, end);
  820. }
  821. delete db;
  822. if (opened_backup_engine) {
  823. CloseBackupEngine();
  824. }
  825. }
  826. void DeleteLogFiles() {
  827. std::vector<std::string> delete_logs;
  828. ASSERT_OK(db_chroot_env_->GetChildren(dbname_, &delete_logs));
  829. for (const auto& f : delete_logs) {
  830. uint64_t number;
  831. FileType type;
  832. bool ok = ParseFileName(f, &number, &type);
  833. if (ok && type == kWalFile) {
  834. ASSERT_OK(db_chroot_env_->DeleteFile(dbname_ + "/" + f));
  835. }
  836. }
  837. }
  838. Status GetDataFilesInDB(const FileType& file_type,
  839. std::vector<FileAttributes>* files) {
  840. std::vector<std::string> live;
  841. uint64_t ignore_manifest_size;
  842. Status s = db_->GetLiveFiles(live, &ignore_manifest_size, /*flush*/ false);
  843. if (!s.ok()) {
  844. return s;
  845. }
  846. std::vector<FileAttributes> children;
  847. s = test_db_env_->GetChildrenFileAttributes(dbname_, &children);
  848. for (const auto& child : children) {
  849. FileType type;
  850. uint64_t number = 0;
  851. if (ParseFileName(child.name, &number, &type) && type == file_type &&
  852. std::find(live.begin(), live.end(), "/" + child.name) != live.end()) {
  853. files->push_back(child);
  854. }
  855. }
  856. return s;
  857. }
  858. Status GetRandomDataFileInDB(const FileType& file_type,
  859. std::string* fname_out,
  860. uint64_t* fsize_out = nullptr) {
  861. Random rnd(6); // NB: hardly "random"
  862. std::vector<FileAttributes> files;
  863. Status s = GetDataFilesInDB(file_type, &files);
  864. if (!s.ok()) {
  865. return s;
  866. }
  867. if (files.empty()) {
  868. return Status::NotFound("");
  869. }
  870. size_t i = rnd.Uniform(static_cast<int>(files.size()));
  871. *fname_out = dbname_ + "/" + files[i].name;
  872. if (fsize_out) {
  873. *fsize_out = files[i].size_bytes;
  874. }
  875. return Status::OK();
  876. }
  877. Status CorruptRandomDataFileInDB(const FileType& file_type) {
  878. std::string fname;
  879. uint64_t fsize = 0;
  880. Status s = GetRandomDataFileInDB(file_type, &fname, &fsize);
  881. if (!s.ok()) {
  882. return s;
  883. }
  884. std::string file_contents;
  885. s = ReadFileToString(test_db_env_.get(), fname, &file_contents);
  886. if (!s.ok()) {
  887. return s;
  888. }
  889. s = test_db_env_->DeleteFile(fname);
  890. if (!s.ok()) {
  891. return s;
  892. }
  893. file_contents[0] = (file_contents[0] + 257) % 256;
  894. return WriteStringToFile(test_db_env_.get(), file_contents, fname, false);
  895. }
  896. void AssertDirectoryFilesMatchRegex(const std::string& dir,
  897. const TestRegex& pattern,
  898. const std::string& file_type,
  899. int minimum_count) {
  900. std::vector<FileAttributes> children;
  901. ASSERT_OK(file_manager_->GetChildrenFileAttributes(dir, &children));
  902. int found_count = 0;
  903. for (const auto& child : children) {
  904. if (EndsWith(child.name, file_type)) {
  905. ASSERT_MATCHES_REGEX(child.name, pattern);
  906. ++found_count;
  907. }
  908. }
  909. ASSERT_GE(found_count, minimum_count);
  910. }
  911. void AssertDirectoryFilesSizeIndicators(const std::string& dir,
  912. int minimum_count) {
  913. std::vector<FileAttributes> children;
  914. ASSERT_OK(file_manager_->GetChildrenFileAttributes(dir, &children));
  915. int found_count = 0;
  916. for (const auto& child : children) {
  917. auto last_underscore = child.name.find_last_of('_');
  918. auto last_dot = child.name.find_last_of('.');
  919. ASSERT_NE(child.name, child.name.substr(0, last_underscore));
  920. ASSERT_NE(child.name, child.name.substr(0, last_dot));
  921. ASSERT_LT(last_underscore, last_dot);
  922. std::string s = child.name.substr(last_underscore + 1,
  923. last_dot - (last_underscore + 1));
  924. ASSERT_EQ(s, std::to_string(child.size_bytes));
  925. ++found_count;
  926. }
  927. ASSERT_GE(found_count, minimum_count);
  928. }
  929. // files
  930. std::string dbname_;
  931. std::string backupdir_;
  932. std::string latest_backup_;
  933. // logger_ must be above backup_engine_ such that the engine's destructor,
  934. // which uses a raw pointer to the logger, executes first.
  935. std::shared_ptr<Logger> logger_;
  936. // FileSystems
  937. std::shared_ptr<FileSystem> db_chroot_fs_;
  938. std::shared_ptr<FileSystem> backup_chroot_fs_;
  939. std::shared_ptr<TestFs> test_db_fs_;
  940. std::shared_ptr<TestFs> test_backup_fs_;
  941. // Env wrappers
  942. std::unique_ptr<Env> db_chroot_env_;
  943. std::unique_ptr<Env> backup_chroot_env_;
  944. std::unique_ptr<Env> test_db_env_;
  945. std::unique_ptr<Env> test_backup_env_;
  946. std::unique_ptr<FileManager> file_manager_;
  947. std::unique_ptr<FileManager> db_file_manager_;
  948. // all the dbs!
  949. DummyDB* dummy_db_; // owned as db_ when present
  950. std::unique_ptr<DB> db_;
  951. std::unique_ptr<BackupEngine> backup_engine_;
  952. // options
  953. Options options_;
  954. protected:
  955. void DestroyDBWithoutCheck(const std::string& dbname,
  956. const Options& options) {
  957. // DestroyDB may fail because the db might not be existed for some tests
  958. DestroyDB(dbname, options).PermitUncheckedError();
  959. }
  960. std::unique_ptr<BackupEngineOptions> engine_options_;
  961. }; // BackupEngineTest
  962. void AppendPath(const std::string& path, std::vector<std::string>& v) {
  963. for (auto& f : v) {
  964. f = path + f;
  965. }
  966. }
  967. class BackupEngineTestWithParam : public BackupEngineTest,
  968. public testing::WithParamInterface<bool> {
  969. public:
  970. BackupEngineTestWithParam() {
  971. engine_options_->share_files_with_checksum = GetParam();
  972. }
  973. void OpenDBAndBackupEngine(
  974. bool destroy_old_data = false, bool dummy = false,
  975. ShareOption shared_option = kShareNoChecksum) override {
  976. BackupEngineTest::InitializeDBAndBackupEngine(dummy);
  977. // reset backup env defaults
  978. test_backup_fs_->SetLimitWrittenFiles(1000000);
  979. engine_options_->destroy_old_data = destroy_old_data;
  980. engine_options_->share_table_files = shared_option != kNoShare;
  981. // NOTE: keep share_files_with_checksum setting from constructor
  982. OpenBackupEngine(destroy_old_data);
  983. }
  984. };
  985. TEST_F(BackupEngineTest, IncrementalRestore) {
  986. // Required for excluding files.
  987. engine_options_->schema_version = 2;
  988. const int keys_iteration = 100;
  989. options_.disable_auto_compactions = true;
  990. options_.level0_file_num_compaction_trigger = 1000;
  991. for (const auto& mode : {RestoreOptions::Mode::kPurgeAllFiles,
  992. RestoreOptions::Mode::kKeepLatestDbSessionIdFiles,
  993. RestoreOptions::Mode::kVerifyChecksum}) {
  994. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  995. kShareWithChecksum);
  996. // 1. Populate db with seed data (2 SST files, 2 blob files).
  997. FillDB(db_.get(), 0, keys_iteration);
  998. FillDB(db_.get(), keys_iteration, keys_iteration * 2);
  999. std::vector<LiveFileStorageInfo> file_infos;
  1000. EXPECT_OK(db_->GetLiveFilesStorageInfo(LiveFilesStorageInfoOptions(),
  1001. &file_infos));
  1002. std::vector<std::string> all_files;
  1003. std::vector<std::string> all_files_but_sst;
  1004. std::vector<std::string> all_sst_files;
  1005. std::vector<std::string> all_blob_files;
  1006. std::vector<std::string> all_files_but_data;
  1007. for (const auto& file_info : file_infos) {
  1008. std::string abs_file_path =
  1009. file_info.directory + "/" + file_info.relative_filename;
  1010. if (file_info.relative_filename == "CURRENT") {
  1011. abs_file_path += ".tmp";
  1012. }
  1013. all_files.push_back(abs_file_path);
  1014. if (file_info.file_type == kTableFile) {
  1015. all_sst_files.push_back(abs_file_path);
  1016. } else {
  1017. all_files_but_sst.push_back(abs_file_path);
  1018. }
  1019. if (file_info.file_type == kBlobFile) {
  1020. all_blob_files.push_back(abs_file_path);
  1021. }
  1022. if (file_info.file_type != kTableFile &&
  1023. file_info.file_type != kBlobFile) {
  1024. all_files_but_data.push_back(abs_file_path);
  1025. }
  1026. }
  1027. std::string one_sst_file = all_sst_files[0];
  1028. // 2. Verify expected behavior with exclude files feature.
  1029. BackupID first_id;
  1030. CreateBackupOptions cbo;
  1031. cbo.exclude_files_callback = [&one_sst_file](
  1032. MaybeExcludeBackupFile* files_begin,
  1033. MaybeExcludeBackupFile* files_end) {
  1034. for (auto* f = files_begin; f != files_end; ++f) {
  1035. std::string s = StringSplit(f->info.relative_file, '/').back();
  1036. s = s.substr(0, s.find('_'));
  1037. auto filename = one_sst_file.substr(one_sst_file.find_last_of("/") + 1);
  1038. if (s + ".sst" == filename) {
  1039. // Backup will include everything BUT that one very SST file.
  1040. f->exclude_decision = true;
  1041. } else {
  1042. f->exclude_decision = false;
  1043. }
  1044. }
  1045. };
  1046. ASSERT_OK(backup_engine_->CreateNewBackup(cbo, db_.get(), &first_id));
  1047. test_db_fs_->ClearWrittenFiles();
  1048. RestoreOptions restore_options(false, mode);
  1049. IOStatus io_st = backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_,
  1050. restore_options);
  1051. if (mode == RestoreOptions::kKeepLatestDbSessionIdFiles) {
  1052. EXPECT_OK(io_st);
  1053. test_db_fs_->AssertWrittenFiles(all_files_but_sst);
  1054. } else {
  1055. ASSERT_TRUE(io_st.IsInvalidArgument());
  1056. }
  1057. ASSERT_OK(backup_engine_->DeleteBackup(first_id));
  1058. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1059. CloseDBAndBackupEngine();
  1060. DestroyDBWithoutCheck(dbname_, options_);
  1061. // 3. Verify clean restore scenario.
  1062. test_db_fs_->ClearWrittenFiles();
  1063. OpenBackupEngine();
  1064. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_,
  1065. restore_options));
  1066. CloseBackupEngine();
  1067. // Since we started with a blank db, restore copied all the files.
  1068. test_db_fs_->AssertWrittenFiles(all_files);
  1069. db_.reset(OpenDB());
  1070. // Check DB contents.
  1071. AssertExists(db_.get(), 0, keys_iteration * 2);
  1072. // Create more data files. Those will be wiped out in consecutive restore.
  1073. FillDB(db_.get(), keys_iteration * 2, keys_iteration * 3);
  1074. db_.reset(); // CloseDB
  1075. // 4. Incremental restore - simple case.
  1076. //
  1077. // Create 'a hole' in a cleanly restored db by manually deleting data files.
  1078. // At this point new files were created and old files were deleted - which
  1079. // is representative of the users workloads.
  1080. std::string sst_file_to_be_deleted = one_sst_file;
  1081. std::string blob_file_to_be_deleted = all_blob_files[0];
  1082. IOOptions io_opts;
  1083. ASSERT_OK(test_db_fs_->DeleteFile(sst_file_to_be_deleted, io_opts,
  1084. nullptr /* dbg */));
  1085. ASSERT_OK(test_db_fs_->DeleteFile(blob_file_to_be_deleted, io_opts,
  1086. nullptr /* dbg */));
  1087. test_db_fs_->ClearWrittenFiles();
  1088. OpenBackupEngine();
  1089. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_,
  1090. restore_options));
  1091. CloseBackupEngine();
  1092. std::vector<std::string> should_have_written;
  1093. if (mode == RestoreOptions::Mode::kPurgeAllFiles) {
  1094. should_have_written = all_files;
  1095. } else {
  1096. should_have_written = all_files_but_data;
  1097. should_have_written.emplace_back(sst_file_to_be_deleted);
  1098. if (mode == RestoreOptions::Mode::kKeepLatestDbSessionIdFiles) {
  1099. // We only support incremental restore for blobs in kVerifyChecksum
  1100. // mode.
  1101. should_have_written.insert(should_have_written.end(),
  1102. all_blob_files.begin(),
  1103. all_blob_files.end());
  1104. } else {
  1105. should_have_written.emplace_back(blob_file_to_be_deleted);
  1106. }
  1107. }
  1108. // 'Hole' has been patched, 'in-policy' db files were retained.
  1109. test_db_fs_->AssertWrittenFiles(should_have_written);
  1110. // Check DB contents.
  1111. db_.reset(OpenDB());
  1112. AssertExists(db_.get(), 0, keys_iteration * 2);
  1113. db_.reset(); // Close DB.
  1114. // 5. Incremental restore - corrupted db files.
  1115. std::string blob_file_to_be_corrupted = all_blob_files[0];
  1116. ASSERT_OK(db_file_manager_->CorruptFile(blob_file_to_be_corrupted, 3));
  1117. // First few bytes corruption will be detected by ReadTablePropertiesHelper
  1118. // at the time of reading the metadata footer. We must try a bit harder
  1119. // (by overriding bytes beyond the footer) to corrupt a file in a more
  1120. // harmful way...
  1121. std::string sst_file_to_be_corrupted = all_sst_files[0];
  1122. ASSERT_OK(db_file_manager_->CorruptFileStart(sst_file_to_be_corrupted));
  1123. OpenBackupEngine();
  1124. test_db_fs_->ClearWrittenFiles();
  1125. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_,
  1126. restore_options));
  1127. CloseBackupEngine();
  1128. if (mode == RestoreOptions::Mode::kPurgeAllFiles) {
  1129. should_have_written = all_files;
  1130. } else {
  1131. should_have_written = all_files_but_data;
  1132. if (mode == RestoreOptions::Mode::kVerifyChecksum) {
  1133. // Restore running in kVerifyChecksum mode would have caught the
  1134. // mismatch between crc32c and db file contents. Such file would have
  1135. // been deleted and restored from the backup.
  1136. should_have_written.emplace_back(blob_file_to_be_corrupted);
  1137. should_have_written.emplace_back(sst_file_to_be_corrupted);
  1138. } else if (mode == RestoreOptions::Mode::kKeepLatestDbSessionIdFiles) {
  1139. // This mode is more prone to subtle db file corruptions as we do not
  1140. // run any CPU intensive computations (like checksum) and the match
  1141. // between existing db file and its' relevant backup counterpart is
  1142. // determined purely based on the metadata from the footer (size,
  1143. // db_session_id). Therefore, if corrupted portion of an existing db
  1144. // file does NOT directly affect those properties in the footer, it
  1145. // might slip through the cracks and only be detected at the time of
  1146. // running CRC32c.
  1147. // Separately, this mode does not support incremental restore for blobs.
  1148. should_have_written.insert(should_have_written.end(),
  1149. all_blob_files.begin(),
  1150. all_blob_files.end());
  1151. }
  1152. }
  1153. // 'Hole' has been patched, 'in-policy' db files were retained.
  1154. test_db_fs_->AssertWrittenFiles(should_have_written);
  1155. db_.reset(OpenDB());
  1156. Status s = db_->VerifyChecksum();
  1157. // Check DB contents.
  1158. if (mode == RestoreOptions::Mode::kKeepLatestDbSessionIdFiles) {
  1159. ASSERT_TRUE(s.IsCorruption());
  1160. } else {
  1161. EXPECT_OK(s);
  1162. AssertExists(db_.get(), 0, keys_iteration * 2);
  1163. }
  1164. db_.reset(); // Close DB.
  1165. DestroyDBWithoutCheck(dbname_, options_);
  1166. }
  1167. }
  1168. TEST_F(BackupEngineTest, FileCollision) {
  1169. const int keys_iteration = 100;
  1170. for (const auto& sopt : kAllShareOptions) {
  1171. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */, sopt);
  1172. FillDB(db_.get(), 0, keys_iteration);
  1173. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1174. FillDB(db_.get(), keys_iteration, keys_iteration * 2);
  1175. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1176. CloseDBAndBackupEngine();
  1177. // If the db directory has been cleaned up, it is sensitive to file
  1178. // collision.
  1179. DestroyDBWithoutCheck(dbname_, options_);
  1180. // open fresh DB, but old backups present
  1181. OpenDBAndBackupEngine(false /* destroy_old_data */, false /* dummy */,
  1182. sopt);
  1183. FillDB(db_.get(), 0, keys_iteration);
  1184. ASSERT_OK(db_->Flush(FlushOptions())); // like backup would do
  1185. FillDB(db_.get(), keys_iteration, keys_iteration * 2);
  1186. if (sopt != kShareNoChecksum) {
  1187. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1188. } else {
  1189. // The new table files created in FillDB() will clash with the old
  1190. // backup and sharing tables with no checksum will have the file
  1191. // collision problem.
  1192. ASSERT_NOK(backup_engine_->CreateNewBackup(db_.get()));
  1193. ASSERT_OK(backup_engine_->PurgeOldBackups(0));
  1194. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1195. }
  1196. CloseDBAndBackupEngine();
  1197. // delete old data
  1198. DestroyDBWithoutCheck(dbname_, options_);
  1199. }
  1200. }
  1201. // This test verifies that the verifyBackup method correctly identifies
  1202. // invalid backups
  1203. TEST_P(BackupEngineTestWithParam, VerifyBackup) {
  1204. const int keys_iteration = 5000;
  1205. OpenDBAndBackupEngine(true);
  1206. // create five backups
  1207. for (int i = 0; i < 5; ++i) {
  1208. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1209. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1210. }
  1211. CloseDBAndBackupEngine();
  1212. OpenDBAndBackupEngine();
  1213. // ---------- case 1. - valid backup -----------
  1214. ASSERT_TRUE(backup_engine_->VerifyBackup(1).ok());
  1215. // ---------- case 2. - delete a file -----------i
  1216. ASSERT_OK(file_manager_->DeleteRandomFileInDir(backupdir_ + "/private/1"));
  1217. ASSERT_TRUE(backup_engine_->VerifyBackup(1).IsNotFound());
  1218. // ---------- case 3. - corrupt a file -----------
  1219. std::string append_data = "Corrupting a random file";
  1220. ASSERT_OK(file_manager_->AppendToRandomFileInDir(backupdir_ + "/private/2",
  1221. append_data));
  1222. ASSERT_TRUE(backup_engine_->VerifyBackup(2).IsCorruption());
  1223. // ---------- case 4. - invalid backup -----------
  1224. ASSERT_TRUE(backup_engine_->VerifyBackup(6).IsNotFound());
  1225. CloseDBAndBackupEngine();
  1226. }
  1227. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1228. // open DB, write, close DB, backup, restore, repeat
  1229. TEST_P(BackupEngineTestWithParam, OfflineIntegrationTest) {
  1230. // has to be a big number, so that it triggers the memtable flush
  1231. const int keys_iteration = 5000;
  1232. const int max_key = keys_iteration * 4 + 10;
  1233. // first iter -- flush before backup
  1234. // second iter -- don't flush before backup
  1235. for (int iter = 0; iter < 2; ++iter) {
  1236. // delete old data
  1237. DestroyDBWithoutCheck(dbname_, options_);
  1238. bool destroy_data = true;
  1239. // every iteration --
  1240. // 1. insert new data in the DB
  1241. // 2. backup the DB
  1242. // 3. destroy the db
  1243. // 4. restore the db, check everything is still there
  1244. for (int i = 0; i < 5; ++i) {
  1245. // in last iteration, put smaller amount of data,
  1246. int fill_up_to = std::min(keys_iteration * (i + 1), max_key);
  1247. // ---- insert new data and back up ----
  1248. OpenDBAndBackupEngine(destroy_data);
  1249. destroy_data = false;
  1250. // kAutoFlushOnly to preserve legacy test behavior (consider updating)
  1251. FillDB(db_.get(), keys_iteration * i, fill_up_to, kAutoFlushOnly);
  1252. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), iter == 0))
  1253. << "iter: " << iter << ", idx: " << i;
  1254. CloseDBAndBackupEngine();
  1255. DestroyDBWithoutCheck(dbname_, options_);
  1256. // ---- make sure it's empty ----
  1257. DB* db = OpenDB();
  1258. AssertEmpty(db, 0, fill_up_to);
  1259. delete db;
  1260. // ---- restore the DB ----
  1261. OpenBackupEngine();
  1262. if (i >= 3) { // test purge old backups
  1263. // when i == 4, purge to only 1 backup
  1264. // when i == 3, purge to 2 backups
  1265. ASSERT_OK(backup_engine_->PurgeOldBackups(5 - i));
  1266. }
  1267. // ---- make sure the data is there ---
  1268. AssertBackupConsistency(0, 0, fill_up_to, max_key);
  1269. CloseBackupEngine();
  1270. }
  1271. }
  1272. }
  1273. // open DB, write, backup, write, backup, close, restore
  1274. TEST_P(BackupEngineTestWithParam, OnlineIntegrationTest) {
  1275. // has to be a big number, so that it triggers the memtable flush
  1276. const int keys_iteration = 5000;
  1277. const int max_key = keys_iteration * 4 + 10;
  1278. Random rnd(7);
  1279. // delete old data
  1280. DestroyDBWithoutCheck(dbname_, options_);
  1281. // TODO: Implement & test db_paths support in backup (not supported in
  1282. // restore)
  1283. // options_.db_paths.emplace_back(dbname_, 500 * 1024);
  1284. // options_.db_paths.emplace_back(dbname_ + "_2", 1024 * 1024 * 1024);
  1285. test_db_fs_->SetCheckIOOptionsSequentialFile(true);
  1286. test_backup_fs_->SetCheckIOOptionsSequentialFile(true);
  1287. OpenDBAndBackupEngine(true);
  1288. // write some data, backup, repeat
  1289. for (int i = 0; i < 5; ++i) {
  1290. if (i == 4) {
  1291. // delete backup number 2, online delete!
  1292. ASSERT_OK(backup_engine_->DeleteBackup(2));
  1293. }
  1294. // in last iteration, put smaller amount of data,
  1295. // so that backups can share sst files
  1296. int fill_up_to = std::min(keys_iteration * (i + 1), max_key);
  1297. // kAutoFlushOnly to preserve legacy test behavior (consider updating)
  1298. FillDB(db_.get(), keys_iteration * i, fill_up_to, kAutoFlushOnly);
  1299. // we should get consistent results with flush_before_backup
  1300. // set to both true and false
  1301. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  1302. }
  1303. // close and destroy
  1304. CloseDBAndBackupEngine();
  1305. DestroyDBWithoutCheck(dbname_, options_);
  1306. // ---- make sure it's empty ----
  1307. DB* db = OpenDB();
  1308. AssertEmpty(db, 0, max_key);
  1309. delete db;
  1310. // ---- restore every backup and verify all the data is there ----
  1311. OpenBackupEngine();
  1312. for (int i = 1; i <= 5; ++i) {
  1313. if (i == 2) {
  1314. // we deleted backup 2
  1315. Status s = backup_engine_->RestoreDBFromBackup(2, dbname_, dbname_);
  1316. ASSERT_TRUE(!s.ok());
  1317. } else {
  1318. int fill_up_to = std::min(keys_iteration * i, max_key);
  1319. AssertBackupConsistency(i, 0, fill_up_to, max_key);
  1320. }
  1321. }
  1322. // delete some backups -- this should leave only backups 3 and 5 alive
  1323. ASSERT_OK(backup_engine_->DeleteBackup(4));
  1324. ASSERT_OK(backup_engine_->PurgeOldBackups(2));
  1325. std::vector<BackupInfo> backup_info;
  1326. backup_engine_->GetBackupInfo(&backup_info);
  1327. ASSERT_EQ(2UL, backup_info.size());
  1328. // check backup 3
  1329. AssertBackupConsistency(3, 0, 3 * keys_iteration, max_key);
  1330. // check backup 5
  1331. AssertBackupConsistency(5, 0, max_key);
  1332. // check that "latest backup" still works after deleting latest
  1333. ASSERT_OK(backup_engine_->DeleteBackup(5));
  1334. AssertBackupConsistency(0, 0, 3 * keys_iteration, max_key);
  1335. CloseBackupEngine();
  1336. test_db_fs_->SetCheckIOOptionsSequentialFile(false);
  1337. test_backup_fs_->SetCheckIOOptionsSequentialFile(false);
  1338. }
  1339. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1340. INSTANTIATE_TEST_CASE_P(BackupEngineTestWithParam, BackupEngineTestWithParam,
  1341. ::testing::Bool());
  1342. // this will make sure that backup does not copy the same file twice
  1343. TEST_F(BackupEngineTest, NoDoubleCopy_And_AutoGC) {
  1344. OpenDBAndBackupEngine(true, true);
  1345. // should write 5 DB files + one meta file
  1346. test_backup_fs_->SetLimitWrittenFiles(7);
  1347. test_backup_fs_->ClearWrittenFiles();
  1348. test_db_fs_->SetLimitWrittenFiles(0);
  1349. dummy_db_->live_files_ = {"00010.sst", "00011.sst", "CURRENT", "MANIFEST-01",
  1350. "00011.log"};
  1351. test_db_fs_->SetFilenamesForMockedAttrs(dummy_db_->live_files_);
  1352. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  1353. std::vector<std::string> should_have_written = {
  1354. "/shared/.00010.sst.tmp", "/shared/.00011.sst.tmp", "/private/1/CURRENT",
  1355. "/private/1/MANIFEST-01", "/private/1/00011.log", "/meta/.1.tmp"};
  1356. AppendPath(backupdir_, should_have_written);
  1357. test_backup_fs_->AssertWrittenFiles(should_have_written);
  1358. char db_number = '1';
  1359. for (std::string other_sst : {"00015.sst", "00017.sst", "00019.sst"}) {
  1360. // should write 4 new DB files + one meta file
  1361. // should not write/copy 00010.sst, since it's already there!
  1362. test_backup_fs_->SetLimitWrittenFiles(6);
  1363. test_backup_fs_->ClearWrittenFiles();
  1364. dummy_db_->live_files_ = {"00010.sst", other_sst, "CURRENT", "MANIFEST-01",
  1365. "00011.log"};
  1366. test_db_fs_->SetFilenamesForMockedAttrs(dummy_db_->live_files_);
  1367. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  1368. // should not open 00010.sst - it's already there
  1369. ++db_number;
  1370. std::string private_dir = std::string("/private/") + db_number;
  1371. should_have_written = {
  1372. "/shared/." + other_sst + ".tmp", private_dir + "/CURRENT",
  1373. private_dir + "/MANIFEST-01", private_dir + "/00011.log",
  1374. std::string("/meta/.") + db_number + ".tmp"};
  1375. AppendPath(backupdir_, should_have_written);
  1376. test_backup_fs_->AssertWrittenFiles(should_have_written);
  1377. }
  1378. ASSERT_OK(backup_engine_->DeleteBackup(1));
  1379. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00010.sst"));
  1380. // 00011.sst was only in backup 1, should be deleted
  1381. ASSERT_EQ(Status::NotFound(),
  1382. test_backup_env_->FileExists(backupdir_ + "/shared/00011.sst"));
  1383. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00015.sst"));
  1384. // MANIFEST file size should be only 100
  1385. uint64_t size = 0;
  1386. ASSERT_OK(test_backup_env_->GetFileSize(backupdir_ + "/private/2/MANIFEST-01",
  1387. &size));
  1388. ASSERT_EQ(100UL, size);
  1389. ASSERT_OK(
  1390. test_backup_env_->GetFileSize(backupdir_ + "/shared/00015.sst", &size));
  1391. ASSERT_EQ(200UL, size);
  1392. CloseBackupEngine();
  1393. //
  1394. // Now simulate incomplete delete by removing just meta
  1395. //
  1396. ASSERT_OK(test_backup_env_->DeleteFile(backupdir_ + "/meta/2"));
  1397. OpenBackupEngine();
  1398. // 1 appears to be removed, so
  1399. // 2 non-corrupt and 0 corrupt seen
  1400. std::vector<BackupInfo> backup_info;
  1401. std::vector<BackupID> corrupt_backup_ids;
  1402. backup_engine_->GetBackupInfo(&backup_info);
  1403. backup_engine_->GetCorruptedBackups(&corrupt_backup_ids);
  1404. ASSERT_EQ(2UL, backup_info.size());
  1405. ASSERT_EQ(0UL, corrupt_backup_ids.size());
  1406. // Keep the two we see, but this should suffice to purge unreferenced
  1407. // shared files from incomplete delete.
  1408. ASSERT_OK(backup_engine_->PurgeOldBackups(2));
  1409. // Make sure dangling sst file has been removed (somewhere along this
  1410. // process). GarbageCollect should not be needed.
  1411. ASSERT_EQ(Status::NotFound(),
  1412. test_backup_env_->FileExists(backupdir_ + "/shared/00015.sst"));
  1413. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00017.sst"));
  1414. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00019.sst"));
  1415. // Now actually purge a good one
  1416. ASSERT_OK(backup_engine_->PurgeOldBackups(1));
  1417. ASSERT_EQ(Status::NotFound(),
  1418. test_backup_env_->FileExists(backupdir_ + "/shared/00017.sst"));
  1419. ASSERT_OK(test_backup_env_->FileExists(backupdir_ + "/shared/00019.sst"));
  1420. CloseDBAndBackupEngine();
  1421. }
  1422. // test various kind of corruptions that may happen:
  1423. // 1. Not able to write a file for backup - that backup should fail,
  1424. // everything else should work
  1425. // 2. Corrupted backup meta file or missing backuped file - we should
  1426. // not be able to open that backup, but all other backups should be
  1427. // fine
  1428. // 3. Corrupted checksum value - if the checksum is not a valid uint32_t,
  1429. // db open should fail, otherwise, it aborts during the restore process.
  1430. TEST_F(BackupEngineTest, CorruptionsTest) {
  1431. const int keys_iteration = 5000;
  1432. Random rnd(6);
  1433. Status s;
  1434. OpenDBAndBackupEngine(true);
  1435. // create five backups
  1436. for (int i = 0; i < 5; ++i) {
  1437. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1438. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  1439. }
  1440. // ---------- case 1. - fail a write -----------
  1441. // try creating backup 6, but fail a write
  1442. FillDB(db_.get(), keys_iteration * 5, keys_iteration * 6);
  1443. test_backup_fs_->SetLimitWrittenFiles(2);
  1444. // should fail
  1445. s = backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2));
  1446. ASSERT_NOK(s);
  1447. test_backup_fs_->SetLimitWrittenFiles(1000000);
  1448. // latest backup should have all the keys
  1449. CloseDBAndBackupEngine();
  1450. AssertBackupConsistency(0, 0, keys_iteration * 5, keys_iteration * 6);
  1451. // --------- case 2. corrupted backup meta or missing backuped file ----
  1452. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/5", 3));
  1453. // since 5 meta is now corrupted, latest backup should be 4
  1454. AssertBackupConsistency(0, 0, keys_iteration * 4, keys_iteration * 5);
  1455. OpenBackupEngine();
  1456. s = backup_engine_->RestoreDBFromBackup(5, dbname_, dbname_);
  1457. ASSERT_NOK(s);
  1458. CloseBackupEngine();
  1459. ASSERT_OK(file_manager_->DeleteRandomFileInDir(backupdir_ + "/private/4"));
  1460. // 4 is corrupted, 3 is the latest backup now
  1461. AssertBackupConsistency(0, 0, keys_iteration * 3, keys_iteration * 5);
  1462. OpenBackupEngine();
  1463. s = backup_engine_->RestoreDBFromBackup(4, dbname_, dbname_);
  1464. CloseBackupEngine();
  1465. ASSERT_NOK(s);
  1466. // --------- case 3. corrupted checksum value ----
  1467. ASSERT_OK(file_manager_->CorruptChecksum(backupdir_ + "/meta/3", false));
  1468. // checksum of backup 3 is an invalid value, this can be detected at
  1469. // db open time, and it reverts to the previous backup automatically
  1470. AssertBackupConsistency(0, 0, keys_iteration * 2, keys_iteration * 5);
  1471. // checksum of the backup 2 appears to be valid, this can cause checksum
  1472. // mismatch and abort restore process
  1473. ASSERT_OK(file_manager_->CorruptChecksum(backupdir_ + "/meta/2", true));
  1474. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/2"));
  1475. OpenBackupEngine();
  1476. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/2"));
  1477. s = backup_engine_->RestoreDBFromBackup(2, dbname_, dbname_);
  1478. ASSERT_NOK(s);
  1479. // make sure that no corrupt backups have actually been deleted!
  1480. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/1"));
  1481. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/2"));
  1482. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/3"));
  1483. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/4"));
  1484. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/5"));
  1485. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/1"));
  1486. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/2"));
  1487. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/3"));
  1488. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/4"));
  1489. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/5"));
  1490. // delete the corrupt backups and then make sure they're actually deleted
  1491. ASSERT_OK(backup_engine_->DeleteBackup(5));
  1492. ASSERT_OK(backup_engine_->DeleteBackup(4));
  1493. ASSERT_OK(backup_engine_->DeleteBackup(3));
  1494. ASSERT_OK(backup_engine_->DeleteBackup(2));
  1495. // Should not be needed anymore with auto-GC on DeleteBackup
  1496. //(void)backup_engine_->GarbageCollect();
  1497. ASSERT_EQ(Status::NotFound(),
  1498. file_manager_->FileExists(backupdir_ + "/meta/5"));
  1499. ASSERT_EQ(Status::NotFound(),
  1500. file_manager_->FileExists(backupdir_ + "/private/5"));
  1501. ASSERT_EQ(Status::NotFound(),
  1502. file_manager_->FileExists(backupdir_ + "/meta/4"));
  1503. ASSERT_EQ(Status::NotFound(),
  1504. file_manager_->FileExists(backupdir_ + "/private/4"));
  1505. ASSERT_EQ(Status::NotFound(),
  1506. file_manager_->FileExists(backupdir_ + "/meta/3"));
  1507. ASSERT_EQ(Status::NotFound(),
  1508. file_manager_->FileExists(backupdir_ + "/private/3"));
  1509. ASSERT_EQ(Status::NotFound(),
  1510. file_manager_->FileExists(backupdir_ + "/meta/2"));
  1511. ASSERT_EQ(Status::NotFound(),
  1512. file_manager_->FileExists(backupdir_ + "/private/2"));
  1513. CloseBackupEngine();
  1514. AssertBackupConsistency(0, 0, keys_iteration * 1, keys_iteration * 5);
  1515. // new backup should be 2!
  1516. OpenDBAndBackupEngine();
  1517. FillDB(db_.get(), keys_iteration * 1, keys_iteration * 2);
  1518. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  1519. CloseDBAndBackupEngine();
  1520. AssertBackupConsistency(2, 0, keys_iteration * 2, keys_iteration * 5);
  1521. }
  1522. // Corrupt a file but maintain its size
  1523. TEST_F(BackupEngineTest, CorruptFileMaintainSize) {
  1524. const int keys_iteration = 5000;
  1525. OpenDBAndBackupEngine(true);
  1526. // create a backup
  1527. FillDB(db_.get(), 0, keys_iteration);
  1528. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1529. CloseDBAndBackupEngine();
  1530. OpenDBAndBackupEngine();
  1531. // verify with file size
  1532. ASSERT_OK(backup_engine_->VerifyBackup(1, false));
  1533. // verify with file checksum
  1534. ASSERT_OK(backup_engine_->VerifyBackup(1, true));
  1535. std::string file_to_corrupt;
  1536. uint64_t file_size = 0;
  1537. // under normal circumstance, there should be at least one nonempty file
  1538. while (file_size == 0) {
  1539. // get a random file in /private/1
  1540. assert(file_manager_
  1541. ->GetRandomFileInDir(backupdir_ + "/private/1", &file_to_corrupt,
  1542. &file_size)
  1543. .ok());
  1544. // corrupt the file by replacing its content by file_size random bytes
  1545. ASSERT_OK(file_manager_->CorruptFile(file_to_corrupt, file_size));
  1546. }
  1547. // file sizes match
  1548. ASSERT_OK(backup_engine_->VerifyBackup(1, false));
  1549. // file checksums mismatch
  1550. ASSERT_NOK(backup_engine_->VerifyBackup(1, true));
  1551. // sanity check, use default second argument
  1552. ASSERT_OK(backup_engine_->VerifyBackup(1));
  1553. CloseDBAndBackupEngine();
  1554. // an extra challenge
  1555. // set share_files_with_checksum to true and do two more backups
  1556. // corrupt all the table files in shared_checksum but maintain their sizes
  1557. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  1558. kShareWithChecksum);
  1559. // create two backups
  1560. for (int i = 1; i < 3; ++i) {
  1561. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1562. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1563. }
  1564. CloseDBAndBackupEngine();
  1565. OpenDBAndBackupEngine();
  1566. std::vector<FileAttributes> children;
  1567. const std::string dir = backupdir_ + "/shared_checksum";
  1568. ASSERT_OK(file_manager_->GetChildrenFileAttributes(dir, &children));
  1569. for (const auto& child : children) {
  1570. if (child.size_bytes == 0) {
  1571. continue;
  1572. }
  1573. // corrupt the file by replacing its content by file_size random bytes
  1574. ASSERT_OK(
  1575. file_manager_->CorruptFile(dir + "/" + child.name, child.size_bytes));
  1576. }
  1577. // file sizes match
  1578. ASSERT_OK(backup_engine_->VerifyBackup(1, false));
  1579. ASSERT_OK(backup_engine_->VerifyBackup(2, false));
  1580. // file checksums mismatch
  1581. ASSERT_NOK(backup_engine_->VerifyBackup(1, true));
  1582. ASSERT_NOK(backup_engine_->VerifyBackup(2, true));
  1583. CloseDBAndBackupEngine();
  1584. }
  1585. // Corrupt a blob file but maintain its size
  1586. TEST_P(BackupEngineTestWithParam, CorruptBlobFileMaintainSize) {
  1587. const int keys_iteration = 5000;
  1588. OpenDBAndBackupEngine(true);
  1589. // create a backup
  1590. FillDB(db_.get(), 0, keys_iteration);
  1591. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1592. CloseDBAndBackupEngine();
  1593. OpenDBAndBackupEngine();
  1594. // verify with file size
  1595. ASSERT_OK(backup_engine_->VerifyBackup(1, false));
  1596. // verify with file checksum
  1597. ASSERT_OK(backup_engine_->VerifyBackup(1, true));
  1598. std::string file_to_corrupt;
  1599. std::vector<FileAttributes> children;
  1600. std::string dir = backupdir_;
  1601. if (engine_options_->share_files_with_checksum) {
  1602. dir += "/shared_checksum";
  1603. } else {
  1604. dir += "/shared";
  1605. }
  1606. ASSERT_OK(file_manager_->GetChildrenFileAttributes(dir, &children));
  1607. for (const auto& child : children) {
  1608. if (EndsWith(child.name, ".blob") && child.size_bytes != 0) {
  1609. // corrupt the blob files by replacing its content by file_size random
  1610. // bytes
  1611. ASSERT_OK(
  1612. file_manager_->CorruptFile(dir + "/" + child.name, child.size_bytes));
  1613. }
  1614. }
  1615. // file sizes match
  1616. ASSERT_OK(backup_engine_->VerifyBackup(1, false));
  1617. // file checksums mismatch
  1618. ASSERT_NOK(backup_engine_->VerifyBackup(1, true));
  1619. // sanity check, use default second argument
  1620. ASSERT_OK(backup_engine_->VerifyBackup(1));
  1621. CloseDBAndBackupEngine();
  1622. }
  1623. // Test if BackupEngine will fail to create new backup if some table has been
  1624. // corrupted and the table file checksum is stored in the DB manifest
  1625. TEST_F(BackupEngineTest, TableFileCorruptedBeforeBackup) {
  1626. const int keys_iteration = 50000;
  1627. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  1628. kNoShare);
  1629. FillDB(db_.get(), 0, keys_iteration);
  1630. CloseAndReopenDB(/*read_only*/ true);
  1631. // corrupt a random table file in the DB directory
  1632. ASSERT_OK(CorruptRandomDataFileInDB(kTableFile));
  1633. // file_checksum_gen_factory is null, and thus table checksum is not
  1634. // verified for creating a new backup; no correction is detected
  1635. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1636. CloseDBAndBackupEngine();
  1637. // delete old files in db
  1638. DestroyDBWithoutCheck(dbname_, options_);
  1639. // Enable table file checksum in DB manifest
  1640. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  1641. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  1642. kNoShare);
  1643. FillDB(db_.get(), 0, keys_iteration);
  1644. CloseAndReopenDB(/*read_only*/ true);
  1645. // corrupt a random table file in the DB directory
  1646. ASSERT_OK(CorruptRandomDataFileInDB(kTableFile));
  1647. // table file checksum is enabled so we should be able to detect any
  1648. // corruption
  1649. ASSERT_NOK(backup_engine_->CreateNewBackup(db_.get()));
  1650. CloseDBAndBackupEngine();
  1651. }
  1652. // Test if BackupEngine will fail to create new backup if some blob files has
  1653. // been corrupted and the blob file checksum is stored in the DB manifest
  1654. TEST_F(BackupEngineTest, BlobFileCorruptedBeforeBackup) {
  1655. const int keys_iteration = 50000;
  1656. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  1657. kNoShare);
  1658. FillDB(db_.get(), 0, keys_iteration);
  1659. CloseAndReopenDB(/*read_only*/ true);
  1660. // corrupt a random blob file in the DB directory
  1661. ASSERT_OK(CorruptRandomDataFileInDB(kBlobFile));
  1662. // file_checksum_gen_factory is null, and thus blob checksum is not
  1663. // verified for creating a new backup; no correction is detected
  1664. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1665. CloseDBAndBackupEngine();
  1666. // delete old files in db
  1667. DestroyDBWithoutCheck(dbname_, options_);
  1668. // Enable file checksum in DB manifest
  1669. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  1670. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  1671. kNoShare);
  1672. FillDB(db_.get(), 0, keys_iteration);
  1673. CloseAndReopenDB(/*read_only*/ true);
  1674. // corrupt a random blob file in the DB directory
  1675. ASSERT_OK(CorruptRandomDataFileInDB(kBlobFile));
  1676. // file checksum is enabled so we should be able to detect any
  1677. // corruption
  1678. ASSERT_NOK(backup_engine_->CreateNewBackup(db_.get()));
  1679. CloseDBAndBackupEngine();
  1680. }
  1681. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1682. // Test if BackupEngine will fail to create new backup if some table has been
  1683. // corrupted and the table file checksum is stored in the DB manifest for the
  1684. // case when backup table files will be stored in a shared directory
  1685. TEST_P(BackupEngineTestWithParam, TableFileCorruptedBeforeBackup) {
  1686. const int keys_iteration = 50000;
  1687. OpenDBAndBackupEngine(true /* destroy_old_data */);
  1688. FillDB(db_.get(), 0, keys_iteration);
  1689. CloseAndReopenDB(/*read_only*/ true);
  1690. // corrupt a random table file in the DB directory
  1691. ASSERT_OK(CorruptRandomDataFileInDB(kTableFile));
  1692. // cannot detect corruption since DB manifest has no table checksums
  1693. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1694. CloseDBAndBackupEngine();
  1695. // delete old files in db
  1696. DestroyDBWithoutCheck(dbname_, options_);
  1697. // Enable table checksums in DB manifest
  1698. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  1699. OpenDBAndBackupEngine(true /* destroy_old_data */);
  1700. FillDB(db_.get(), 0, keys_iteration);
  1701. CloseAndReopenDB(/*read_only*/ true);
  1702. // corrupt a random table file in the DB directory
  1703. ASSERT_OK(CorruptRandomDataFileInDB(kTableFile));
  1704. // corruption is detected
  1705. ASSERT_NOK(backup_engine_->CreateNewBackup(db_.get()));
  1706. CloseDBAndBackupEngine();
  1707. }
  1708. // Test if BackupEngine will fail to create new backup if some blob files have
  1709. // been corrupted and the blob file checksum is stored in the DB manifest for
  1710. // the case when backup blob files will be stored in a shared directory
  1711. TEST_P(BackupEngineTestWithParam, BlobFileCorruptedBeforeBackup) {
  1712. const int keys_iteration = 50000;
  1713. OpenDBAndBackupEngine(true /* destroy_old_data */);
  1714. FillDB(db_.get(), 0, keys_iteration);
  1715. CloseAndReopenDB(/*read_only*/ true);
  1716. // corrupt a random blob file in the DB directory
  1717. ASSERT_OK(CorruptRandomDataFileInDB(kBlobFile));
  1718. // cannot detect corruption since DB manifest has no blob file checksums
  1719. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1720. CloseDBAndBackupEngine();
  1721. // delete old files in db
  1722. DestroyDBWithoutCheck(dbname_, options_);
  1723. // Enable blob file checksums in DB manifest
  1724. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  1725. OpenDBAndBackupEngine(true /* destroy_old_data */);
  1726. FillDB(db_.get(), 0, keys_iteration);
  1727. CloseAndReopenDB(/*read_only*/ true);
  1728. // corrupt a random blob file in the DB directory
  1729. ASSERT_OK(CorruptRandomDataFileInDB(kBlobFile));
  1730. // corruption is detected
  1731. ASSERT_NOK(backup_engine_->CreateNewBackup(db_.get()));
  1732. CloseDBAndBackupEngine();
  1733. }
  1734. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1735. TEST_F(BackupEngineTest, TableFileWithoutDbChecksumCorruptedDuringBackup) {
  1736. const int keys_iteration = 50000;
  1737. engine_options_->share_files_with_checksum_naming = kLegacyCrc32cAndFileSize;
  1738. // When share_files_with_checksum is on, we calculate checksums of table
  1739. // files before and after copying. So we can test whether a corruption has
  1740. // happened during the file is copied to backup directory.
  1741. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  1742. kShareWithChecksum);
  1743. FillDB(db_.get(), 0, keys_iteration);
  1744. std::atomic<bool> corrupted{false};
  1745. // corrupt files when copying to the backup directory
  1746. SyncPoint::GetInstance()->SetCallBack(
  1747. "BackupEngineImpl::CopyOrCreateFile:CorruptionDuringBackup",
  1748. [&](void* data) {
  1749. if (data != nullptr) {
  1750. Slice* d = static_cast<Slice*>(data);
  1751. if (!d->empty()) {
  1752. d->remove_suffix(1);
  1753. corrupted = true;
  1754. }
  1755. }
  1756. });
  1757. SyncPoint::GetInstance()->EnableProcessing();
  1758. Status s = backup_engine_->CreateNewBackup(db_.get());
  1759. if (corrupted) {
  1760. ASSERT_NOK(s);
  1761. } else {
  1762. // should not in this path in normal cases
  1763. ASSERT_OK(s);
  1764. }
  1765. SyncPoint::GetInstance()->DisableProcessing();
  1766. SyncPoint::GetInstance()->ClearAllCallBacks();
  1767. CloseDBAndBackupEngine();
  1768. // delete old files in db
  1769. DestroyDBWithoutCheck(dbname_, options_);
  1770. }
  1771. TEST_F(BackupEngineTest, TableFileWithDbChecksumCorruptedDuringBackup) {
  1772. const int keys_iteration = 50000;
  1773. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  1774. for (auto& sopt : kAllShareOptions) {
  1775. // Since the default DB table file checksum is on, we obtain checksums of
  1776. // table files from the DB manifest before copying and verify it with the
  1777. // one calculated during copying.
  1778. // Therefore, we can test whether a corruption has happened during the file
  1779. // being copied to backup directory.
  1780. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */, sopt);
  1781. FillDB(db_.get(), 0, keys_iteration);
  1782. // corrupt files when copying to the backup directory
  1783. SyncPoint::GetInstance()->SetCallBack(
  1784. "BackupEngineImpl::CopyOrCreateFile:CorruptionDuringBackup",
  1785. [&](void* data) {
  1786. if (data != nullptr) {
  1787. Slice* d = static_cast<Slice*>(data);
  1788. if (!d->empty()) {
  1789. d->remove_suffix(1);
  1790. }
  1791. }
  1792. });
  1793. SyncPoint::GetInstance()->EnableProcessing();
  1794. // The only case that we can't detect a corruption is when the file
  1795. // being backed up is empty. But as keys_iteration is large, such
  1796. // a case shouldn't have happened and we should be able to detect
  1797. // the corruption.
  1798. ASSERT_NOK(backup_engine_->CreateNewBackup(db_.get()));
  1799. SyncPoint::GetInstance()->DisableProcessing();
  1800. SyncPoint::GetInstance()->ClearAllCallBacks();
  1801. CloseDBAndBackupEngine();
  1802. // delete old files in db
  1803. DestroyDBWithoutCheck(dbname_, options_);
  1804. }
  1805. }
  1806. TEST_F(BackupEngineTest, InterruptCreationTest) {
  1807. // Interrupt backup creation by failing new writes and failing cleanup of the
  1808. // partial state. Then verify a subsequent backup can still succeed.
  1809. const int keys_iteration = 5000;
  1810. Random rnd(6);
  1811. OpenDBAndBackupEngine(true /* destroy_old_data */);
  1812. FillDB(db_.get(), 0, keys_iteration);
  1813. test_backup_fs_->SetLimitWrittenFiles(2);
  1814. test_backup_fs_->SetDeleteFileFailure(true);
  1815. // should fail creation
  1816. ASSERT_NOK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  1817. CloseDBAndBackupEngine();
  1818. // should also fail cleanup so the tmp directory stays behind
  1819. ASSERT_OK(backup_chroot_env_->FileExists(backupdir_ + "/private/1/"));
  1820. OpenDBAndBackupEngine(false /* destroy_old_data */);
  1821. test_backup_fs_->SetLimitWrittenFiles(1000000);
  1822. test_backup_fs_->SetDeleteFileFailure(false);
  1823. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  1824. // latest backup should have all the keys
  1825. CloseDBAndBackupEngine();
  1826. AssertBackupConsistency(0, 0, keys_iteration);
  1827. }
  1828. TEST_F(BackupEngineTest, FlushCompactDuringBackupCheckpoint) {
  1829. const int keys_iteration = 5000;
  1830. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  1831. for (const auto& sopt : kAllShareOptions) {
  1832. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */, sopt);
  1833. FillDB(db_.get(), 0, keys_iteration);
  1834. // That FillDB leaves a mix of flushed and unflushed data
  1835. SyncPoint::GetInstance()->LoadDependency(
  1836. {{"CheckpointImpl::CreateCustomCheckpoint:AfterGetLive1",
  1837. "BackupEngineTest::FlushCompactDuringBackupCheckpoint:Before"},
  1838. {"BackupEngineTest::FlushCompactDuringBackupCheckpoint:After",
  1839. "CheckpointImpl::CreateCustomCheckpoint:AfterGetLive2"}});
  1840. SyncPoint::GetInstance()->EnableProcessing();
  1841. ROCKSDB_NAMESPACE::port::Thread flush_thread{[this]() {
  1842. TEST_SYNC_POINT(
  1843. "BackupEngineTest::FlushCompactDuringBackupCheckpoint:Before");
  1844. FillDB(db_.get(), keys_iteration, 2 * keys_iteration);
  1845. ASSERT_OK(db_->Flush(FlushOptions()));
  1846. DBImpl* dbi = static_cast<DBImpl*>(db_.get());
  1847. ASSERT_OK(dbi->TEST_WaitForFlushMemTable());
  1848. ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
  1849. ASSERT_OK(dbi->TEST_WaitForCompact());
  1850. TEST_SYNC_POINT(
  1851. "BackupEngineTest::FlushCompactDuringBackupCheckpoint:After");
  1852. }};
  1853. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1854. flush_thread.join();
  1855. CloseDBAndBackupEngine();
  1856. SyncPoint::GetInstance()->DisableProcessing();
  1857. SyncPoint::GetInstance()->ClearAllCallBacks();
  1858. /* FIXME(peterd): reinstate with option for checksum in file names
  1859. if (sopt == kShareWithChecksum) {
  1860. // Ensure we actually got DB manifest checksums by inspecting
  1861. // shared_checksum file names for hex checksum component
  1862. TestRegex expected("[^_]+_[0-9A-F]{8}_[^_]+.sst");
  1863. std::vector<FileAttributes> children;
  1864. const std::string dir = backupdir_ + "/shared_checksum";
  1865. ASSERT_OK(file_manager_->GetChildrenFileAttributes(dir, &children));
  1866. for (const auto& child : children) {
  1867. if (child.size_bytes == 0) {
  1868. continue;
  1869. }
  1870. EXPECT_MATCHES_REGEX(child.name, expected);
  1871. }
  1872. }
  1873. */
  1874. AssertBackupConsistency(0, 0, keys_iteration);
  1875. }
  1876. }
  1877. inline std::string OptionsPath(std::string ret, int backupID) {
  1878. ret += "/private/";
  1879. ret += std::to_string(backupID);
  1880. ret += "/";
  1881. return ret;
  1882. }
  1883. // Backup the LATEST options file to
  1884. // "<backup_dir>/private/<backup_id>/OPTIONS<number>"
  1885. TEST_F(BackupEngineTest, BackupOptions) {
  1886. OpenDBAndBackupEngine(true);
  1887. for (int i = 1; i < 5; i++) {
  1888. std::string name;
  1889. std::vector<std::string> filenames;
  1890. // Must reset() before reset(OpenDB()) again.
  1891. // Calling OpenDB() while *db_ is existing will cause LOCK issue
  1892. db_.reset();
  1893. db_.reset(OpenDB());
  1894. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  1895. ASSERT_OK(ROCKSDB_NAMESPACE::GetLatestOptionsFileName(db_->GetName(),
  1896. options_.env, &name));
  1897. ASSERT_OK(file_manager_->FileExists(OptionsPath(backupdir_, i) + name));
  1898. ASSERT_OK(backup_chroot_env_->GetChildren(OptionsPath(backupdir_, i),
  1899. &filenames));
  1900. for (const auto& fn : filenames) {
  1901. if (fn.compare(0, 7, "OPTIONS") == 0) {
  1902. ASSERT_EQ(name, fn);
  1903. }
  1904. }
  1905. }
  1906. CloseDBAndBackupEngine();
  1907. }
  1908. TEST_F(BackupEngineTest, SetOptionsBackupRaceCondition) {
  1909. OpenDBAndBackupEngine(true);
  1910. SyncPoint::GetInstance()->LoadDependency(
  1911. {{"CheckpointImpl::CreateCheckpoint:SavedLiveFiles1",
  1912. "BackupEngineTest::SetOptionsBackupRaceCondition:BeforeSetOptions"},
  1913. {"BackupEngineTest::SetOptionsBackupRaceCondition:AfterSetOptions",
  1914. "CheckpointImpl::CreateCheckpoint:SavedLiveFiles2"}});
  1915. SyncPoint::GetInstance()->EnableProcessing();
  1916. ROCKSDB_NAMESPACE::port::Thread setoptions_thread{[this]() {
  1917. TEST_SYNC_POINT(
  1918. "BackupEngineTest::SetOptionsBackupRaceCondition:BeforeSetOptions");
  1919. DBImpl* dbi = static_cast<DBImpl*>(db_.get());
  1920. // Change arbitrary option to trigger OPTIONS file deletion
  1921. ASSERT_OK(dbi->SetOptions(dbi->DefaultColumnFamily(),
  1922. {{"paranoid_file_checks", "false"}}));
  1923. ASSERT_OK(dbi->SetOptions(dbi->DefaultColumnFamily(),
  1924. {{"paranoid_file_checks", "true"}}));
  1925. ASSERT_OK(dbi->SetOptions(dbi->DefaultColumnFamily(),
  1926. {{"paranoid_file_checks", "false"}}));
  1927. TEST_SYNC_POINT(
  1928. "BackupEngineTest::SetOptionsBackupRaceCondition:AfterSetOptions");
  1929. }};
  1930. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1931. setoptions_thread.join();
  1932. CloseDBAndBackupEngine();
  1933. }
  1934. // This test verifies we don't delete the latest backup when read-only option is
  1935. // set
  1936. TEST_F(BackupEngineTest, NoDeleteWithReadOnly) {
  1937. const int keys_iteration = 5000;
  1938. Random rnd(6);
  1939. OpenDBAndBackupEngine(true);
  1940. // create five backups
  1941. for (int i = 0; i < 5; ++i) {
  1942. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  1943. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)));
  1944. }
  1945. CloseDBAndBackupEngine();
  1946. ASSERT_OK(file_manager_->WriteToFile(latest_backup_, "4"));
  1947. engine_options_->destroy_old_data = false;
  1948. BackupEngineReadOnly* read_only_backup_engine;
  1949. ASSERT_OK(BackupEngineReadOnly::Open(
  1950. backup_chroot_env_.get(), *engine_options_, &read_only_backup_engine));
  1951. // assert that data from backup 5 is still here (even though LATEST_BACKUP
  1952. // says 4 is latest)
  1953. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/meta/5"));
  1954. ASSERT_OK(file_manager_->FileExists(backupdir_ + "/private/5"));
  1955. // Behavior change: We now ignore LATEST_BACKUP contents. This means that
  1956. // we should have 5 backups, even if LATEST_BACKUP says 4.
  1957. std::vector<BackupInfo> backup_info;
  1958. read_only_backup_engine->GetBackupInfo(&backup_info);
  1959. ASSERT_EQ(5UL, backup_info.size());
  1960. delete read_only_backup_engine;
  1961. }
  1962. TEST_F(BackupEngineTest, FailOverwritingBackups) {
  1963. options_.write_buffer_size = 1024 * 1024 * 1024; // 1GB
  1964. options_.disable_auto_compactions = true;
  1965. // create backups 1, 2, 3, 4, 5
  1966. OpenDBAndBackupEngine(true);
  1967. for (int i = 0; i < 5; ++i) {
  1968. CloseDBAndBackupEngine();
  1969. DeleteLogFiles();
  1970. OpenDBAndBackupEngine(false);
  1971. FillDB(db_.get(), 100 * i, 100 * (i + 1), kFlushAll);
  1972. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1973. }
  1974. CloseDBAndBackupEngine();
  1975. // restore 3
  1976. OpenBackupEngine();
  1977. ASSERT_OK(backup_engine_->RestoreDBFromBackup(3, dbname_, dbname_));
  1978. CloseBackupEngine();
  1979. OpenDBAndBackupEngine(false);
  1980. // More data, bigger SST
  1981. FillDB(db_.get(), 1000, 1300, kFlushAll);
  1982. Status s = backup_engine_->CreateNewBackup(db_.get());
  1983. // the new backup fails because new table files
  1984. // clash with old table files from backups 4 and 5
  1985. // (since write_buffer_size is huge, we can be sure that
  1986. // each backup will generate only one sst file and that
  1987. // a file generated here would have the same name as an
  1988. // sst file generated by backup 4, and will be bigger)
  1989. ASSERT_TRUE(s.IsCorruption());
  1990. ASSERT_OK(backup_engine_->DeleteBackup(4));
  1991. ASSERT_OK(backup_engine_->DeleteBackup(5));
  1992. // now, the backup can succeed
  1993. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  1994. CloseDBAndBackupEngine();
  1995. }
  1996. TEST_F(BackupEngineTest, NoShareTableFiles) {
  1997. const int keys_iteration = 5000;
  1998. OpenDBAndBackupEngine(true, false, kNoShare);
  1999. for (int i = 0; i < 5; ++i) {
  2000. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  2001. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(i % 2)));
  2002. }
  2003. CloseDBAndBackupEngine();
  2004. for (int i = 0; i < 5; ++i) {
  2005. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2006. keys_iteration * 6);
  2007. }
  2008. }
  2009. // Verify that you can backup and restore with share_files_with_checksum on
  2010. TEST_F(BackupEngineTest, ShareTableFilesWithChecksums) {
  2011. const int keys_iteration = 5000;
  2012. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  2013. for (int i = 0; i < 5; ++i) {
  2014. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  2015. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), !!(i % 2)));
  2016. }
  2017. CloseDBAndBackupEngine();
  2018. for (int i = 0; i < 5; ++i) {
  2019. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2020. keys_iteration * 6);
  2021. }
  2022. }
  2023. // Verify that you can backup and restore using share_files_with_checksum set to
  2024. // false and then transition this option to true
  2025. TEST_F(BackupEngineTest, ShareTableFilesWithChecksumsTransition) {
  2026. const int keys_iteration = 5000;
  2027. // set share_files_with_checksum to false
  2028. OpenDBAndBackupEngine(true, false, kShareNoChecksum);
  2029. for (int i = 0; i < 5; ++i) {
  2030. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  2031. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2032. }
  2033. CloseDBAndBackupEngine();
  2034. for (int i = 0; i < 5; ++i) {
  2035. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2036. keys_iteration * 6);
  2037. }
  2038. // set share_files_with_checksum to true and do some more backups
  2039. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  2040. kShareWithChecksum);
  2041. for (int i = 5; i < 10; ++i) {
  2042. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  2043. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2044. }
  2045. CloseDBAndBackupEngine();
  2046. // Verify first (about to delete)
  2047. AssertBackupConsistency(1, 0, keys_iteration, keys_iteration * 11);
  2048. // For an extra challenge, make sure that GarbageCollect / DeleteBackup
  2049. // is OK even if we open without share_table_files
  2050. OpenDBAndBackupEngine(false /* destroy_old_data */, false, kNoShare);
  2051. ASSERT_OK(backup_engine_->DeleteBackup(1));
  2052. ASSERT_OK(backup_engine_->GarbageCollect());
  2053. CloseDBAndBackupEngine();
  2054. // Verify rest (not deleted)
  2055. for (int i = 1; i < 10; ++i) {
  2056. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2057. keys_iteration * 11);
  2058. }
  2059. }
  2060. // Verify backup and restore with various naming options, check names
  2061. TEST_F(BackupEngineTest, ShareTableFilesWithChecksumsNewNaming) {
  2062. ASSERT_TRUE(engine_options_->share_files_with_checksum_naming ==
  2063. kNamingDefault);
  2064. const int keys_iteration = 5000;
  2065. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  2066. FillDB(db_.get(), 0, keys_iteration);
  2067. CloseDBAndBackupEngine();
  2068. static const std::map<ShareFilesNaming, TestRegex> option_to_expected = {
  2069. {kLegacyCrc32cAndFileSize, "[0-9]+_[0-9]+_[0-9]+[.]sst"},
  2070. // kFlagIncludeFileSize redundant here
  2071. {kLegacyCrc32cAndFileSize | kFlagIncludeFileSize,
  2072. "[0-9]+_[0-9]+_[0-9]+[.]sst"},
  2073. {kUseDbSessionId, "[0-9]+_s[0-9A-Z]{20}[.]sst"},
  2074. {kUseDbSessionId | kFlagIncludeFileSize,
  2075. "[0-9]+_s[0-9A-Z]{20}_[0-9]+[.]sst"},
  2076. };
  2077. const TestRegex blobfile_pattern = "[0-9]+_[0-9]+_[0-9]+[.]blob";
  2078. for (const auto& pair : option_to_expected) {
  2079. CloseAndReopenDB();
  2080. engine_options_->share_files_with_checksum_naming = pair.first;
  2081. OpenBackupEngine(true /*destroy_old_data*/);
  2082. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  2083. CloseDBAndBackupEngine();
  2084. AssertBackupConsistency(1, 0, keys_iteration, keys_iteration * 2);
  2085. AssertDirectoryFilesMatchRegex(backupdir_ + "/shared_checksum", pair.second,
  2086. ".sst", 1 /* minimum_count */);
  2087. if (std::string::npos != pair.second.GetPattern().find("_[0-9]+[.]sst")) {
  2088. AssertDirectoryFilesSizeIndicators(backupdir_ + "/shared_checksum",
  2089. 1 /* minimum_count */);
  2090. }
  2091. AssertDirectoryFilesMatchRegex(backupdir_ + "/shared_checksum",
  2092. blobfile_pattern, ".blob",
  2093. 1 /* minimum_count */);
  2094. }
  2095. }
  2096. // Mimic SST file generated by pre-6.12 releases and verify that
  2097. // old names are always used regardless of naming option.
  2098. TEST_F(BackupEngineTest, ShareTableFilesWithChecksumsOldFileNaming) {
  2099. const int keys_iteration = 5000;
  2100. // Pre-6.12 release did not include db id and db session id properties.
  2101. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  2102. "PropertyBlockBuilder::AddTableProperty:Start", [&](void* props_vs) {
  2103. auto props = static_cast<TableProperties*>(props_vs);
  2104. props->db_id = "";
  2105. props->db_session_id = "";
  2106. });
  2107. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  2108. // Corrupting the table properties corrupts the unique id.
  2109. // Ignore the unique id recorded in the manifest.
  2110. options_.verify_sst_unique_id_in_manifest = false;
  2111. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  2112. FillDB(db_.get(), 0, keys_iteration);
  2113. CloseDBAndBackupEngine();
  2114. // Old names should always be used on old files
  2115. const TestRegex sstfile_pattern("[0-9]+_[0-9]+_[0-9]+[.]sst");
  2116. const TestRegex blobfile_pattern = "[0-9]+_[0-9]+_[0-9]+[.]blob";
  2117. for (ShareFilesNaming option : {kNamingDefault, kUseDbSessionId}) {
  2118. CloseAndReopenDB();
  2119. engine_options_->share_files_with_checksum_naming = option;
  2120. OpenBackupEngine(true /*destroy_old_data*/);
  2121. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  2122. CloseDBAndBackupEngine();
  2123. AssertBackupConsistency(1, 0, keys_iteration, keys_iteration * 2);
  2124. AssertDirectoryFilesMatchRegex(backupdir_ + "/shared_checksum",
  2125. sstfile_pattern, ".sst",
  2126. 1 /* minimum_count */);
  2127. AssertDirectoryFilesMatchRegex(backupdir_ + "/shared_checksum",
  2128. blobfile_pattern, ".blob",
  2129. 1 /* minimum_count */);
  2130. }
  2131. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  2132. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  2133. }
  2134. // Test how naming options interact with detecting DB corruption
  2135. // between incremental backups
  2136. TEST_F(BackupEngineTest, TableFileCorruptionBeforeIncremental) {
  2137. const auto share_no_checksum = static_cast<ShareFilesNaming>(0);
  2138. for (bool corrupt_before_first_backup : {false, true}) {
  2139. for (ShareFilesNaming option :
  2140. {share_no_checksum, kLegacyCrc32cAndFileSize, kNamingDefault}) {
  2141. auto share =
  2142. option == share_no_checksum ? kShareNoChecksum : kShareWithChecksum;
  2143. if (option != share_no_checksum) {
  2144. engine_options_->share_files_with_checksum_naming = option;
  2145. }
  2146. OpenDBAndBackupEngine(true, false, share);
  2147. DBImpl* dbi = static_cast<DBImpl*>(db_.get());
  2148. // A small SST file
  2149. ASSERT_OK(dbi->Put(WriteOptions(), "x", "y"));
  2150. ASSERT_OK(dbi->Flush(FlushOptions()));
  2151. // And a bigger one
  2152. ASSERT_OK(dbi->Put(WriteOptions(), "y", Random(42).RandomString(500)));
  2153. ASSERT_OK(dbi->Flush(FlushOptions()));
  2154. ASSERT_OK(dbi->TEST_WaitForFlushMemTable());
  2155. CloseAndReopenDB(/*read_only*/ true);
  2156. std::vector<FileAttributes> table_files;
  2157. ASSERT_OK(GetDataFilesInDB(kTableFile, &table_files));
  2158. ASSERT_EQ(table_files.size(), 2);
  2159. std::string tf0 = dbname_ + "/" + table_files[0].name;
  2160. std::string tf1 = dbname_ + "/" + table_files[1].name;
  2161. CloseDBAndBackupEngine();
  2162. if (corrupt_before_first_backup) {
  2163. // This corrupts a data block, which does not cause DB open
  2164. // failure, only failure on accessing the block.
  2165. ASSERT_OK(db_file_manager_->CorruptFileStart(tf0));
  2166. }
  2167. OpenDBAndBackupEngine(false, false, share);
  2168. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  2169. CloseDBAndBackupEngine();
  2170. // if corrupt_before_first_backup, this undoes the initial corruption
  2171. ASSERT_OK(db_file_manager_->CorruptFileStart(tf0));
  2172. OpenDBAndBackupEngine(false, false, share);
  2173. Status s = backup_engine_->CreateNewBackup(db_.get());
  2174. // Even though none of the naming options catch the inconsistency
  2175. // between the first and second time backing up fname, in the case
  2176. // of kUseDbSessionId (kNamingDefault), this is an intentional
  2177. // trade-off to avoid full scan of files from the DB that are
  2178. // already backed up. If we did the scan, kUseDbSessionId could catch
  2179. // the corruption. kLegacyCrc32cAndFileSize does the scan (to
  2180. // compute checksum for name) without catching the corruption,
  2181. // because the corruption means the names don't merge.
  2182. EXPECT_OK(s);
  2183. // VerifyBackup doesn't check DB integrity or table file internal
  2184. // checksums
  2185. EXPECT_OK(backup_engine_->VerifyBackup(1, true));
  2186. EXPECT_OK(backup_engine_->VerifyBackup(2, true));
  2187. db_.reset();
  2188. ASSERT_OK(backup_engine_->RestoreDBFromBackup(2, dbname_, dbname_));
  2189. {
  2190. DB* db = OpenDB();
  2191. s = db->VerifyChecksum();
  2192. delete db;
  2193. }
  2194. if (option != kLegacyCrc32cAndFileSize && !corrupt_before_first_backup) {
  2195. // Second backup is OK because it used (uncorrupt) file from first
  2196. // backup instead of (corrupt) file from DB.
  2197. // This is arguably a good trade-off vs. treating the file as distinct
  2198. // from the old version, because a file should be more likely to be
  2199. // corrupt as it ages. Although the backed-up file might also corrupt
  2200. // with age, the alternative approach (checksum in file name computed
  2201. // from current DB file contents) wouldn't detect that case at backup
  2202. // time either. Although you would have both copies of the file with
  2203. // the alternative approach, that would only last until the older
  2204. // backup is deleted.
  2205. ASSERT_OK(s);
  2206. } else if (option == kLegacyCrc32cAndFileSize &&
  2207. corrupt_before_first_backup) {
  2208. // Second backup is OK because it saved the updated (uncorrupt)
  2209. // file from DB, instead of the sharing with first backup.
  2210. // Recall: if corrupt_before_first_backup, [second CorruptFileStart]
  2211. // undoes the initial corruption.
  2212. // This is arguably a bad trade-off vs. sharing the old version of the
  2213. // file because a file should be more likely to corrupt as it ages.
  2214. // (Not likely that the previously backed-up version was already
  2215. // corrupt and the new version is non-corrupt. This approach doesn't
  2216. // help if backed-up version is corrupted after taking the backup.)
  2217. ASSERT_OK(s);
  2218. } else {
  2219. // Something is legitimately corrupted, but we can't be sure what
  2220. // with information available (TODO? unless one passes block checksum
  2221. // test and other doesn't. Probably better to use end-to-end full file
  2222. // checksum anyway.)
  2223. ASSERT_TRUE(s.IsCorruption());
  2224. }
  2225. CloseDBAndBackupEngine();
  2226. DestroyDBWithoutCheck(dbname_, options_);
  2227. }
  2228. }
  2229. }
  2230. TEST_F(BackupEngineTest, PropertiesBlockCorruptionIncremental) {
  2231. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  2232. DBImpl* dbi = static_cast<DBImpl*>(db_.get());
  2233. // A small SST file
  2234. ASSERT_OK(dbi->Put(WriteOptions(), "x", "y"));
  2235. ASSERT_OK(dbi->Flush(FlushOptions()));
  2236. ASSERT_OK(dbi->TEST_WaitForFlushMemTable());
  2237. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  2238. CloseBackupEngine();
  2239. std::vector<FileAttributes> table_files;
  2240. ASSERT_OK(GetDataFilesInDB(kTableFile, &table_files));
  2241. ASSERT_EQ(table_files.size(), 1);
  2242. std::string tf = dbname_ + "/" + table_files[0].name;
  2243. // Properties block should be in the middle of a small file
  2244. ASSERT_OK(db_file_manager_->CorruptFileMiddle(tf));
  2245. OpenBackupEngine();
  2246. Status s = backup_engine_->CreateNewBackup(db_.get());
  2247. ASSERT_TRUE(s.IsCorruption());
  2248. CloseDBAndBackupEngine();
  2249. }
  2250. // Test how naming options interact with detecting file size corruption
  2251. // between incremental backups
  2252. TEST_F(BackupEngineTest, FileSizeForIncremental) {
  2253. const auto share_no_checksum = static_cast<ShareFilesNaming>(0);
  2254. // TODO: enable blob files once Integrated BlobDB supports DB session id.
  2255. options_.enable_blob_files = false;
  2256. for (ShareFilesNaming option : {share_no_checksum, kLegacyCrc32cAndFileSize,
  2257. kNamingDefault, kUseDbSessionId}) {
  2258. auto share =
  2259. option == share_no_checksum ? kShareNoChecksum : kShareWithChecksum;
  2260. if (option != share_no_checksum) {
  2261. engine_options_->share_files_with_checksum_naming = option;
  2262. }
  2263. OpenDBAndBackupEngine(true, false, share);
  2264. std::vector<FileAttributes> children;
  2265. const std::string shared_dir =
  2266. backupdir_ +
  2267. (option == share_no_checksum ? "/shared" : "/shared_checksum");
  2268. // A single small SST file
  2269. ASSERT_OK(db_->Put(WriteOptions(), "x", "y"));
  2270. // First, test that we always detect file size corruption on the shared
  2271. // backup side on incremental. (Since sizes aren't really part of backup
  2272. // meta file, this works by querying the filesystem for the sizes.)
  2273. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true /*flush*/));
  2274. CloseDBAndBackupEngine();
  2275. // Corrupt backup SST file
  2276. ASSERT_OK(file_manager_->GetChildrenFileAttributes(shared_dir, &children));
  2277. ASSERT_EQ(children.size(), 1U); // one sst
  2278. for (const auto& child : children) {
  2279. if (child.name.size() > 4 && child.size_bytes > 0) {
  2280. ASSERT_OK(
  2281. file_manager_->WriteToFile(shared_dir + "/" + child.name, "asdf"));
  2282. break;
  2283. }
  2284. }
  2285. OpenDBAndBackupEngine(false, false, share);
  2286. Status s = backup_engine_->CreateNewBackup(db_.get());
  2287. EXPECT_TRUE(s.IsCorruption());
  2288. ASSERT_OK(backup_engine_->PurgeOldBackups(0));
  2289. CloseDBAndBackupEngine();
  2290. // Second, test that a hypothetical db session id collision would likely
  2291. // not suffice to corrupt a backup, because there's a good chance of
  2292. // file size difference (in this test, guaranteed) so either no name
  2293. // collision or detected collision.
  2294. // Create backup 1
  2295. OpenDBAndBackupEngine(false, false, share);
  2296. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  2297. // Even though we have "the same" DB state as backup 1, we need
  2298. // to restore to recreate the same conditions as later restore.
  2299. db_.reset();
  2300. DestroyDBWithoutCheck(dbname_, options_);
  2301. ASSERT_OK(backup_engine_->RestoreDBFromBackup(1, dbname_, dbname_));
  2302. CloseDBAndBackupEngine();
  2303. // Forge session id
  2304. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  2305. "DBImpl::SetDbSessionId", [](void* sid_void_star) {
  2306. std::string* sid = static_cast<std::string*>(sid_void_star);
  2307. *sid = "01234567890123456789";
  2308. });
  2309. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  2310. // Create another SST file
  2311. OpenDBAndBackupEngine(false, false, share);
  2312. ASSERT_OK(db_->Put(WriteOptions(), "y", "x"));
  2313. // Create backup 2
  2314. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true /*flush*/));
  2315. // Restore backup 1 (again)
  2316. db_.reset();
  2317. DestroyDBWithoutCheck(dbname_, options_);
  2318. ASSERT_OK(backup_engine_->RestoreDBFromBackup(1, dbname_, dbname_));
  2319. CloseDBAndBackupEngine();
  2320. // Create another SST file with same number and db session id, only bigger
  2321. OpenDBAndBackupEngine(false, false, share);
  2322. ASSERT_OK(db_->Put(WriteOptions(), "y", Random(42).RandomString(500)));
  2323. // Count backup SSTs files.
  2324. children.clear();
  2325. ASSERT_OK(file_manager_->GetChildrenFileAttributes(shared_dir, &children));
  2326. ASSERT_EQ(children.size(), 2U); // two sst files
  2327. // Try create backup 3
  2328. s = backup_engine_->CreateNewBackup(db_.get(), true /*flush*/);
  2329. // Re-count backup SSTs
  2330. children.clear();
  2331. ASSERT_OK(file_manager_->GetChildrenFileAttributes(shared_dir, &children));
  2332. if (option == kUseDbSessionId) {
  2333. // Acceptable to call it corruption if size is not in name and
  2334. // db session id collision is practically impossible.
  2335. EXPECT_TRUE(s.IsCorruption());
  2336. EXPECT_EQ(children.size(), 2U); // no SST file added
  2337. } else if (option == share_no_checksum) {
  2338. // Good to call it corruption if both backups cannot be
  2339. // accommodated.
  2340. EXPECT_TRUE(s.IsCorruption());
  2341. EXPECT_EQ(children.size(), 2U); // no SST file added
  2342. } else {
  2343. // Since opening a DB seems sufficient for detecting size corruption
  2344. // on the DB side, this should be a good thing, ...
  2345. EXPECT_OK(s);
  2346. // ... as long as we did actually treat it as a distinct SST file.
  2347. EXPECT_EQ(children.size(), 3U); // Another SST added
  2348. }
  2349. CloseDBAndBackupEngine();
  2350. DestroyDBWithoutCheck(dbname_, options_);
  2351. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  2352. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  2353. }
  2354. }
  2355. // Verify backup and restore with share_files_with_checksum off and then
  2356. // transition this option to on and share_files_with_checksum_naming to be
  2357. // based on kUseDbSessionId
  2358. TEST_F(BackupEngineTest, ShareTableFilesWithChecksumsNewNamingTransition) {
  2359. const int keys_iteration = 5000;
  2360. // We may set share_files_with_checksum_naming to kLegacyCrc32cAndFileSize
  2361. // here but even if we don't, it should have no effect when
  2362. // share_files_with_checksum is false
  2363. ASSERT_TRUE(engine_options_->share_files_with_checksum_naming ==
  2364. kNamingDefault);
  2365. // set share_files_with_checksum to false
  2366. OpenDBAndBackupEngine(true, false, kShareNoChecksum);
  2367. int j = 3;
  2368. for (int i = 0; i < j; ++i) {
  2369. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  2370. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2371. }
  2372. CloseDBAndBackupEngine();
  2373. for (int i = 0; i < j; ++i) {
  2374. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2375. keys_iteration * (j + 1));
  2376. }
  2377. // set share_files_with_checksum to true and do some more backups
  2378. // and use session id in the name of SST file backup
  2379. ASSERT_TRUE(engine_options_->share_files_with_checksum_naming ==
  2380. kNamingDefault);
  2381. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  2382. kShareWithChecksum);
  2383. FillDB(db_.get(), keys_iteration * j, keys_iteration * (j + 1));
  2384. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2385. CloseDBAndBackupEngine();
  2386. // Use checksum in the name as well
  2387. ++j;
  2388. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  2389. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  2390. kShareWithChecksum);
  2391. FillDB(db_.get(), keys_iteration * j, keys_iteration * (j + 1));
  2392. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2393. CloseDBAndBackupEngine();
  2394. // Verify first (about to delete)
  2395. AssertBackupConsistency(1, 0, keys_iteration, keys_iteration * (j + 1));
  2396. // For an extra challenge, make sure that GarbageCollect / DeleteBackup
  2397. // is OK even if we open without share_table_files but with
  2398. // share_files_with_checksum_naming based on kUseDbSessionId
  2399. ASSERT_TRUE(engine_options_->share_files_with_checksum_naming ==
  2400. kNamingDefault);
  2401. OpenDBAndBackupEngine(false /* destroy_old_data */, false, kNoShare);
  2402. ASSERT_OK(backup_engine_->DeleteBackup(1));
  2403. ASSERT_OK(backup_engine_->GarbageCollect());
  2404. CloseDBAndBackupEngine();
  2405. // Verify second (about to delete)
  2406. AssertBackupConsistency(2, 0, keys_iteration * 2, keys_iteration * (j + 1));
  2407. // Use checksum and file size for backup table file names and open without
  2408. // share_table_files
  2409. // Again, make sure that GarbageCollect / DeleteBackup is OK
  2410. engine_options_->share_files_with_checksum_naming = kLegacyCrc32cAndFileSize;
  2411. OpenDBAndBackupEngine(false /* destroy_old_data */, false, kNoShare);
  2412. ASSERT_OK(backup_engine_->DeleteBackup(2));
  2413. ASSERT_OK(backup_engine_->GarbageCollect());
  2414. CloseDBAndBackupEngine();
  2415. // Verify rest (not deleted)
  2416. for (int i = 2; i < j; ++i) {
  2417. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2418. keys_iteration * (j + 1));
  2419. }
  2420. }
  2421. // Verify backup and restore with share_files_with_checksum on and transition
  2422. // from kLegacyCrc32cAndFileSize to kUseDbSessionId
  2423. TEST_F(BackupEngineTest, ShareTableFilesWithChecksumsNewNamingUpgrade) {
  2424. engine_options_->share_files_with_checksum_naming = kLegacyCrc32cAndFileSize;
  2425. const int keys_iteration = 5000;
  2426. // set share_files_with_checksum to true
  2427. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  2428. int j = 3;
  2429. for (int i = 0; i < j; ++i) {
  2430. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  2431. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2432. }
  2433. CloseDBAndBackupEngine();
  2434. for (int i = 0; i < j; ++i) {
  2435. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2436. keys_iteration * (j + 1));
  2437. }
  2438. engine_options_->share_files_with_checksum_naming = kUseDbSessionId;
  2439. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  2440. kShareWithChecksum);
  2441. FillDB(db_.get(), keys_iteration * j, keys_iteration * (j + 1));
  2442. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2443. CloseDBAndBackupEngine();
  2444. ++j;
  2445. options_.file_checksum_gen_factory = GetFileChecksumGenCrc32cFactory();
  2446. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  2447. kShareWithChecksum);
  2448. FillDB(db_.get(), keys_iteration * j, keys_iteration * (j + 1));
  2449. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  2450. CloseDBAndBackupEngine();
  2451. // Verify first (about to delete)
  2452. AssertBackupConsistency(1, 0, keys_iteration, keys_iteration * (j + 1));
  2453. // For an extra challenge, make sure that GarbageCollect / DeleteBackup
  2454. // is OK even if we open without share_table_files
  2455. OpenDBAndBackupEngine(false /* destroy_old_data */, false, kNoShare);
  2456. ASSERT_OK(backup_engine_->DeleteBackup(1));
  2457. ASSERT_OK(backup_engine_->GarbageCollect());
  2458. CloseDBAndBackupEngine();
  2459. // Verify second (about to delete)
  2460. AssertBackupConsistency(2, 0, keys_iteration * 2, keys_iteration * (j + 1));
  2461. // Use checksum and file size for backup table file names and open without
  2462. // share_table_files
  2463. // Again, make sure that GarbageCollect / DeleteBackup is OK
  2464. engine_options_->share_files_with_checksum_naming = kLegacyCrc32cAndFileSize;
  2465. OpenDBAndBackupEngine(false /* destroy_old_data */, false, kNoShare);
  2466. ASSERT_OK(backup_engine_->DeleteBackup(2));
  2467. ASSERT_OK(backup_engine_->GarbageCollect());
  2468. CloseDBAndBackupEngine();
  2469. // Verify rest (not deleted)
  2470. for (int i = 2; i < j; ++i) {
  2471. AssertBackupConsistency(i + 1, 0, keys_iteration * (i + 1),
  2472. keys_iteration * (j + 1));
  2473. }
  2474. }
  2475. // This test simulates cleaning up after aborted or incomplete creation
  2476. // of a new backup.
  2477. TEST_F(BackupEngineTest, DeleteTmpFiles) {
  2478. for (int cleanup_fn : {1, 2, 3, 4}) {
  2479. for (ShareOption shared_option : kAllShareOptions) {
  2480. OpenDBAndBackupEngine(false /* destroy_old_data */, false /* dummy */,
  2481. shared_option);
  2482. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  2483. BackupID next_id = 1;
  2484. BackupID oldest_id = std::numeric_limits<BackupID>::max();
  2485. {
  2486. std::vector<BackupInfo> backup_info;
  2487. backup_engine_->GetBackupInfo(&backup_info);
  2488. for (const auto& bi : backup_info) {
  2489. next_id = std::max(next_id, bi.backup_id + 1);
  2490. oldest_id = std::min(oldest_id, bi.backup_id);
  2491. }
  2492. }
  2493. CloseDBAndBackupEngine();
  2494. // An aborted or incomplete new backup will always be in the next
  2495. // id (maybe more)
  2496. std::string next_private = "private/" + std::to_string(next_id);
  2497. // NOTE: both shared and shared_checksum should be cleaned up
  2498. // regardless of how the backup engine is opened.
  2499. std::vector<std::string> tmp_files_and_dirs;
  2500. for (const auto& dir_and_file : {
  2501. std::make_pair(std::string("shared"),
  2502. std::string(".00006.sst.tmp")),
  2503. std::make_pair(std::string("shared_checksum"),
  2504. std::string(".00007.sst.tmp")),
  2505. std::make_pair(next_private, std::string("00003.sst")),
  2506. }) {
  2507. std::string dir = backupdir_ + "/" + dir_and_file.first;
  2508. ASSERT_OK(file_manager_->CreateDirIfMissing(dir));
  2509. ASSERT_OK(file_manager_->FileExists(dir));
  2510. std::string file = dir + "/" + dir_and_file.second;
  2511. ASSERT_OK(file_manager_->WriteToFile(file, "tmp"));
  2512. ASSERT_OK(file_manager_->FileExists(file));
  2513. tmp_files_and_dirs.push_back(file);
  2514. }
  2515. if (cleanup_fn != /*CreateNewBackup*/ 4) {
  2516. // This exists after CreateNewBackup because it's deleted then
  2517. // re-created.
  2518. tmp_files_and_dirs.push_back(backupdir_ + "/" + next_private);
  2519. }
  2520. OpenDBAndBackupEngine(false /* destroy_old_data */, false /* dummy */,
  2521. shared_option);
  2522. // Need to call one of these explicitly to delete tmp files
  2523. switch (cleanup_fn) {
  2524. case 1:
  2525. ASSERT_OK(backup_engine_->GarbageCollect());
  2526. break;
  2527. case 2:
  2528. ASSERT_OK(backup_engine_->DeleteBackup(oldest_id));
  2529. break;
  2530. case 3:
  2531. ASSERT_OK(backup_engine_->PurgeOldBackups(1));
  2532. break;
  2533. case 4:
  2534. // Does a garbage collect if it sees that next private dir exists
  2535. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  2536. break;
  2537. default:
  2538. assert(false);
  2539. }
  2540. CloseDBAndBackupEngine();
  2541. for (const std::string& file_or_dir : tmp_files_and_dirs) {
  2542. if (file_manager_->FileExists(file_or_dir) != Status::NotFound()) {
  2543. FAIL() << file_or_dir << " was expected to be deleted." << cleanup_fn;
  2544. }
  2545. }
  2546. }
  2547. }
  2548. }
  2549. TEST_F(BackupEngineTest, KeepLogFiles) {
  2550. engine_options_->backup_log_files = false;
  2551. // basically infinite
  2552. options_.WAL_ttl_seconds = 24 * 60 * 60;
  2553. OpenDBAndBackupEngine(true);
  2554. FillDB(db_.get(), 0, 100, kFlushAll);
  2555. FillDB(db_.get(), 100, 200, kFlushAll);
  2556. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  2557. FillDB(db_.get(), 200, 300, kFlushAll);
  2558. FillDB(db_.get(), 300, 400, kFlushAll);
  2559. FillDB(db_.get(), 400, 500, kFlushAll);
  2560. CloseDBAndBackupEngine();
  2561. // all data should be there if we call with keep_log_files = true
  2562. AssertBackupConsistency(0, 0, 500, 600, true);
  2563. }
  2564. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  2565. class BackupEngineRateLimitingTestWithParam
  2566. : public BackupEngineTest,
  2567. public testing::WithParamInterface<
  2568. std::tuple<bool /* make throttle */,
  2569. int /* 0 = single threaded, 1 = multi threaded*/,
  2570. std::pair<uint64_t, uint64_t> /* limits */>> {
  2571. public:
  2572. BackupEngineRateLimitingTestWithParam() = default;
  2573. };
  2574. uint64_t const MB = 1024 * 1024;
  2575. INSTANTIATE_TEST_CASE_P(
  2576. RateLimiting, BackupEngineRateLimitingTestWithParam,
  2577. ::testing::Values(std::make_tuple(false, 0, std::make_pair(1 * MB, 5 * MB)),
  2578. std::make_tuple(false, 0, std::make_pair(2 * MB, 3 * MB)),
  2579. std::make_tuple(false, 1, std::make_pair(1 * MB, 5 * MB)),
  2580. std::make_tuple(false, 1, std::make_pair(2 * MB, 3 * MB)),
  2581. std::make_tuple(true, 0, std::make_pair(1 * MB, 5 * MB)),
  2582. std::make_tuple(true, 0, std::make_pair(2 * MB, 3 * MB)),
  2583. std::make_tuple(true, 1, std::make_pair(1 * MB, 5 * MB)),
  2584. std::make_tuple(true, 1,
  2585. std::make_pair(2 * MB, 3 * MB))));
  2586. TEST_P(BackupEngineRateLimitingTestWithParam, RateLimiting) {
  2587. size_t const kMicrosPerSec = 1000 * 1000LL;
  2588. const bool custom_rate_limiter = std::get<0>(GetParam());
  2589. // iter 0 -- single threaded
  2590. // iter 1 -- multi threaded
  2591. const int iter = std::get<1>(GetParam());
  2592. const std::pair<uint64_t, uint64_t> limit = std::get<2>(GetParam());
  2593. std::unique_ptr<Env> special_env(
  2594. new SpecialEnv(db_chroot_env_.get(), /*time_elapse_only_sleep*/ true));
  2595. // destroy old data
  2596. Options options;
  2597. options.env = special_env.get();
  2598. DestroyDBWithoutCheck(dbname_, options);
  2599. if (custom_rate_limiter) {
  2600. std::shared_ptr<RateLimiter> backup_rate_limiter =
  2601. std::make_shared<GenericRateLimiter>(
  2602. limit.first, 100 * 1000 /* refill_period_us */, 10 /* fairness */,
  2603. RateLimiter::Mode::kWritesOnly /* mode */,
  2604. special_env->GetSystemClock(), false /* auto_tuned */,
  2605. 0 /* single_burst_bytes */);
  2606. std::shared_ptr<RateLimiter> restore_rate_limiter =
  2607. std::make_shared<GenericRateLimiter>(
  2608. limit.second, 100 * 1000 /* refill_period_us */, 10 /* fairness */,
  2609. RateLimiter::Mode::kWritesOnly /* mode */,
  2610. special_env->GetSystemClock(), false /* auto_tuned */,
  2611. 0 /* single_burst_bytes */);
  2612. engine_options_->backup_rate_limiter = backup_rate_limiter;
  2613. engine_options_->restore_rate_limiter = restore_rate_limiter;
  2614. } else {
  2615. engine_options_->backup_rate_limit = limit.first;
  2616. engine_options_->restore_rate_limit = limit.second;
  2617. }
  2618. engine_options_->max_background_operations = (iter == 0) ? 1 : 10;
  2619. options_.compression = kNoCompression;
  2620. // Rate limiter uses `CondVar::TimedWait()`, which does not have access to the
  2621. // `Env` to advance its time according to the fake wait duration. The
  2622. // workaround is to install a callback that advance the `Env`'s mock time.
  2623. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  2624. "GenericRateLimiter::Request:PostTimedWait", [&](void* arg) {
  2625. int64_t time_waited_us = *static_cast<int64_t*>(arg);
  2626. special_env->SleepForMicroseconds(static_cast<int>(time_waited_us));
  2627. });
  2628. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  2629. OpenDBAndBackupEngine(true);
  2630. TEST_SetDefaultRateLimitersClock(backup_engine_.get(),
  2631. special_env->GetSystemClock());
  2632. size_t bytes_written = FillDB(db_.get(), 0, 10000);
  2633. auto start_backup = special_env->NowMicros();
  2634. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  2635. auto backup_time = special_env->NowMicros() - start_backup;
  2636. CloseDBAndBackupEngine();
  2637. auto rate_limited_backup_time = (bytes_written * kMicrosPerSec) / limit.first;
  2638. ASSERT_GT(backup_time, 0.8 * rate_limited_backup_time);
  2639. OpenBackupEngine();
  2640. TEST_SetDefaultRateLimitersClock(
  2641. backup_engine_.get(),
  2642. special_env->GetSystemClock() /* backup_rate_limiter_clock */,
  2643. special_env->GetSystemClock() /* restore_rate_limiter_clock */);
  2644. auto start_restore = special_env->NowMicros();
  2645. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_));
  2646. auto restore_time = special_env->NowMicros() - start_restore;
  2647. CloseBackupEngine();
  2648. auto rate_limited_restore_time =
  2649. (bytes_written * kMicrosPerSec) / limit.second;
  2650. ASSERT_GT(restore_time, 0.8 * rate_limited_restore_time);
  2651. AssertBackupConsistency(0, 0, 10000, 10100);
  2652. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  2653. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearCallBack(
  2654. "GenericRateLimiter::Request:PostTimedWait");
  2655. }
  2656. TEST_P(BackupEngineRateLimitingTestWithParam, RateLimitingVerifyBackup) {
  2657. const std::size_t kMicrosPerSec = 1000 * 1000LL;
  2658. const bool custom_rate_limiter = std::get<0>(GetParam());
  2659. const std::uint64_t backup_rate_limiter_limit = std::get<2>(GetParam()).first;
  2660. const bool is_single_threaded = std::get<1>(GetParam()) == 0 ? true : false;
  2661. std::unique_ptr<Env> special_env(
  2662. new SpecialEnv(db_chroot_env_.get(), /*time_elapse_only_sleep*/ true));
  2663. if (custom_rate_limiter) {
  2664. std::shared_ptr<RateLimiter> backup_rate_limiter =
  2665. std::make_shared<GenericRateLimiter>(
  2666. backup_rate_limiter_limit, 100 * 1000 /* refill_period_us */,
  2667. 10 /* fairness */, RateLimiter::Mode::kAllIo /* mode */,
  2668. special_env->GetSystemClock(), false /* auto_tuned */,
  2669. 0 /* single_burst_bytes */);
  2670. engine_options_->backup_rate_limiter = backup_rate_limiter;
  2671. } else {
  2672. engine_options_->backup_rate_limit = backup_rate_limiter_limit;
  2673. }
  2674. engine_options_->max_background_operations = is_single_threaded ? 1 : 10;
  2675. Options options;
  2676. options.env = special_env.get();
  2677. DestroyDBWithoutCheck(dbname_, options);
  2678. // Rate limiter uses `CondVar::TimedWait()`, which does not have access to the
  2679. // `Env` to advance its time according to the fake wait duration. The
  2680. // workaround is to install a callback that advance the `Env`'s mock time.
  2681. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  2682. "GenericRateLimiter::Request:PostTimedWait", [&](void* arg) {
  2683. int64_t time_waited_us = *static_cast<int64_t*>(arg);
  2684. special_env->SleepForMicroseconds(static_cast<int>(time_waited_us));
  2685. });
  2686. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  2687. OpenDBAndBackupEngine(true /* destroy_old_data */);
  2688. TEST_SetDefaultRateLimitersClock(backup_engine_.get(),
  2689. special_env->GetSystemClock(), nullptr);
  2690. FillDB(db_.get(), 0, 10000);
  2691. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  2692. false /* flush_before_backup */));
  2693. std::vector<BackupInfo> backup_infos;
  2694. BackupInfo backup_info;
  2695. backup_engine_->GetBackupInfo(&backup_infos);
  2696. ASSERT_EQ(1, backup_infos.size());
  2697. const int backup_id = 1;
  2698. ASSERT_EQ(backup_id, backup_infos[0].backup_id);
  2699. ASSERT_OK(backup_engine_->GetBackupInfo(backup_id, &backup_info,
  2700. true /* include_file_details */));
  2701. std::uint64_t bytes_read_during_verify_backup = 0;
  2702. for (const BackupFileInfo& backup_file_info : backup_info.file_details) {
  2703. bytes_read_during_verify_backup += backup_file_info.size;
  2704. }
  2705. auto start_verify_backup = special_env->NowMicros();
  2706. ASSERT_OK(
  2707. backup_engine_->VerifyBackup(backup_id, true /* verify_with_checksum */));
  2708. auto verify_backup_time = special_env->NowMicros() - start_verify_backup;
  2709. auto rate_limited_verify_backup_time =
  2710. (bytes_read_during_verify_backup * kMicrosPerSec) /
  2711. backup_rate_limiter_limit;
  2712. if (custom_rate_limiter) {
  2713. EXPECT_GE(verify_backup_time, 0.8 * rate_limited_verify_backup_time);
  2714. }
  2715. CloseDBAndBackupEngine();
  2716. AssertBackupConsistency(backup_id, 0, 10000, 10010);
  2717. DestroyDBWithoutCheck(dbname_, options);
  2718. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  2719. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearCallBack(
  2720. "GenericRateLimiter::Request:PostTimedWait");
  2721. }
  2722. TEST_P(BackupEngineRateLimitingTestWithParam, RateLimitingChargeReadInBackup) {
  2723. bool is_single_threaded = std::get<1>(GetParam()) == 0 ? true : false;
  2724. engine_options_->max_background_operations = is_single_threaded ? 1 : 10;
  2725. const std::uint64_t backup_rate_limiter_limit = std::get<2>(GetParam()).first;
  2726. std::shared_ptr<RateLimiter> backup_rate_limiter(NewGenericRateLimiter(
  2727. backup_rate_limiter_limit, 100 * 1000 /* refill_period_us */,
  2728. 10 /* fairness */, RateLimiter::Mode::kWritesOnly /* mode */));
  2729. engine_options_->backup_rate_limiter = backup_rate_limiter;
  2730. DestroyDBWithoutCheck(dbname_, Options());
  2731. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  2732. kShareWithChecksum /* shared_option */);
  2733. FillDB(db_.get(), 0, 10);
  2734. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  2735. false /* flush_before_backup */));
  2736. std::int64_t total_bytes_through_with_no_read_charged =
  2737. backup_rate_limiter->GetTotalBytesThrough();
  2738. CloseBackupEngine();
  2739. backup_rate_limiter.reset(NewGenericRateLimiter(
  2740. backup_rate_limiter_limit, 100 * 1000 /* refill_period_us */,
  2741. 10 /* fairness */, RateLimiter::Mode::kAllIo /* mode */));
  2742. engine_options_->backup_rate_limiter = backup_rate_limiter;
  2743. OpenBackupEngine(true);
  2744. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  2745. false /* flush_before_backup */));
  2746. std::int64_t total_bytes_through_with_read_charged =
  2747. backup_rate_limiter->GetTotalBytesThrough();
  2748. EXPECT_GT(total_bytes_through_with_read_charged,
  2749. total_bytes_through_with_no_read_charged);
  2750. CloseDBAndBackupEngine();
  2751. AssertBackupConsistency(1, 0, 10, 20);
  2752. DestroyDBWithoutCheck(dbname_, Options());
  2753. }
  2754. TEST_P(BackupEngineRateLimitingTestWithParam, RateLimitingChargeReadInRestore) {
  2755. bool is_single_threaded = std::get<1>(GetParam()) == 0 ? true : false;
  2756. engine_options_->max_background_operations = is_single_threaded ? 1 : 10;
  2757. const std::uint64_t restore_rate_limiter_limit =
  2758. std::get<2>(GetParam()).second;
  2759. std::shared_ptr<RateLimiter> restore_rate_limiter(NewGenericRateLimiter(
  2760. restore_rate_limiter_limit, 100 * 1000 /* refill_period_us */,
  2761. 10 /* fairness */, RateLimiter::Mode::kWritesOnly /* mode */));
  2762. engine_options_->restore_rate_limiter = restore_rate_limiter;
  2763. DestroyDBWithoutCheck(dbname_, Options());
  2764. OpenDBAndBackupEngine(true /* destroy_old_data */);
  2765. FillDB(db_.get(), 0, 10);
  2766. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  2767. false /* flush_before_backup */));
  2768. CloseDBAndBackupEngine();
  2769. DestroyDBWithoutCheck(dbname_, Options());
  2770. OpenBackupEngine(false /* destroy_old_data */);
  2771. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_));
  2772. std::int64_t total_bytes_through_with_no_read_charged =
  2773. restore_rate_limiter->GetTotalBytesThrough();
  2774. CloseBackupEngine();
  2775. DestroyDBWithoutCheck(dbname_, Options());
  2776. restore_rate_limiter.reset(NewGenericRateLimiter(
  2777. restore_rate_limiter_limit, 100 * 1000 /* refill_period_us */,
  2778. 10 /* fairness */, RateLimiter::Mode::kAllIo /* mode */));
  2779. engine_options_->restore_rate_limiter = restore_rate_limiter;
  2780. OpenBackupEngine(false /* destroy_old_data */);
  2781. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_));
  2782. std::int64_t total_bytes_through_with_read_charged =
  2783. restore_rate_limiter->GetTotalBytesThrough();
  2784. EXPECT_EQ(total_bytes_through_with_read_charged,
  2785. total_bytes_through_with_no_read_charged * 2);
  2786. CloseBackupEngine();
  2787. AssertBackupConsistency(1, 0, 10, 20);
  2788. DestroyDBWithoutCheck(dbname_, Options());
  2789. }
  2790. TEST_P(BackupEngineRateLimitingTestWithParam,
  2791. RateLimitingChargeReadInInitialize) {
  2792. bool is_single_threaded = std::get<1>(GetParam()) == 0 ? true : false;
  2793. engine_options_->max_background_operations = is_single_threaded ? 1 : 10;
  2794. const std::uint64_t backup_rate_limiter_limit = std::get<2>(GetParam()).first;
  2795. std::shared_ptr<RateLimiter> backup_rate_limiter(NewGenericRateLimiter(
  2796. backup_rate_limiter_limit, 100 * 1000 /* refill_period_us */,
  2797. 10 /* fairness */, RateLimiter::Mode::kAllIo /* mode */));
  2798. engine_options_->backup_rate_limiter = backup_rate_limiter;
  2799. DestroyDBWithoutCheck(dbname_, Options());
  2800. OpenDBAndBackupEngine(true /* destroy_old_data */);
  2801. FillDB(db_.get(), 0, 10);
  2802. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  2803. false /* flush_before_backup */));
  2804. CloseDBAndBackupEngine();
  2805. AssertBackupConsistency(1, 0, 10, 20);
  2806. std::int64_t total_bytes_through_before_initialize =
  2807. engine_options_->backup_rate_limiter->GetTotalBytesThrough();
  2808. OpenDBAndBackupEngine(false /* destroy_old_data */);
  2809. // We charge read in BackupEngineImpl::BackupMeta::LoadFromFile,
  2810. // which is called in BackupEngineImpl::Initialize() during
  2811. // OpenBackupEngine(false)
  2812. EXPECT_GT(engine_options_->backup_rate_limiter->GetTotalBytesThrough(),
  2813. total_bytes_through_before_initialize);
  2814. CloseDBAndBackupEngine();
  2815. DestroyDBWithoutCheck(dbname_, Options());
  2816. }
  2817. class BackupEngineRateLimitingTestWithParam2
  2818. : public BackupEngineTest,
  2819. public testing::WithParamInterface<
  2820. std::tuple<std::pair<uint64_t, uint64_t> /* limits */>> {
  2821. public:
  2822. BackupEngineRateLimitingTestWithParam2() = default;
  2823. };
  2824. INSTANTIATE_TEST_CASE_P(
  2825. LowRefillBytesPerPeriod, BackupEngineRateLimitingTestWithParam2,
  2826. ::testing::Values(std::make_tuple(std::make_pair(1, 1))));
  2827. // To verify we don't request over-sized bytes relative to
  2828. // refill_bytes_per_period_ in each RateLimiter::Request() called in
  2829. // BackupEngine through verifying we don't trigger assertion
  2830. // failure on over-sized request in GenericRateLimiter in debug builds
  2831. TEST_P(BackupEngineRateLimitingTestWithParam2,
  2832. RateLimitingWithLowRefillBytesPerPeriod) {
  2833. SpecialEnv special_env(Env::Default(), /*time_elapse_only_sleep*/ true);
  2834. engine_options_->max_background_operations = 1;
  2835. const uint64_t backup_rate_limiter_limit = std::get<0>(GetParam()).first;
  2836. std::shared_ptr<RateLimiter> backup_rate_limiter(
  2837. std::make_shared<GenericRateLimiter>(
  2838. backup_rate_limiter_limit, 1000 * 1000 /* refill_period_us */,
  2839. 10 /* fairness */, RateLimiter::Mode::kAllIo /* mode */,
  2840. special_env.GetSystemClock(), false /* auto_tuned */,
  2841. 0 /* single_burst_bytes */));
  2842. engine_options_->backup_rate_limiter = backup_rate_limiter;
  2843. const uint64_t restore_rate_limiter_limit = std::get<0>(GetParam()).second;
  2844. std::shared_ptr<RateLimiter> restore_rate_limiter(
  2845. std::make_shared<GenericRateLimiter>(
  2846. restore_rate_limiter_limit, 1000 * 1000 /* refill_period_us */,
  2847. 10 /* fairness */, RateLimiter::Mode::kAllIo /* mode */,
  2848. special_env.GetSystemClock(), false /* auto_tuned */,
  2849. 0 /* single_burst_bytes */));
  2850. engine_options_->restore_rate_limiter = restore_rate_limiter;
  2851. // Rate limiter uses `CondVar::TimedWait()`, which does not have access to the
  2852. // `Env` to advance its time according to the fake wait duration. The
  2853. // workaround is to install a callback that advance the `Env`'s mock time.
  2854. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  2855. "GenericRateLimiter::Request:PostTimedWait", [&](void* arg) {
  2856. int64_t time_waited_us = *static_cast<int64_t*>(arg);
  2857. special_env.SleepForMicroseconds(static_cast<int>(time_waited_us));
  2858. });
  2859. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  2860. DestroyDBWithoutCheck(dbname_, Options());
  2861. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  2862. kShareWithChecksum /* shared_option */);
  2863. FillDB(db_.get(), 0, 100);
  2864. int64_t total_bytes_through_before_backup =
  2865. engine_options_->backup_rate_limiter->GetTotalBytesThrough();
  2866. EXPECT_OK(backup_engine_->CreateNewBackup(db_.get(),
  2867. false /* flush_before_backup */));
  2868. int64_t total_bytes_through_after_backup =
  2869. engine_options_->backup_rate_limiter->GetTotalBytesThrough();
  2870. ASSERT_GT(total_bytes_through_after_backup,
  2871. total_bytes_through_before_backup);
  2872. std::vector<BackupInfo> backup_infos;
  2873. BackupInfo backup_info;
  2874. backup_engine_->GetBackupInfo(&backup_infos);
  2875. ASSERT_EQ(1, backup_infos.size());
  2876. const int backup_id = 1;
  2877. ASSERT_EQ(backup_id, backup_infos[0].backup_id);
  2878. ASSERT_OK(backup_engine_->GetBackupInfo(backup_id, &backup_info,
  2879. true /* include_file_details */));
  2880. int64_t total_bytes_through_before_verify_backup =
  2881. engine_options_->backup_rate_limiter->GetTotalBytesThrough();
  2882. EXPECT_OK(
  2883. backup_engine_->VerifyBackup(backup_id, true /* verify_with_checksum */));
  2884. int64_t total_bytes_through_after_verify_backup =
  2885. engine_options_->backup_rate_limiter->GetTotalBytesThrough();
  2886. ASSERT_GT(total_bytes_through_after_verify_backup,
  2887. total_bytes_through_before_verify_backup);
  2888. CloseDBAndBackupEngine();
  2889. AssertBackupConsistency(backup_id, 0, 100, 101);
  2890. int64_t total_bytes_through_before_initialize =
  2891. engine_options_->backup_rate_limiter->GetTotalBytesThrough();
  2892. OpenDBAndBackupEngine(false /* destroy_old_data */);
  2893. // We charge read in BackupEngineImpl::BackupMeta::LoadFromFile,
  2894. // which is called in BackupEngineImpl::Initialize() during
  2895. // OpenBackupEngine(false)
  2896. int64_t total_bytes_through_after_initialize =
  2897. engine_options_->backup_rate_limiter->GetTotalBytesThrough();
  2898. ASSERT_GT(total_bytes_through_after_initialize,
  2899. total_bytes_through_before_initialize);
  2900. CloseDBAndBackupEngine();
  2901. DestroyDBWithoutCheck(dbname_, Options());
  2902. OpenBackupEngine(false /* destroy_old_data */);
  2903. int64_t total_bytes_through_before_restore =
  2904. engine_options_->restore_rate_limiter->GetTotalBytesThrough();
  2905. EXPECT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_));
  2906. int64_t total_bytes_through_after_restore =
  2907. engine_options_->restore_rate_limiter->GetTotalBytesThrough();
  2908. ASSERT_GT(total_bytes_through_after_restore,
  2909. total_bytes_through_before_restore);
  2910. CloseBackupEngine();
  2911. DestroyDBWithoutCheck(dbname_, Options());
  2912. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  2913. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearCallBack(
  2914. "GenericRateLimiter::Request:PostTimedWait");
  2915. }
  2916. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  2917. TEST_F(BackupEngineTest, ReadOnlyBackupEngine) {
  2918. DestroyDBWithoutCheck(dbname_, options_);
  2919. OpenDBAndBackupEngine(true);
  2920. FillDB(db_.get(), 0, 100);
  2921. // Also test read-only DB with CreateNewBackup and flush=true (no flush)
  2922. CloseAndReopenDB(/*read_only*/ true);
  2923. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), /*flush*/ true));
  2924. CloseAndReopenDB(/*read_only*/ false);
  2925. FillDB(db_.get(), 100, 200);
  2926. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), /*flush*/ true));
  2927. CloseDBAndBackupEngine();
  2928. DestroyDBWithoutCheck(dbname_, options_);
  2929. engine_options_->destroy_old_data = false;
  2930. test_backup_fs_->ClearWrittenFiles();
  2931. test_backup_fs_->SetLimitDeleteFiles(0);
  2932. BackupEngineReadOnly* read_only_backup_engine;
  2933. ASSERT_OK(BackupEngineReadOnly::Open(db_chroot_env_.get(), *engine_options_,
  2934. &read_only_backup_engine));
  2935. std::vector<BackupInfo> backup_info;
  2936. read_only_backup_engine->GetBackupInfo(&backup_info);
  2937. ASSERT_EQ(backup_info.size(), 2U);
  2938. RestoreOptions restore_options(false);
  2939. ASSERT_OK(read_only_backup_engine->RestoreDBFromLatestBackup(
  2940. dbname_, dbname_, restore_options));
  2941. delete read_only_backup_engine;
  2942. std::vector<std::string> should_have_written;
  2943. test_backup_fs_->AssertWrittenFiles(should_have_written);
  2944. DB* db = OpenDB();
  2945. AssertExists(db, 0, 200);
  2946. delete db;
  2947. }
  2948. TEST_F(BackupEngineTest, OpenBackupAsReadOnlyDB) {
  2949. DestroyDBWithoutCheck(dbname_, options_);
  2950. options_.write_dbid_to_manifest = false;
  2951. OpenDBAndBackupEngine(true);
  2952. FillDB(db_.get(), 0, 100);
  2953. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), /*flush*/ false));
  2954. options_.write_dbid_to_manifest = true; // exercises some read-only DB code
  2955. CloseAndReopenDB();
  2956. FillDB(db_.get(), 100, 200);
  2957. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), /*flush*/ false));
  2958. db_.reset(); // CloseDB
  2959. DestroyDBWithoutCheck(dbname_, options_);
  2960. BackupInfo backup_info;
  2961. // First, check that we get empty fields without include_file_details
  2962. ASSERT_OK(backup_engine_->GetBackupInfo(/*id*/ 1U, &backup_info,
  2963. /*with file details*/ false));
  2964. ASSERT_EQ(backup_info.name_for_open, "");
  2965. ASSERT_FALSE(backup_info.env_for_open);
  2966. // Now for the real test
  2967. backup_info = BackupInfo();
  2968. ASSERT_OK(backup_engine_->GetBackupInfo(/*id*/ 1U, &backup_info,
  2969. /*with file details*/ true));
  2970. // Caution: DBOptions only holds a raw pointer to Env, so something else
  2971. // must keep it alive.
  2972. // Case 1: Keeping BackupEngine open suffices to keep Env alive
  2973. DB* db = nullptr;
  2974. Options opts = options_;
  2975. // Ensure some key defaults are set
  2976. opts.wal_dir = "";
  2977. opts.create_if_missing = false;
  2978. opts.info_log.reset();
  2979. opts.env = backup_info.env_for_open.get();
  2980. std::string name = backup_info.name_for_open;
  2981. backup_info = BackupInfo();
  2982. ASSERT_OK(DB::OpenForReadOnly(opts, name, &db));
  2983. AssertExists(db, 0, 100);
  2984. AssertEmpty(db, 100, 200);
  2985. delete db;
  2986. db = nullptr;
  2987. // Case 2: Keeping BackupInfo alive rather than BackupEngine also suffices
  2988. ASSERT_OK(backup_engine_->GetBackupInfo(/*id*/ 2U, &backup_info,
  2989. /*with file details*/ true));
  2990. CloseBackupEngine();
  2991. opts.create_if_missing = true; // check also OK (though pointless)
  2992. opts.env = backup_info.env_for_open.get();
  2993. name = backup_info.name_for_open;
  2994. // Note: keeping backup_info alive
  2995. ASSERT_OK(DB::OpenForReadOnly(opts, name, &db));
  2996. AssertExists(db, 0, 200);
  2997. delete db;
  2998. db = nullptr;
  2999. // Now try opening read-write and make sure it fails, for safety.
  3000. ASSERT_TRUE(DB::Open(opts, name, &db).IsIOError());
  3001. }
  3002. TEST_F(BackupEngineTest, ProgressCallbackDuringBackup) {
  3003. DestroyDBWithoutCheck(dbname_, options_);
  3004. OpenDBAndBackupEngine(true);
  3005. FillDB(db_.get(), 0, 100);
  3006. // First test exception handling
  3007. // Easily small enough for this small DB
  3008. engine_options_->callback_trigger_interval_size = 1000;
  3009. OpenBackupEngine();
  3010. ASSERT_TRUE(
  3011. backup_engine_->CreateNewBackup(db_.get(), true, []() { throw 42; })
  3012. .IsAborted());
  3013. ASSERT_TRUE(backup_engine_
  3014. ->CreateNewBackup(db_.get(), true,
  3015. []() { throw std::out_of_range("blah"); })
  3016. .IsAborted());
  3017. // Too big for this small DB
  3018. engine_options_->callback_trigger_interval_size = 100000;
  3019. OpenBackupEngine();
  3020. bool is_callback_invoked = false;
  3021. ASSERT_OK(backup_engine_->CreateNewBackup(
  3022. db_.get(), true,
  3023. [&is_callback_invoked]() { is_callback_invoked = true; }));
  3024. ASSERT_FALSE(is_callback_invoked);
  3025. CloseBackupEngine();
  3026. // Easily small enough for this small DB
  3027. engine_options_->callback_trigger_interval_size = 1000;
  3028. OpenBackupEngine();
  3029. ASSERT_OK(backup_engine_->CreateNewBackup(
  3030. db_.get(), true,
  3031. [&is_callback_invoked]() { is_callback_invoked = true; }));
  3032. ASSERT_TRUE(is_callback_invoked);
  3033. CloseDBAndBackupEngine();
  3034. DestroyDBWithoutCheck(dbname_, options_);
  3035. }
  3036. TEST_F(BackupEngineTest, GarbageCollectionBeforeBackup) {
  3037. DestroyDBWithoutCheck(dbname_, options_);
  3038. OpenDBAndBackupEngine(true);
  3039. ASSERT_OK(backup_chroot_env_->CreateDirIfMissing(backupdir_ + "/shared"));
  3040. std::string file_five = backupdir_ + "/shared/000009.sst";
  3041. std::string file_five_contents = "I'm not really a sst file";
  3042. // this depends on the fact that 00009.sst is the first file created by the DB
  3043. ASSERT_OK(file_manager_->WriteToFile(file_five, file_five_contents));
  3044. FillDB(db_.get(), 0, 100);
  3045. // backup overwrites file 000009.sst
  3046. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3047. std::string new_file_five_contents;
  3048. ASSERT_OK(ReadFileToString(backup_chroot_env_.get(), file_five,
  3049. &new_file_five_contents));
  3050. // file 000009.sst was overwritten
  3051. ASSERT_TRUE(new_file_five_contents != file_five_contents);
  3052. CloseDBAndBackupEngine();
  3053. AssertBackupConsistency(0, 0, 100);
  3054. }
  3055. // Test that we properly propagate Env failures
  3056. TEST_F(BackupEngineTest, EnvFailures) {
  3057. BackupEngine* backup_engine;
  3058. // get children failure
  3059. {
  3060. test_backup_fs_->SetGetChildrenFailure(true);
  3061. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *engine_options_,
  3062. &backup_engine));
  3063. test_backup_fs_->SetGetChildrenFailure(false);
  3064. }
  3065. // created dir failure
  3066. {
  3067. test_backup_fs_->SetCreateDirIfMissingFailure(true);
  3068. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *engine_options_,
  3069. &backup_engine));
  3070. test_backup_fs_->SetCreateDirIfMissingFailure(false);
  3071. }
  3072. // new directory failure
  3073. {
  3074. test_backup_fs_->SetNewDirectoryFailure(true);
  3075. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *engine_options_,
  3076. &backup_engine));
  3077. test_backup_fs_->SetNewDirectoryFailure(false);
  3078. }
  3079. // Read from meta-file failure
  3080. {
  3081. DestroyDBWithoutCheck(dbname_, options_);
  3082. OpenDBAndBackupEngine(true);
  3083. FillDB(db_.get(), 0, 100);
  3084. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3085. CloseDBAndBackupEngine();
  3086. test_backup_fs_->SetDummySequentialFile(true);
  3087. test_backup_fs_->SetDummySequentialFileFailReads(true);
  3088. engine_options_->destroy_old_data = false;
  3089. ASSERT_NOK(BackupEngine::Open(test_db_env_.get(), *engine_options_,
  3090. &backup_engine));
  3091. test_backup_fs_->SetDummySequentialFile(false);
  3092. test_backup_fs_->SetDummySequentialFileFailReads(false);
  3093. }
  3094. // no failure
  3095. {
  3096. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), *engine_options_,
  3097. &backup_engine));
  3098. delete backup_engine;
  3099. }
  3100. }
  3101. // Verify manifest can roll while a backup is being created with the old
  3102. // manifest.
  3103. TEST_F(BackupEngineTest, ChangeManifestDuringBackupCreation) {
  3104. DestroyDBWithoutCheck(dbname_, options_);
  3105. options_.max_manifest_file_size = 0; // always rollover manifest for file add
  3106. OpenDBAndBackupEngine(true);
  3107. FillDB(db_.get(), 0, 100, kAutoFlushOnly);
  3108. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency({
  3109. {"CheckpointImpl::CreateCheckpoint:SavedLiveFiles1",
  3110. "VersionSet::LogAndApply:WriteManifest"},
  3111. {"VersionSet::LogAndApply:WriteManifestDone",
  3112. "CheckpointImpl::CreateCheckpoint:SavedLiveFiles2"},
  3113. });
  3114. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  3115. ROCKSDB_NAMESPACE::port::Thread flush_thread{
  3116. [this]() { ASSERT_OK(db_->Flush(FlushOptions())); }};
  3117. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  3118. flush_thread.join();
  3119. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  3120. // The last manifest roll would've already been cleaned up by the full scan
  3121. // that happens when CreateNewBackup invokes EnableFileDeletions. We need to
  3122. // trigger another roll to verify non-full scan purges stale manifests.
  3123. DBImpl* db_impl = static_cast_with_check<DBImpl>(db_.get());
  3124. std::string prev_manifest_path =
  3125. DescriptorFileName(dbname_, db_impl->TEST_Current_Manifest_FileNo());
  3126. FillDB(db_.get(), 0, 100, kAutoFlushOnly);
  3127. ASSERT_OK(db_chroot_env_->FileExists(prev_manifest_path));
  3128. ASSERT_OK(db_->Flush(FlushOptions()));
  3129. // Even though manual flush completed above, the background thread may not
  3130. // have finished its cleanup work. `TEST_WaitForBackgroundWork()` will wait
  3131. // until all the background thread's work has completed, including cleanup.
  3132. ASSERT_OK(db_impl->TEST_WaitForBackgroundWork());
  3133. ASSERT_TRUE(db_chroot_env_->FileExists(prev_manifest_path).IsNotFound());
  3134. CloseDBAndBackupEngine();
  3135. DestroyDBWithoutCheck(dbname_, options_);
  3136. AssertBackupConsistency(0, 0, 100);
  3137. }
  3138. // see https://github.com/facebook/rocksdb/issues/921
  3139. TEST_F(BackupEngineTest, Issue921Test) {
  3140. BackupEngine* backup_engine;
  3141. engine_options_->share_table_files = false;
  3142. ASSERT_OK(
  3143. backup_chroot_env_->CreateDirIfMissing(engine_options_->backup_dir));
  3144. engine_options_->backup_dir += "/new_dir";
  3145. ASSERT_OK(BackupEngine::Open(backup_chroot_env_.get(), *engine_options_,
  3146. &backup_engine));
  3147. delete backup_engine;
  3148. }
  3149. TEST_F(BackupEngineTest, BackupWithMetadata) {
  3150. const int keys_iteration = 5000;
  3151. OpenDBAndBackupEngine(true);
  3152. // create five backups
  3153. for (int i = 0; i < 5; ++i) {
  3154. const std::string metadata = std::to_string(i);
  3155. FillDB(db_.get(), keys_iteration * i, keys_iteration * (i + 1));
  3156. // Here also test CreateNewBackupWithMetadata with CreateBackupOptions
  3157. // and outputting saved BackupID.
  3158. CreateBackupOptions opts;
  3159. opts.flush_before_backup = true;
  3160. BackupID new_id = 0;
  3161. ASSERT_OK(backup_engine_->CreateNewBackupWithMetadata(opts, db_.get(),
  3162. metadata, &new_id));
  3163. ASSERT_EQ(new_id, static_cast<BackupID>(i + 1));
  3164. }
  3165. CloseDBAndBackupEngine();
  3166. OpenDBAndBackupEngine();
  3167. { // Verify in bulk BackupInfo
  3168. std::vector<BackupInfo> backup_infos;
  3169. backup_engine_->GetBackupInfo(&backup_infos);
  3170. ASSERT_EQ(5, backup_infos.size());
  3171. for (int i = 0; i < 5; i++) {
  3172. ASSERT_EQ(std::to_string(i), backup_infos[i].app_metadata);
  3173. }
  3174. }
  3175. // Also verify in individual BackupInfo
  3176. for (int i = 0; i < 5; i++) {
  3177. BackupInfo backup_info;
  3178. ASSERT_OK(backup_engine_->GetBackupInfo(static_cast<BackupID>(i + 1),
  3179. &backup_info));
  3180. ASSERT_EQ(std::to_string(i), backup_info.app_metadata);
  3181. }
  3182. CloseDBAndBackupEngine();
  3183. DestroyDBWithoutCheck(dbname_, options_);
  3184. }
  3185. TEST_F(BackupEngineTest, BinaryMetadata) {
  3186. OpenDBAndBackupEngine(true);
  3187. std::string binaryMetadata = "abc\ndef";
  3188. binaryMetadata.push_back('\0');
  3189. binaryMetadata.append("ghi");
  3190. ASSERT_OK(
  3191. backup_engine_->CreateNewBackupWithMetadata(db_.get(), binaryMetadata));
  3192. CloseDBAndBackupEngine();
  3193. OpenDBAndBackupEngine();
  3194. std::vector<BackupInfo> backup_infos;
  3195. backup_engine_->GetBackupInfo(&backup_infos);
  3196. ASSERT_EQ(1, backup_infos.size());
  3197. ASSERT_EQ(binaryMetadata, backup_infos[0].app_metadata);
  3198. CloseDBAndBackupEngine();
  3199. DestroyDBWithoutCheck(dbname_, options_);
  3200. }
  3201. TEST_F(BackupEngineTest, MetadataTooLarge) {
  3202. OpenDBAndBackupEngine(true);
  3203. std::string largeMetadata(1024 * 1024 + 1, 0);
  3204. ASSERT_NOK(
  3205. backup_engine_->CreateNewBackupWithMetadata(db_.get(), largeMetadata));
  3206. CloseDBAndBackupEngine();
  3207. DestroyDBWithoutCheck(dbname_, options_);
  3208. }
  3209. TEST_F(BackupEngineTest, MetaSchemaVersion2_SizeCorruption) {
  3210. engine_options_->schema_version = 1;
  3211. OpenDBAndBackupEngine(/*destroy_old_data*/ true);
  3212. // Backup 1: no future schema, no sizes, with checksums
  3213. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  3214. CloseDBAndBackupEngine();
  3215. engine_options_->schema_version = 2;
  3216. OpenDBAndBackupEngine(/*destroy_old_data*/ false);
  3217. // Backup 2: no checksums, no sizes
  3218. TEST_BackupMetaSchemaOptions test_opts;
  3219. test_opts.crc32c_checksums = false;
  3220. test_opts.file_sizes = false;
  3221. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3222. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  3223. // Backup 3: no checksums, with sizes
  3224. test_opts.file_sizes = true;
  3225. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3226. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  3227. // Backup 4: with checksums and sizes
  3228. test_opts.crc32c_checksums = true;
  3229. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3230. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  3231. CloseDBAndBackupEngine();
  3232. // Corrupt all the CURRENT files with the wrong size
  3233. const std::string private_dir = backupdir_ + "/private";
  3234. for (int id = 1; id <= 3; ++id) {
  3235. ASSERT_OK(file_manager_->WriteToFile(
  3236. private_dir + "/" + std::to_string(id) + "/CURRENT", "x"));
  3237. }
  3238. // Except corrupt Backup 4 with same size CURRENT file
  3239. {
  3240. uint64_t size = 0;
  3241. ASSERT_OK(test_backup_env_->GetFileSize(private_dir + "/4/CURRENT", &size));
  3242. ASSERT_OK(file_manager_->WriteToFile(private_dir + "/4/CURRENT",
  3243. std::string(size, 'x')));
  3244. }
  3245. OpenBackupEngine();
  3246. // Only the one with sizes in metadata will be immediately detected
  3247. // as corrupt
  3248. std::vector<BackupID> corrupted;
  3249. backup_engine_->GetCorruptedBackups(&corrupted);
  3250. ASSERT_EQ(corrupted.size(), 1);
  3251. ASSERT_EQ(corrupted[0], 3);
  3252. // Size corruption detected on Restore with checksum
  3253. ASSERT_TRUE(backup_engine_->RestoreDBFromBackup(1 /*id*/, dbname_, dbname_)
  3254. .IsCorruption());
  3255. // Size corruption not detected without checksums nor sizes
  3256. ASSERT_OK(backup_engine_->RestoreDBFromBackup(2 /*id*/, dbname_, dbname_));
  3257. // Non-size corruption detected on Restore with checksum
  3258. ASSERT_TRUE(backup_engine_->RestoreDBFromBackup(4 /*id*/, dbname_, dbname_)
  3259. .IsCorruption());
  3260. CloseBackupEngine();
  3261. }
  3262. TEST_F(BackupEngineTest, MetaSchemaVersion2_NotSupported) {
  3263. engine_options_->schema_version = 2;
  3264. TEST_BackupMetaSchemaOptions test_opts;
  3265. std::string app_metadata = "abc\ndef";
  3266. OpenDBAndBackupEngine(true);
  3267. // Start with supported
  3268. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3269. ASSERT_OK(
  3270. backup_engine_->CreateNewBackupWithMetadata(db_.get(), app_metadata));
  3271. // Because we are injecting badness with a TEST API, the badness is only
  3272. // detected on attempt to restore.
  3273. // Not supported versions
  3274. test_opts.version = "3";
  3275. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3276. ASSERT_OK(
  3277. backup_engine_->CreateNewBackupWithMetadata(db_.get(), app_metadata));
  3278. test_opts.version = "23.45.67";
  3279. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3280. ASSERT_OK(
  3281. backup_engine_->CreateNewBackupWithMetadata(db_.get(), app_metadata));
  3282. test_opts.version = "2";
  3283. // Non-ignorable fields
  3284. test_opts.meta_fields["ni::blah"] = "123";
  3285. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3286. ASSERT_OK(
  3287. backup_engine_->CreateNewBackupWithMetadata(db_.get(), app_metadata));
  3288. test_opts.meta_fields.clear();
  3289. test_opts.file_fields["ni::123"] = "xyz";
  3290. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3291. ASSERT_OK(
  3292. backup_engine_->CreateNewBackupWithMetadata(db_.get(), app_metadata));
  3293. test_opts.file_fields.clear();
  3294. test_opts.footer_fields["ni::123"] = "xyz";
  3295. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3296. ASSERT_OK(
  3297. backup_engine_->CreateNewBackupWithMetadata(db_.get(), app_metadata));
  3298. test_opts.footer_fields.clear();
  3299. CloseDBAndBackupEngine();
  3300. OpenBackupEngine();
  3301. std::vector<BackupID> corrupted;
  3302. backup_engine_->GetCorruptedBackups(&corrupted);
  3303. ASSERT_EQ(corrupted.size(), 5);
  3304. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(dbname_, dbname_));
  3305. CloseBackupEngine();
  3306. }
  3307. TEST_F(BackupEngineTest, MetaSchemaVersion2_Restore) {
  3308. engine_options_->schema_version = 2;
  3309. TEST_BackupMetaSchemaOptions test_opts;
  3310. const int keys_iteration = 5000;
  3311. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  3312. FillDB(db_.get(), 0, keys_iteration);
  3313. // Start with minimum metadata to ensure it works without it being filled
  3314. // based on shared files also in other backups with the metadata.
  3315. test_opts.crc32c_checksums = false;
  3316. test_opts.file_sizes = false;
  3317. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3318. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3319. CloseDBAndBackupEngine();
  3320. AssertBackupConsistency(1 /* id */, 0, keys_iteration, keys_iteration * 2);
  3321. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  3322. kShareWithChecksum);
  3323. test_opts.file_sizes = true;
  3324. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3325. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3326. CloseDBAndBackupEngine();
  3327. for (int id = 1; id <= 2; ++id) {
  3328. AssertBackupConsistency(id, 0, keys_iteration, keys_iteration * 2);
  3329. }
  3330. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  3331. kShareWithChecksum);
  3332. test_opts.crc32c_checksums = true;
  3333. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3334. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3335. CloseDBAndBackupEngine();
  3336. for (int id = 1; id <= 3; ++id) {
  3337. AssertBackupConsistency(id, 0, keys_iteration, keys_iteration * 2);
  3338. }
  3339. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  3340. kShareWithChecksum);
  3341. // No TEST_EnableWriteFutureSchemaVersion2
  3342. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3343. CloseDBAndBackupEngine();
  3344. for (int id = 1; id <= 4; ++id) {
  3345. AssertBackupConsistency(id, 0, keys_iteration, keys_iteration * 2);
  3346. }
  3347. OpenDBAndBackupEngine(false /* destroy_old_data */, false,
  3348. kShareWithChecksum);
  3349. // Minor version updates should be forward-compatible
  3350. test_opts.version = "2.5.70";
  3351. test_opts.meta_fields["asdf.3456"] = "-42";
  3352. test_opts.meta_fields["__QRST"] = " 1 $ %%& ";
  3353. test_opts.file_fields["z94._"] = "^\\";
  3354. test_opts.file_fields["_7yyyyyyyyy"] = "111111111111";
  3355. test_opts.footer_fields["Qwzn.tz89"] = "ASDF!!@# ##=\t ";
  3356. test_opts.footer_fields["yes"] = "no!";
  3357. TEST_SetBackupMetaSchemaOptions(backup_engine_.get(), test_opts);
  3358. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3359. CloseDBAndBackupEngine();
  3360. for (int id = 1; id <= 5; ++id) {
  3361. AssertBackupConsistency(id, 0, keys_iteration, keys_iteration * 2);
  3362. }
  3363. }
  3364. TEST_F(BackupEngineTest, Concurrency) {
  3365. // Check that we can simultaneously:
  3366. // * Run several read operations in different threads on a single
  3367. // BackupEngine object, and
  3368. // * With another BackupEngine object on the same
  3369. // backup_dir, run the same read operations in another thread, and
  3370. // * With yet another BackupEngine object on the same
  3371. // backup_dir, create two new backups in parallel threads.
  3372. //
  3373. // Because of the challenges of integrating this into db_stress,
  3374. // this is a non-deterministic mini-stress test here instead.
  3375. // To check for a race condition in handling buffer size based on byte
  3376. // burst limit, we need a (generous) rate limiter
  3377. std::shared_ptr<RateLimiter> limiter{NewGenericRateLimiter(1000000000)};
  3378. engine_options_->backup_rate_limiter = limiter;
  3379. engine_options_->restore_rate_limiter = limiter;
  3380. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  3381. static constexpr int keys_iteration = 5000;
  3382. FillDB(db_.get(), 0, keys_iteration);
  3383. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  3384. FillDB(db_.get(), keys_iteration, 2 * keys_iteration);
  3385. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  3386. static constexpr int max_factor = 3;
  3387. FillDB(db_.get(), 2 * keys_iteration, max_factor * keys_iteration);
  3388. // will create another backup soon...
  3389. Options db_opts = options_;
  3390. db_opts.wal_dir = "";
  3391. db_opts.create_if_missing = false;
  3392. BackupEngineOptions be_opts = *engine_options_;
  3393. be_opts.destroy_old_data = false;
  3394. std::mt19937 rng{std::random_device()()};
  3395. std::array<std::thread, 4> read_threads;
  3396. std::array<std::thread, 4> restore_verify_threads;
  3397. for (uint32_t i = 0; i < read_threads.size(); ++i) {
  3398. uint32_t sleep_micros = rng() % 100000;
  3399. read_threads[i] = std::thread([this, i, sleep_micros, &db_opts, &be_opts,
  3400. &restore_verify_threads, &limiter] {
  3401. test_db_env_->SleepForMicroseconds(sleep_micros);
  3402. // Whether to also re-open the BackupEngine, potentially seeing
  3403. // additional backups
  3404. bool reopen = i == 3;
  3405. // Whether we are going to restore "latest"
  3406. bool latest = i > 1;
  3407. BackupEngine* my_be;
  3408. if (reopen) {
  3409. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), be_opts, &my_be));
  3410. } else {
  3411. my_be = backup_engine_.get();
  3412. }
  3413. // Verify metadata (we don't receive updates from concurrently
  3414. // creating a new backup)
  3415. std::vector<BackupInfo> infos;
  3416. my_be->GetBackupInfo(&infos);
  3417. const uint32_t count = static_cast<uint32_t>(infos.size());
  3418. infos.clear();
  3419. if (reopen) {
  3420. ASSERT_GE(count, 2U);
  3421. ASSERT_LE(count, 4U);
  3422. fprintf(stderr, "Reopen saw %u backups\n", count);
  3423. } else {
  3424. ASSERT_EQ(count, 2U);
  3425. }
  3426. std::vector<BackupID> ids;
  3427. my_be->GetCorruptedBackups(&ids);
  3428. ASSERT_EQ(ids.size(), 0U);
  3429. // (Eventually, see below) Restore one of the backups, or "latest"
  3430. std::string restore_db_dir = dbname_ + "/restore" + std::to_string(i);
  3431. DestroyDir(test_db_env_.get(), restore_db_dir).PermitUncheckedError();
  3432. BackupID to_restore;
  3433. if (latest) {
  3434. to_restore = count;
  3435. } else {
  3436. to_restore = i + 1;
  3437. }
  3438. // Open restored DB to verify its contents, but test atomic restore
  3439. // by doing it async and ensuring we either get OK or InvalidArgument
  3440. restore_verify_threads[i] =
  3441. std::thread([this, &db_opts, restore_db_dir, to_restore] {
  3442. DB* restored;
  3443. Status s;
  3444. for (;;) {
  3445. s = DB::Open(db_opts, restore_db_dir, &restored);
  3446. if (s.IsInvalidArgument()) {
  3447. // Restore hasn't finished
  3448. test_db_env_->SleepForMicroseconds(1000);
  3449. continue;
  3450. } else {
  3451. // We should only get InvalidArgument if restore is
  3452. // incomplete, or OK if complete
  3453. ASSERT_OK(s);
  3454. break;
  3455. }
  3456. }
  3457. int factor = std::min(static_cast<int>(to_restore), max_factor);
  3458. AssertExists(restored, 0, factor * keys_iteration);
  3459. AssertEmpty(restored, factor * keys_iteration,
  3460. (factor + 1) * keys_iteration);
  3461. delete restored;
  3462. });
  3463. // (Ok now) Restore one of the backups, or "latest"
  3464. if (latest) {
  3465. ASSERT_OK(
  3466. my_be->RestoreDBFromLatestBackup(restore_db_dir, restore_db_dir));
  3467. } else {
  3468. ASSERT_OK(my_be->VerifyBackup(to_restore, true));
  3469. ASSERT_OK(my_be->RestoreDBFromBackup(to_restore, restore_db_dir,
  3470. restore_db_dir));
  3471. }
  3472. // Test for race condition in reconfiguring limiter
  3473. // FIXME: this could set to a different value in all threads, except
  3474. // GenericRateLimiter::SetBytesPerSecond has a write-write race
  3475. // reported by TSAN
  3476. if (i == 0) {
  3477. limiter->SetBytesPerSecond(2000000000);
  3478. }
  3479. // Re-verify metadata (we don't receive updates from concurrently
  3480. // creating a new backup)
  3481. my_be->GetBackupInfo(&infos);
  3482. ASSERT_EQ(infos.size(), count);
  3483. my_be->GetCorruptedBackups(&ids);
  3484. ASSERT_EQ(ids.size(), 0);
  3485. // fprintf(stderr, "Finished read thread\n");
  3486. if (reopen) {
  3487. delete my_be;
  3488. }
  3489. });
  3490. }
  3491. BackupEngine* alt_be;
  3492. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), be_opts, &alt_be));
  3493. std::array<std::thread, 2> append_threads;
  3494. for (unsigned i = 0; i < append_threads.size(); ++i) {
  3495. uint32_t sleep_micros = rng() % 100000;
  3496. append_threads[i] = std::thread([this, sleep_micros, alt_be] {
  3497. test_db_env_->SleepForMicroseconds(sleep_micros);
  3498. // WART: CreateNewBackup doesn't tell you the BackupID it just created,
  3499. // which is ugly for multithreaded setting.
  3500. // TODO: add delete backup also when that is added
  3501. ASSERT_OK(alt_be->CreateNewBackup(db_.get()));
  3502. // fprintf(stderr, "Finished append thread\n");
  3503. });
  3504. }
  3505. for (auto& t : append_threads) {
  3506. t.join();
  3507. }
  3508. // Verify metadata
  3509. std::vector<BackupInfo> infos;
  3510. alt_be->GetBackupInfo(&infos);
  3511. ASSERT_EQ(infos.size(), 2 + append_threads.size());
  3512. for (auto& t : read_threads) {
  3513. t.join();
  3514. }
  3515. delete alt_be;
  3516. for (auto& t : restore_verify_threads) {
  3517. t.join();
  3518. }
  3519. CloseDBAndBackupEngine();
  3520. }
  3521. TEST_F(BackupEngineTest, LimitBackupsOpened) {
  3522. // Verify the specified max backups are opened, including skipping over
  3523. // corrupted backups.
  3524. //
  3525. // Setup:
  3526. // - backups 1, 2, and 4 are valid
  3527. // - backup 3 is corrupt
  3528. // - max_valid_backups_to_open == 2
  3529. //
  3530. // Expectation: the engine opens backups 4 and 2 since those are latest two
  3531. // non-corrupt backups.
  3532. const int kNumKeys = 5000;
  3533. OpenDBAndBackupEngine(true);
  3534. for (int i = 1; i <= 4; ++i) {
  3535. FillDB(db_.get(), kNumKeys * i, kNumKeys * (i + 1));
  3536. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3537. if (i == 3) {
  3538. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/3", 3));
  3539. }
  3540. }
  3541. CloseDBAndBackupEngine();
  3542. engine_options_->max_valid_backups_to_open = 2;
  3543. engine_options_->destroy_old_data = false;
  3544. BackupEngineReadOnly* read_only_backup_engine;
  3545. ASSERT_OK(BackupEngineReadOnly::Open(
  3546. backup_chroot_env_.get(), *engine_options_, &read_only_backup_engine));
  3547. std::vector<BackupInfo> backup_infos;
  3548. read_only_backup_engine->GetBackupInfo(&backup_infos);
  3549. ASSERT_EQ(2, backup_infos.size());
  3550. ASSERT_EQ(2, backup_infos[0].backup_id);
  3551. ASSERT_EQ(4, backup_infos[1].backup_id);
  3552. delete read_only_backup_engine;
  3553. }
  3554. TEST_F(BackupEngineTest, IgnoreLimitBackupsOpenedWhenNotReadOnly) {
  3555. // Verify the specified max_valid_backups_to_open is ignored if the engine
  3556. // is not read-only.
  3557. //
  3558. // Setup:
  3559. // - backups 1, 2, and 4 are valid
  3560. // - backup 3 is corrupt
  3561. // - max_valid_backups_to_open == 2
  3562. //
  3563. // Expectation: the engine opens backups 4, 2, and 1 since those are latest
  3564. // non-corrupt backups, by ignoring max_valid_backups_to_open == 2.
  3565. const int kNumKeys = 5000;
  3566. OpenDBAndBackupEngine(true);
  3567. for (int i = 1; i <= 4; ++i) {
  3568. FillDB(db_.get(), kNumKeys * i, kNumKeys * (i + 1));
  3569. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3570. if (i == 3) {
  3571. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/3", 3));
  3572. }
  3573. }
  3574. CloseDBAndBackupEngine();
  3575. engine_options_->max_valid_backups_to_open = 2;
  3576. OpenDBAndBackupEngine();
  3577. std::vector<BackupInfo> backup_infos;
  3578. backup_engine_->GetBackupInfo(&backup_infos);
  3579. ASSERT_EQ(3, backup_infos.size());
  3580. ASSERT_EQ(1, backup_infos[0].backup_id);
  3581. ASSERT_EQ(2, backup_infos[1].backup_id);
  3582. ASSERT_EQ(4, backup_infos[2].backup_id);
  3583. CloseDBAndBackupEngine();
  3584. DestroyDBWithoutCheck(dbname_, options_);
  3585. }
  3586. TEST_F(BackupEngineTest, CreateWhenLatestBackupCorrupted) {
  3587. // we should pick an ID greater than corrupted backups' IDs so creation can
  3588. // succeed even when latest backup is corrupted.
  3589. const int kNumKeys = 5000;
  3590. OpenDBAndBackupEngine(true /* destroy_old_data */);
  3591. BackupInfo backup_info;
  3592. ASSERT_TRUE(backup_engine_->GetLatestBackupInfo(&backup_info).IsNotFound());
  3593. FillDB(db_.get(), 0 /* from */, kNumKeys);
  3594. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  3595. true /* flush_before_backup */));
  3596. ASSERT_OK(file_manager_->CorruptFile(backupdir_ + "/meta/1",
  3597. 3 /* bytes_to_corrupt */));
  3598. CloseDBAndBackupEngine();
  3599. OpenDBAndBackupEngine();
  3600. ASSERT_TRUE(backup_engine_->GetLatestBackupInfo(&backup_info).IsNotFound());
  3601. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  3602. true /* flush_before_backup */));
  3603. ASSERT_TRUE(backup_engine_->GetLatestBackupInfo(&backup_info).ok());
  3604. ASSERT_EQ(2, backup_info.backup_id);
  3605. std::vector<BackupInfo> backup_infos;
  3606. backup_engine_->GetBackupInfo(&backup_infos);
  3607. ASSERT_EQ(1, backup_infos.size());
  3608. ASSERT_EQ(2, backup_infos[0].backup_id);
  3609. // Verify individual GetBackupInfo by ID
  3610. ASSERT_TRUE(backup_engine_->GetBackupInfo(0U, &backup_info).IsNotFound());
  3611. ASSERT_TRUE(backup_engine_->GetBackupInfo(1U, &backup_info).IsCorruption());
  3612. ASSERT_TRUE(backup_engine_->GetBackupInfo(2U, &backup_info).ok());
  3613. ASSERT_TRUE(backup_engine_->GetBackupInfo(3U, &backup_info).IsNotFound());
  3614. ASSERT_TRUE(
  3615. backup_engine_->GetBackupInfo(999999U, &backup_info).IsNotFound());
  3616. }
  3617. TEST_F(BackupEngineTest, WriteOnlyEngineNoSharedFileDeletion) {
  3618. // Verifies a write-only BackupEngine does not delete files belonging to valid
  3619. // backups when GarbageCollect, PurgeOldBackups, or DeleteBackup are called.
  3620. const int kNumKeys = 5000;
  3621. for (int i = 0; i < 3; ++i) {
  3622. OpenDBAndBackupEngine(i == 0 /* destroy_old_data */);
  3623. FillDB(db_.get(), i * kNumKeys, (i + 1) * kNumKeys);
  3624. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), true));
  3625. CloseDBAndBackupEngine();
  3626. engine_options_->max_valid_backups_to_open = 0;
  3627. OpenDBAndBackupEngine();
  3628. switch (i) {
  3629. case 0:
  3630. ASSERT_OK(backup_engine_->GarbageCollect());
  3631. break;
  3632. case 1:
  3633. ASSERT_OK(backup_engine_->PurgeOldBackups(1 /* num_backups_to_keep */));
  3634. break;
  3635. case 2:
  3636. ASSERT_OK(backup_engine_->DeleteBackup(2 /* backup_id */));
  3637. break;
  3638. default:
  3639. assert(false);
  3640. }
  3641. CloseDBAndBackupEngine();
  3642. engine_options_->max_valid_backups_to_open =
  3643. std::numeric_limits<int32_t>::max();
  3644. AssertBackupConsistency(i + 1, 0, (i + 1) * kNumKeys);
  3645. }
  3646. }
  3647. TEST_P(BackupEngineTestWithParam, BackupUsingDirectIO) {
  3648. // Tests direct I/O on the backup engine's reads and writes on the DB env and
  3649. // backup env
  3650. // We use ChrootEnv underneath so the below line checks for direct I/O support
  3651. // in the chroot directory, not the true filesystem root.
  3652. if (!test::IsDirectIOSupported(test_db_env_.get(), "/")) {
  3653. ROCKSDB_GTEST_SKIP("Test requires Direct I/O Support");
  3654. return;
  3655. }
  3656. const int kNumKeysPerBackup = 100;
  3657. const int kNumBackups = 3;
  3658. options_.use_direct_reads = true;
  3659. OpenDBAndBackupEngine(true /* destroy_old_data */);
  3660. for (int i = 0; i < kNumBackups; ++i) {
  3661. FillDB(db_.get(), i * kNumKeysPerBackup /* from */,
  3662. (i + 1) * kNumKeysPerBackup /* to */);
  3663. // Clear the file open counters and then do a bunch of backup engine ops.
  3664. // For all ops, files should be opened in direct mode.
  3665. test_backup_fs_->ClearFileOpenCounters();
  3666. test_db_fs_->ClearFileOpenCounters();
  3667. CloseBackupEngine();
  3668. OpenBackupEngine();
  3669. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  3670. false /* flush_before_backup */));
  3671. ASSERT_OK(backup_engine_->VerifyBackup(i + 1));
  3672. CloseBackupEngine();
  3673. OpenBackupEngine();
  3674. std::vector<BackupInfo> backup_infos;
  3675. backup_engine_->GetBackupInfo(&backup_infos);
  3676. ASSERT_EQ(static_cast<size_t>(i + 1), backup_infos.size());
  3677. // Verify backup engine always opened files with direct I/O
  3678. ASSERT_EQ(0, test_db_fs_->num_writers());
  3679. ASSERT_GE(test_db_fs_->num_direct_rand_readers(), 0);
  3680. ASSERT_GT(test_db_fs_->num_direct_seq_readers(), 0);
  3681. // Currently the DB doesn't support reading WALs or manifest with direct
  3682. // I/O, so subtract two.
  3683. ASSERT_EQ(test_db_fs_->num_seq_readers() - 2,
  3684. test_db_fs_->num_direct_seq_readers());
  3685. ASSERT_EQ(test_db_fs_->num_rand_readers(),
  3686. test_db_fs_->num_direct_rand_readers());
  3687. }
  3688. CloseDBAndBackupEngine();
  3689. for (int i = 0; i < kNumBackups; ++i) {
  3690. AssertBackupConsistency(i + 1 /* backup_id */,
  3691. i * kNumKeysPerBackup /* start_exist */,
  3692. (i + 1) * kNumKeysPerBackup /* end_exist */,
  3693. (i + 2) * kNumKeysPerBackup /* end */);
  3694. }
  3695. }
  3696. TEST_F(BackupEngineTest, BackgroundThreadCpuPriority) {
  3697. std::atomic<CpuPriority> priority(CpuPriority::kNormal);
  3698. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  3699. "BackupEngineImpl::Initialize:SetCpuPriority", [&](void* new_priority) {
  3700. priority.store(*static_cast<CpuPriority*>(new_priority));
  3701. });
  3702. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  3703. // 1 thread is easier to test, otherwise, we may not be sure which thread
  3704. // actually does the work during CreateNewBackup.
  3705. engine_options_->max_background_operations = 1;
  3706. OpenDBAndBackupEngine(true);
  3707. {
  3708. FillDB(db_.get(), 0, 100);
  3709. // by default, cpu priority is not changed.
  3710. CreateBackupOptions options;
  3711. ASSERT_OK(backup_engine_->CreateNewBackup(options, db_.get()));
  3712. ASSERT_EQ(priority, CpuPriority::kNormal);
  3713. }
  3714. {
  3715. FillDB(db_.get(), 101, 200);
  3716. // decrease cpu priority from normal to low.
  3717. CreateBackupOptions options;
  3718. options.decrease_background_thread_cpu_priority = true;
  3719. options.background_thread_cpu_priority = CpuPriority::kLow;
  3720. ASSERT_OK(backup_engine_->CreateNewBackup(options, db_.get()));
  3721. ASSERT_EQ(priority, CpuPriority::kLow);
  3722. }
  3723. {
  3724. FillDB(db_.get(), 201, 300);
  3725. // try to upgrade cpu priority back to normal,
  3726. // the priority should still low.
  3727. CreateBackupOptions options;
  3728. options.decrease_background_thread_cpu_priority = true;
  3729. options.background_thread_cpu_priority = CpuPriority::kNormal;
  3730. ASSERT_OK(backup_engine_->CreateNewBackup(options, db_.get()));
  3731. ASSERT_EQ(priority, CpuPriority::kLow);
  3732. }
  3733. {
  3734. FillDB(db_.get(), 301, 400);
  3735. // decrease cpu priority from low to idle.
  3736. CreateBackupOptions options;
  3737. options.decrease_background_thread_cpu_priority = true;
  3738. options.background_thread_cpu_priority = CpuPriority::kIdle;
  3739. ASSERT_OK(backup_engine_->CreateNewBackup(options, db_.get()));
  3740. ASSERT_EQ(priority, CpuPriority::kIdle);
  3741. }
  3742. {
  3743. FillDB(db_.get(), 301, 400);
  3744. // reset priority to later verify that it's not updated by SetCpuPriority.
  3745. priority = CpuPriority::kNormal;
  3746. // setting the same cpu priority won't call SetCpuPriority.
  3747. CreateBackupOptions options;
  3748. options.decrease_background_thread_cpu_priority = true;
  3749. options.background_thread_cpu_priority = CpuPriority::kIdle;
  3750. // Also check output backup_id with CreateNewBackup
  3751. BackupID new_id = 0;
  3752. ASSERT_OK(backup_engine_->CreateNewBackup(options, db_.get(), &new_id));
  3753. ASSERT_EQ(new_id, 5U);
  3754. ASSERT_EQ(priority, CpuPriority::kNormal);
  3755. }
  3756. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  3757. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  3758. CloseDBAndBackupEngine();
  3759. DestroyDBWithoutCheck(dbname_, options_);
  3760. }
  3761. // Populates `*total_size` with the size of all files under `backup_dir`.
  3762. // We don't go through `BackupEngine` currently because it's hard to figure out
  3763. // the metadata file size.
  3764. Status GetSizeOfBackupFiles(FileSystem* backup_fs,
  3765. const std::string& backup_dir, size_t* total_size) {
  3766. *total_size = 0;
  3767. std::vector<std::string> dir_stack = {backup_dir};
  3768. Status s;
  3769. while (s.ok() && !dir_stack.empty()) {
  3770. std::string dir = std::move(dir_stack.back());
  3771. dir_stack.pop_back();
  3772. std::vector<std::string> children;
  3773. s = backup_fs->GetChildren(dir, IOOptions(), &children, nullptr /* dbg */);
  3774. for (size_t i = 0; s.ok() && i < children.size(); ++i) {
  3775. std::string path = dir + "/" + children[i];
  3776. bool is_dir;
  3777. s = backup_fs->IsDirectory(path, IOOptions(), &is_dir, nullptr /* dbg */);
  3778. uint64_t file_size = 0;
  3779. if (s.ok()) {
  3780. if (is_dir) {
  3781. dir_stack.emplace_back(std::move(path));
  3782. } else {
  3783. s = backup_fs->GetFileSize(path, IOOptions(), &file_size,
  3784. nullptr /* dbg */);
  3785. }
  3786. }
  3787. if (s.ok()) {
  3788. *total_size += file_size;
  3789. }
  3790. }
  3791. }
  3792. return s;
  3793. }
  3794. TEST_F(BackupEngineTest, IOStats) {
  3795. // Tests the `BACKUP_READ_BYTES` and `BACKUP_WRITE_BYTES` ticker stats have
  3796. // the expected values according to the files in the backups.
  3797. // These ticker stats are expected to be populated regardless of `PerfLevel`
  3798. // in user thread
  3799. SetPerfLevel(kDisable);
  3800. options_.statistics = CreateDBStatistics();
  3801. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  3802. kShareWithChecksum);
  3803. FillDB(db_.get(), 0 /* from */, 100 /* to */, kFlushMost);
  3804. ASSERT_EQ(0, options_.statistics->getTickerCount(BACKUP_READ_BYTES));
  3805. ASSERT_EQ(0, options_.statistics->getTickerCount(BACKUP_WRITE_BYTES));
  3806. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  3807. false /* flush_before_backup */));
  3808. size_t orig_backup_files_size;
  3809. ASSERT_OK(GetSizeOfBackupFiles(test_backup_env_->GetFileSystem().get(),
  3810. backupdir_, &orig_backup_files_size));
  3811. size_t expected_bytes_written = orig_backup_files_size;
  3812. ASSERT_EQ(expected_bytes_written,
  3813. options_.statistics->getTickerCount(BACKUP_WRITE_BYTES));
  3814. // Bytes read is more difficult to pin down since there are reads for many
  3815. // purposes other than creating file, like `GetSortedWalFiles()` to find first
  3816. // sequence number, or `CreateNewBackup()` thread to find SST file session ID.
  3817. // So we loosely require there are at least as many reads as needed for
  3818. // copying, but not as many as twice that.
  3819. ASSERT_GE(options_.statistics->getTickerCount(BACKUP_READ_BYTES),
  3820. expected_bytes_written);
  3821. ASSERT_LT(expected_bytes_written,
  3822. 2 * options_.statistics->getTickerCount(BACKUP_READ_BYTES));
  3823. FillDB(db_.get(), 100 /* from */, 200 /* to */, kFlushMost);
  3824. ASSERT_OK(options_.statistics->Reset());
  3825. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(),
  3826. false /* flush_before_backup */));
  3827. size_t final_backup_files_size;
  3828. ASSERT_OK(GetSizeOfBackupFiles(test_backup_env_->GetFileSystem().get(),
  3829. backupdir_, &final_backup_files_size));
  3830. expected_bytes_written = final_backup_files_size - orig_backup_files_size;
  3831. ASSERT_EQ(expected_bytes_written,
  3832. options_.statistics->getTickerCount(BACKUP_WRITE_BYTES));
  3833. // See above for why these bounds were chosen.
  3834. ASSERT_GE(options_.statistics->getTickerCount(BACKUP_READ_BYTES),
  3835. expected_bytes_written);
  3836. ASSERT_LT(expected_bytes_written,
  3837. 2 * options_.statistics->getTickerCount(BACKUP_READ_BYTES));
  3838. }
  3839. TEST_F(BackupEngineTest, FileTemperatures) {
  3840. CloseDBAndBackupEngine();
  3841. // Required for recording+restoring temperatures
  3842. engine_options_->schema_version = 2;
  3843. // More file IO instrumentation
  3844. auto my_db_fs = std::make_shared<FileTemperatureTestFS>(db_chroot_fs_);
  3845. test_db_fs_ = std::make_shared<TestFs>(my_db_fs);
  3846. SetEnvsFromFileSystems();
  3847. // Use temperatures
  3848. options_.last_level_temperature = Temperature::kWarm;
  3849. options_.level0_file_num_compaction_trigger = 2;
  3850. // set dynamic_level to true so the compaction would compact the data to the
  3851. // last level directly which will have the last_level_temperature
  3852. options_.level_compaction_dynamic_level_bytes = true;
  3853. OpenDBAndBackupEngine(true /* destroy_old_data */, false /* dummy */,
  3854. kShareWithChecksum);
  3855. // generate a bottommost file (combined from 2) and a non-bottommost file
  3856. DBImpl* dbi = static_cast_with_check<DBImpl>(db_.get());
  3857. ASSERT_OK(db_->Put(WriteOptions(), "a", "val"));
  3858. ASSERT_OK(db_->Put(WriteOptions(), "c", "val"));
  3859. ASSERT_OK(db_->Flush(FlushOptions()));
  3860. ASSERT_OK(db_->Put(WriteOptions(), "b", "val"));
  3861. ASSERT_OK(db_->Put(WriteOptions(), "d", "val"));
  3862. ASSERT_OK(db_->Flush(FlushOptions()));
  3863. ASSERT_OK(dbi->TEST_WaitForCompact());
  3864. ASSERT_OK(db_->Put(WriteOptions(), "e", "val"));
  3865. ASSERT_OK(db_->Flush(FlushOptions()));
  3866. // Get temperatures from manifest
  3867. std::map<uint64_t, Temperature> manifest_temps;
  3868. std::map<Temperature, int> manifest_temp_counts;
  3869. {
  3870. std::vector<LiveFileStorageInfo> infos;
  3871. ASSERT_OK(
  3872. db_->GetLiveFilesStorageInfo(LiveFilesStorageInfoOptions(), &infos));
  3873. for (const auto& info : infos) {
  3874. if (info.file_type == kTableFile) {
  3875. manifest_temps.emplace(info.file_number, info.temperature);
  3876. manifest_temp_counts[info.temperature]++;
  3877. }
  3878. }
  3879. }
  3880. // Verify expected manifest temperatures
  3881. ASSERT_EQ(manifest_temp_counts.size(), 2);
  3882. ASSERT_EQ(manifest_temp_counts[Temperature::kWarm], 1);
  3883. ASSERT_EQ(manifest_temp_counts[Temperature::kUnknown], 1);
  3884. // Verify manifest temperatures match FS temperatures
  3885. std::map<uint64_t, Temperature> current_temps;
  3886. my_db_fs->CopyCurrentSstFileTemperatures(&current_temps);
  3887. for (const auto& manifest_temp : manifest_temps) {
  3888. ASSERT_EQ(current_temps[manifest_temp.first], manifest_temp.second);
  3889. }
  3890. // Try a few different things
  3891. for (int i = 1; i <= 5; ++i) {
  3892. // Expected temperatures after restore are based on manifest temperatures
  3893. std::map<uint64_t, Temperature> expected_temps = manifest_temps;
  3894. if (i >= 2) {
  3895. // For iterations 2 & 3, override current temperature of one file
  3896. // and vary which temperature is authoritative (current or manifest).
  3897. // For iterations 4 & 5, override current temperature of both files
  3898. // but make sure an current temperate always takes precedence over
  3899. // unknown regardless of current_temperatures_override_manifest setting.
  3900. bool use_current = ((i % 2) == 1);
  3901. engine_options_->current_temperatures_override_manifest = use_current;
  3902. CloseBackupEngine();
  3903. OpenBackupEngine();
  3904. for (const auto& manifest_temp : manifest_temps) {
  3905. if (i <= 3) {
  3906. if (manifest_temp.second == Temperature::kWarm) {
  3907. my_db_fs->OverrideSstFileTemperature(manifest_temp.first,
  3908. Temperature::kCold);
  3909. if (use_current) {
  3910. expected_temps[manifest_temp.first] = Temperature::kCold;
  3911. }
  3912. }
  3913. } else {
  3914. assert(i <= 5);
  3915. if (manifest_temp.second == Temperature::kWarm) {
  3916. my_db_fs->OverrideSstFileTemperature(manifest_temp.first,
  3917. Temperature::kUnknown);
  3918. } else {
  3919. ASSERT_EQ(manifest_temp.second, Temperature::kUnknown);
  3920. my_db_fs->OverrideSstFileTemperature(manifest_temp.first,
  3921. Temperature::kHot);
  3922. // regardless of use_current
  3923. expected_temps[manifest_temp.first] = Temperature::kHot;
  3924. }
  3925. }
  3926. }
  3927. }
  3928. // Sample requested temperatures in opening files for backup
  3929. my_db_fs->PopRequestedSstFileTemperatures();
  3930. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get()));
  3931. // Verify requested temperatures against manifest temperatures (before
  3932. // retry with kUnknown if needed, and before backup finds out current
  3933. // temperatures in FileSystem)
  3934. std::vector<std::pair<uint64_t, Temperature>> requested_temps;
  3935. my_db_fs->PopRequestedSstFileTemperatures(&requested_temps);
  3936. std::set<uint64_t> distinct_requests;
  3937. for (const auto& requested_temp : requested_temps) {
  3938. // Matching manifest temperatures, except allow retry request with
  3939. // kUnknown
  3940. auto manifest_temp = manifest_temps.at(requested_temp.first);
  3941. if (manifest_temp == Temperature::kUnknown ||
  3942. requested_temp.second != Temperature::kUnknown) {
  3943. ASSERT_EQ(manifest_temp, requested_temp.second);
  3944. }
  3945. distinct_requests.insert(requested_temp.first);
  3946. }
  3947. // Two distinct requests
  3948. ASSERT_EQ(distinct_requests.size(), 2);
  3949. // Verify against backup info file details API
  3950. BackupInfo info;
  3951. ASSERT_OK(backup_engine_->GetLatestBackupInfo(
  3952. &info, /*include_file_details*/ true));
  3953. ASSERT_GT(info.file_details.size(), 2);
  3954. for (auto& e : info.file_details) {
  3955. EXPECT_EQ(expected_temps[e.file_number], e.temperature);
  3956. }
  3957. // Restore backup to another virtual (tiered) dir
  3958. const std::string restore_dir = "/restore" + std::to_string(i);
  3959. ASSERT_OK(backup_engine_->RestoreDBFromLatestBackup(
  3960. RestoreOptions(), restore_dir, restore_dir));
  3961. // Verify restored FS temperatures match expectation
  3962. // (FileTemperatureTestFS doesn't distinguish directories when reporting
  3963. // current temperatures, just whatever SST was written or overridden last
  3964. // with that file number.)
  3965. my_db_fs->CopyCurrentSstFileTemperatures(&current_temps);
  3966. for (const auto& expected_temp : expected_temps) {
  3967. ASSERT_EQ(current_temps[expected_temp.first], expected_temp.second);
  3968. }
  3969. // Delete backup to force next backup to copy files
  3970. ASSERT_OK(backup_engine_->PurgeOldBackups(0));
  3971. }
  3972. }
  3973. TEST_F(BackupEngineTest, ExcludeFiles) {
  3974. // Required for excluding files
  3975. engine_options_->schema_version = 2;
  3976. // Need a sufficent set of file numbers
  3977. options_.level0_file_num_compaction_trigger = 100;
  3978. for (const auto& restore_mode :
  3979. {RestoreOptions::Mode::kPurgeAllFiles,
  3980. RestoreOptions::Mode::kKeepLatestDbSessionIdFiles,
  3981. RestoreOptions::Mode::kVerifyChecksum}) {
  3982. OpenDBAndBackupEngine(true, false, kShareWithChecksum);
  3983. // Need a sufficent set of file numbers
  3984. const int keys_iteration = 5000;
  3985. FillDB(db_.get(), 0, keys_iteration / 3);
  3986. FillDB(db_.get(), keys_iteration / 3, keys_iteration * 2 / 3);
  3987. FillDB(db_.get(), keys_iteration * 2 / 3, keys_iteration);
  3988. CloseAndReopenDB();
  3989. BackupEngine* alt_backup_engine;
  3990. BackupEngineOptions alt_engine_options{*engine_options_};
  3991. // Use an alternate Env to test that support
  3992. std::string backup_alt_chroot = test::PerThreadDBPath("db_alt_backups");
  3993. EXPECT_OK(Env::Default()->CreateDirIfMissing(backup_alt_chroot));
  3994. alt_engine_options.backup_dir = "/altbk";
  3995. std::shared_ptr<FileSystem> alt_fs{
  3996. NewChrootFileSystem(FileSystem::Default(), backup_alt_chroot)};
  3997. std::unique_ptr<Env> alt_env{
  3998. new CompositeEnvWrapper(Env::Default(), alt_fs)};
  3999. alt_engine_options.backup_env = alt_env.get();
  4000. ASSERT_OK(BackupEngine::Open(test_db_env_.get(), alt_engine_options,
  4001. &alt_backup_engine));
  4002. // Ensure each backup is same set of files
  4003. db_.reset();
  4004. DB* db = nullptr;
  4005. ASSERT_OK(DB::OpenForReadOnly(options_, dbname_, &db));
  4006. // A callback that throws should cleanly fail the backup creation.
  4007. // Do this early to ensure later operations still work.
  4008. CreateBackupOptions cbo;
  4009. cbo.exclude_files_callback = [](MaybeExcludeBackupFile* /*files_begin*/,
  4010. MaybeExcludeBackupFile* /*files_end*/) {
  4011. throw 42;
  4012. };
  4013. ASSERT_TRUE(backup_engine_->CreateNewBackup(cbo, db).IsAborted());
  4014. cbo.exclude_files_callback = [](MaybeExcludeBackupFile* /*files_begin*/,
  4015. MaybeExcludeBackupFile* /*files_end*/) {
  4016. throw std::out_of_range("blah");
  4017. };
  4018. ASSERT_TRUE(backup_engine_->CreateNewBackup(cbo, db).IsAborted());
  4019. // Include files only in given bucket, based on modulus and remainder
  4020. constexpr int modulus = 4;
  4021. int remainder = 0;
  4022. cbo.exclude_files_callback = [&remainder](
  4023. MaybeExcludeBackupFile* files_begin,
  4024. MaybeExcludeBackupFile* files_end) {
  4025. for (auto* f = files_begin; f != files_end; ++f) {
  4026. std::string s = StringSplit(f->info.relative_file, '/').back();
  4027. s = s.substr(0, s.find('_'));
  4028. int64_t num = std::strtoll(s.c_str(), nullptr, /*base*/ 10);
  4029. // Exclude if not a match
  4030. f->exclude_decision = (num % modulus) != remainder;
  4031. }
  4032. };
  4033. BackupID first_id{};
  4034. BackupID last_alt_id{};
  4035. remainder = 0;
  4036. ASSERT_OK(backup_engine_->CreateNewBackup(cbo, db, &first_id));
  4037. AssertBackupInfoConsistency(/*allow excluded*/ true);
  4038. remainder = 1;
  4039. ASSERT_OK(alt_backup_engine->CreateNewBackup(cbo, db));
  4040. AssertBackupInfoConsistency(/*allow excluded*/ true);
  4041. remainder = 2;
  4042. ASSERT_OK(backup_engine_->CreateNewBackup(cbo, db));
  4043. AssertBackupInfoConsistency(/*allow excluded*/ true);
  4044. remainder = 3;
  4045. ASSERT_OK(alt_backup_engine->CreateNewBackup(cbo, db, &last_alt_id));
  4046. AssertBackupInfoConsistency(/*allow excluded*/ true);
  4047. // Close DB
  4048. ASSERT_OK(db->Close());
  4049. delete db;
  4050. db = nullptr;
  4051. auto backup_engine = backup_engine_.get();
  4052. for (auto be_pair : {std::make_pair(backup_engine, alt_backup_engine),
  4053. std::make_pair(alt_backup_engine, backup_engine)}) {
  4054. ASSERT_OK(DestroyDB(dbname_, options_));
  4055. RestoreOptions ro(false /* _keep_log_files */, restore_mode);
  4056. // Fails without alternate dir
  4057. ASSERT_TRUE(be_pair.first->RestoreDBFromLatestBackup(dbname_, dbname_, ro)
  4058. .IsInvalidArgument());
  4059. ASSERT_OK(DestroyDB(dbname_, options_));
  4060. // Works with alternate dir
  4061. ro.alternate_dirs.push_front(be_pair.second);
  4062. ASSERT_OK(be_pair.first->RestoreDBFromLatestBackup(dbname_, dbname_, ro));
  4063. // Check DB contents
  4064. db = OpenDB();
  4065. AssertExists(db, 0, keys_iteration);
  4066. delete db;
  4067. }
  4068. // Should still work after close and re-open
  4069. CloseBackupEngine();
  4070. OpenBackupEngine();
  4071. backup_engine = backup_engine_.get();
  4072. for (auto be_pair : {std::make_pair(backup_engine, alt_backup_engine),
  4073. std::make_pair(alt_backup_engine, backup_engine)}) {
  4074. ASSERT_OK(DestroyDB(dbname_, options_));
  4075. RestoreOptions ro(false /* _keep_log_files */, restore_mode);
  4076. ro.alternate_dirs.push_front(be_pair.second);
  4077. ASSERT_OK(be_pair.first->RestoreDBFromLatestBackup(dbname_, dbname_, ro));
  4078. }
  4079. // Deletion semantics are tricky when within a single backup dir one backup
  4080. // includes a file and the other backup excluded the file. The excluded one
  4081. // does not have a persistent record of metadata like file checksum, etc.
  4082. // Although it would be possible to amend the backup with the excluded file,
  4083. // that is not currently supported (unless you open the backup as read-only
  4084. // DB and take another backup of it). The "excluded" reference to the file
  4085. // is like a weak reference: it doesn't prevent the file from being deleted
  4086. // if all the backups with "included" references to it are deleted.
  4087. CloseBackupEngine();
  4088. OpenBackupEngine();
  4089. AssertBackupInfoConsistency(/*allow excluded*/ true);
  4090. ASSERT_OK(backup_engine_->DeleteBackup(first_id));
  4091. ASSERT_OK(alt_backup_engine->DeleteBackup(last_alt_id));
  4092. // Includes check for any leaked backup files
  4093. AssertBackupInfoConsistency(/*allow excluded*/ true);
  4094. // Excluded file(s) deleted, unable to restore
  4095. backup_engine = backup_engine_.get();
  4096. for (auto be_pair : {std::make_pair(backup_engine, alt_backup_engine),
  4097. std::make_pair(alt_backup_engine, backup_engine)}) {
  4098. RestoreOptions ro(false /* _keep_log_files */, restore_mode);
  4099. ro.alternate_dirs.push_front(be_pair.second);
  4100. IOStatus io_st =
  4101. be_pair.first->RestoreDBFromLatestBackup(dbname_, dbname_, ro);
  4102. if (restore_mode == RestoreOptions::Mode::kKeepLatestDbSessionIdFiles) {
  4103. ASSERT_OK(io_st);
  4104. } else {
  4105. ASSERT_TRUE(io_st.IsInvalidArgument());
  4106. }
  4107. }
  4108. // Close & Re-open (no crash, etc.)
  4109. CloseBackupEngine();
  4110. OpenBackupEngine();
  4111. AssertBackupInfoConsistency(/*allow excluded*/ true);
  4112. // Excluded file(s) deleted, unable to restore
  4113. backup_engine = backup_engine_.get();
  4114. for (auto be_pair : {std::make_pair(backup_engine, alt_backup_engine),
  4115. std::make_pair(alt_backup_engine, backup_engine)}) {
  4116. RestoreOptions ro(false /* _keep_log_files */, restore_mode);
  4117. ro.alternate_dirs.push_front(be_pair.second);
  4118. IOStatus io_st =
  4119. be_pair.first->RestoreDBFromLatestBackup(dbname_, dbname_, ro);
  4120. if (restore_mode == RestoreOptions::Mode::kKeepLatestDbSessionIdFiles) {
  4121. ASSERT_OK(io_st);
  4122. } else {
  4123. ASSERT_TRUE(io_st.IsInvalidArgument());
  4124. }
  4125. }
  4126. // Ensure files are not leaked after removing everything.
  4127. ASSERT_OK(backup_engine_->DeleteBackup(first_id + 1));
  4128. ASSERT_OK(alt_backup_engine->DeleteBackup(last_alt_id - 1));
  4129. // Includes check for leaked backups files
  4130. AssertBackupInfoConsistency(/*allow excluded*/ false);
  4131. delete alt_backup_engine;
  4132. ASSERT_OK(DestroyDB(dbname_, options_));
  4133. }
  4134. }
  4135. TEST_F(BackupEngineTest, IOBufferSize) {
  4136. size_t expected_buffer_size = 5 * 1024 * 1024;
  4137. std::atomic<bool> io_buffer_size_calculated{false};
  4138. SyncPoint::GetInstance()->SetCallBack(
  4139. "BackupEngineImpl::CopyOrCreateFile:CalculateIOBufferSize",
  4140. [&](void* data) {
  4141. if (data != nullptr) {
  4142. EXPECT_EQ(expected_buffer_size, *static_cast<uint64_t*>(data));
  4143. }
  4144. io_buffer_size_calculated = true;
  4145. });
  4146. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  4147. const int keys_iteration = 5000;
  4148. Random rnd(6);
  4149. // With no overrides, fall back to the default buffer size of 5 MB
  4150. OpenDBAndBackupEngine(true /* destroy_old_data */);
  4151. FillDB(db_.get(), 0, keys_iteration);
  4152. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  4153. ASSERT_TRUE(io_buffer_size_calculated);
  4154. CloseDBAndBackupEngine();
  4155. // Override the default buffer size to 64 MB through BackupEngineOptions
  4156. expected_buffer_size = 64 * 1024 * 1024;
  4157. engine_options_->io_buffer_size = expected_buffer_size;
  4158. io_buffer_size_calculated = false;
  4159. OpenDBAndBackupEngine(true /* destroy_old_data */);
  4160. FillDB(db_.get(), 0, keys_iteration);
  4161. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  4162. ASSERT_TRUE(io_buffer_size_calculated);
  4163. CloseDBAndBackupEngine();
  4164. // Without io_buffer_size specified, the rate limiter burst bytes value will
  4165. // be used (16 MB in this example)
  4166. engine_options_->io_buffer_size = 0;
  4167. size_t single_burst_bytes = 16 * 1024 * 1024;
  4168. expected_buffer_size = single_burst_bytes;
  4169. std::shared_ptr<RateLimiter> backup_rate_limiter(NewGenericRateLimiter(
  4170. 5 * 1024 * 1024 /* rate_bytes_per_sec */,
  4171. 100 * 1000 /* refill_period_us */, 10 /* fairness */,
  4172. RateLimiter::Mode::kWritesOnly /* mode */, false /* auto_tuned */,
  4173. single_burst_bytes /* single_burst_bytes */));
  4174. engine_options_->backup_rate_limiter = backup_rate_limiter;
  4175. io_buffer_size_calculated = false;
  4176. OpenDBAndBackupEngine(true /* destroy_old_data */);
  4177. FillDB(db_.get(), 0, keys_iteration);
  4178. ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
  4179. ASSERT_TRUE(io_buffer_size_calculated);
  4180. CloseDBAndBackupEngine();
  4181. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  4182. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  4183. }
  4184. } // namespace
  4185. } // namespace ROCKSDB_NAMESPACE
  4186. int main(int argc, char** argv) {
  4187. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  4188. ::testing::InitGoogleTest(&argc, argv);
  4189. return RUN_ALL_TESTS();
  4190. }
  4191. #else
  4192. #include <stdio.h>
  4193. int main(int /*argc*/, char** /*argv*/) {
  4194. fprintf(stderr, "SKIPPED as BackupEngine is not supported in Windows\n");
  4195. return 0;
  4196. }
  4197. #endif // !defined(OS_WIN)