| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189 |
- // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
- // This source code is licensed under both the GPLv2 (found in the
- // COPYING file in the root directory) and Apache 2.0 License
- // (found in the LICENSE.Apache file in the root directory).
- //
- // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file. See the AUTHORS file for names of contributors.
- #include <cctype>
- #include <cinttypes>
- #include <cstring>
- #include <unordered_map>
- #include "cache/lru_cache.h"
- #include "cache/sharded_cache.h"
- #include "options/options_helper.h"
- #include "options/options_parser.h"
- #include "port/port.h"
- #include "rocksdb/cache.h"
- #include "rocksdb/convenience.h"
- #include "rocksdb/file_checksum.h"
- #include "rocksdb/memtablerep.h"
- #include "rocksdb/utilities/leveldb_options.h"
- #include "rocksdb/utilities/object_registry.h"
- #include "rocksdb/utilities/options_type.h"
- #include "table/block_based/filter_policy_internal.h"
- #include "test_util/testharness.h"
- #include "test_util/testutil.h"
- #include "util/random.h"
- #include "util/stderr_logger.h"
- #include "util/string_util.h"
- #include "utilities/merge_operators/bytesxor.h"
- #include "utilities/merge_operators/sortlist.h"
- #include "utilities/merge_operators/string_append/stringappend.h"
- #include "utilities/merge_operators/string_append/stringappend2.h"
- #ifndef GFLAGS
- bool FLAGS_enable_print = false;
- #else
- #include "util/gflags_compat.h"
- using GFLAGS_NAMESPACE::ParseCommandLineFlags;
- DEFINE_bool(enable_print, false, "Print options generated to console.");
- #endif // GFLAGS
- namespace ROCKSDB_NAMESPACE {
- class OptionsTest : public testing::Test {};
- class UnregisteredTableFactory : public TableFactory {
- public:
- UnregisteredTableFactory() = default;
- const char* Name() const override { return "Unregistered"; }
- using TableFactory::NewTableReader;
- Status NewTableReader(const ReadOptions&, const TableReaderOptions&,
- std::unique_ptr<RandomAccessFileReader>&&, uint64_t,
- std::unique_ptr<TableReader>*, bool) const override {
- return Status::NotSupported();
- }
- TableBuilder* NewTableBuilder(const TableBuilderOptions&,
- WritableFileWriter*) const override {
- return nullptr;
- }
- std::unique_ptr<TableFactory> Clone() const override {
- return std::make_unique<UnregisteredTableFactory>();
- }
- };
- TEST_F(OptionsTest, GetOptionsFromMapTest) {
- std::unordered_map<std::string, std::string> cf_options_map = {
- {"write_buffer_size", "1"},
- {"max_write_buffer_number", "2"},
- {"min_write_buffer_number_to_merge", "3"},
- {"max_write_buffer_number_to_maintain", "99"},
- {"max_write_buffer_size_to_maintain", "-99999"},
- {"compression", "kSnappyCompression"},
- {"compression_per_level",
- "kNoCompression:"
- "kSnappyCompression:"
- "kZlibCompression:"
- "kBZip2Compression:"
- "kLZ4Compression:"
- "kLZ4HCCompression:"
- "kXpressCompression:"
- "kZSTD"},
- {"bottommost_compression", "kLZ4Compression"},
- {"bottommost_compression_opts", "5:6:7:8:10:true"},
- {"compression_opts", "4:5:6:7:8:2:true:100:false"},
- {"num_levels", "8"},
- {"level0_file_num_compaction_trigger", "8"},
- {"level0_slowdown_writes_trigger", "9"},
- {"level0_stop_writes_trigger", "10"},
- {"target_file_size_base", "12"},
- {"target_file_size_multiplier", "13"},
- {"max_bytes_for_level_base", "14"},
- {"level_compaction_dynamic_level_bytes", "true"},
- {"max_bytes_for_level_multiplier", "15.0"},
- {"max_bytes_for_level_multiplier_additional", "16:17:18"},
- {"max_compaction_bytes", "21"},
- {"hard_pending_compaction_bytes_limit", "211"},
- {"arena_block_size", "22"},
- {"disable_auto_compactions", "true"},
- {"compaction_style", "kCompactionStyleLevel"},
- {"compaction_pri", "kOldestSmallestSeqFirst"},
- {"verify_checksums_in_compaction", "false"},
- {"compaction_options_fifo",
- "{allow_compaction=true;max_table_files_size=11002244;"
- "file_temperature_age_thresholds={{temperature=kCold;age=12345}}}"},
- {"max_sequential_skip_in_iterations", "24"},
- {"inplace_update_support", "true"},
- {"report_bg_io_stats", "true"},
- {"compaction_measure_io_stats", "false"},
- {"purge_redundant_kvs_while_flush", "false"},
- {"inplace_update_num_locks", "25"},
- {"memtable_prefix_bloom_size_ratio", "0.26"},
- {"memtable_whole_key_filtering", "true"},
- {"memtable_huge_page_size", "28"},
- {"bloom_locality", "29"},
- {"max_successive_merges", "30"},
- {"strict_max_successive_merges", "true"},
- {"min_partial_merge_operands", "31"},
- {"prefix_extractor", "fixed:31"},
- {"experimental_mempurge_threshold", "0.003"},
- {"optimize_filters_for_hits", "true"},
- {"enable_blob_files", "true"},
- {"min_blob_size", "1K"},
- {"blob_file_size", "1G"},
- {"blob_compression_type", "kZSTD"},
- {"enable_blob_garbage_collection", "true"},
- {"blob_garbage_collection_age_cutoff", "0.5"},
- {"blob_garbage_collection_force_threshold", "0.75"},
- {"blob_compaction_readahead_size", "256K"},
- {"blob_file_starting_level", "1"},
- {"prepopulate_blob_cache", "kDisable"},
- {"last_level_temperature", "kWarm"},
- {"default_write_temperature", "kCold"},
- {"default_temperature", "kHot"},
- {"persist_user_defined_timestamps", "true"},
- {"memtable_max_range_deletions", "0"},
- };
- std::unordered_map<std::string, std::string> db_options_map = {
- {"create_if_missing", "false"},
- {"create_missing_column_families", "true"},
- {"error_if_exists", "false"},
- {"paranoid_checks", "true"},
- {"track_and_verify_wals_in_manifest", "true"},
- {"track_and_verify_wals", "true"},
- {"verify_sst_unique_id_in_manifest", "true"},
- {"max_open_files", "32"},
- {"max_total_wal_size", "33"},
- {"use_fsync", "true"},
- {"db_log_dir", "/db_log_dir"},
- {"wal_dir", "/wal_dir"},
- {"delete_obsolete_files_period_micros", "34"},
- {"max_background_compactions", "35"},
- {"max_background_flushes", "36"},
- {"max_log_file_size", "37"},
- {"log_file_time_to_roll", "38"},
- {"keep_log_file_num", "39"},
- {"recycle_log_file_num", "5"},
- {"max_manifest_file_size", "40"},
- {"table_cache_numshardbits", "41"},
- {"WAL_ttl_seconds", "43"},
- {"WAL_size_limit_MB", "44"},
- {"manifest_preallocation_size", "45"},
- {"allow_mmap_reads", "true"},
- {"allow_mmap_writes", "false"},
- {"use_direct_reads", "false"},
- {"use_direct_io_for_flush_and_compaction", "false"},
- {"is_fd_close_on_exec", "true"},
- {"skip_log_error_on_recovery", "false"},
- {"stats_dump_period_sec", "46"},
- {"stats_persist_period_sec", "57"},
- {"persist_stats_to_disk", "false"},
- {"stats_history_buffer_size", "69"},
- {"advise_random_on_open", "true"},
- {"use_adaptive_mutex", "false"},
- {"compaction_readahead_size", "100"},
- {"writable_file_max_buffer_size", "314159"},
- {"bytes_per_sync", "47"},
- {"wal_bytes_per_sync", "48"},
- {"strict_bytes_per_sync", "true"},
- {"preserve_deletes", "false"},
- {"daily_offpeak_time_utc", ""},
- };
- ColumnFamilyOptions base_cf_opt;
- ColumnFamilyOptions new_cf_opt;
- ConfigOptions exact, loose;
- exact.input_strings_escaped = false;
- exact.ignore_unknown_options = false;
- exact.sanity_level = ConfigOptions::kSanityLevelExactMatch;
- loose.sanity_level = ConfigOptions::kSanityLevelLooselyCompatible;
- loose.input_strings_escaped = false;
- loose.ignore_unknown_options = true;
- ASSERT_OK(GetColumnFamilyOptionsFromMap(exact, base_cf_opt, cf_options_map,
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 1U);
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 2);
- ASSERT_EQ(new_cf_opt.min_write_buffer_number_to_merge, 3);
- ASSERT_EQ(new_cf_opt.max_write_buffer_size_to_maintain, -99999);
- ASSERT_EQ(new_cf_opt.compression, kSnappyCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level.size(), 8U);
- ASSERT_EQ(new_cf_opt.compression_per_level[0], kNoCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[1], kSnappyCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[2], kZlibCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[3], kBZip2Compression);
- ASSERT_EQ(new_cf_opt.compression_per_level[4], kLZ4Compression);
- ASSERT_EQ(new_cf_opt.compression_per_level[5], kLZ4HCCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[6], kXpressCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[7], kZSTD);
- ASSERT_EQ(new_cf_opt.compression_opts.window_bits, 4);
- ASSERT_EQ(new_cf_opt.compression_opts.level, 5);
- ASSERT_EQ(new_cf_opt.compression_opts.strategy, 6);
- ASSERT_EQ(new_cf_opt.compression_opts.max_dict_bytes, 7u);
- ASSERT_EQ(new_cf_opt.compression_opts.zstd_max_train_bytes, 8u);
- ASSERT_EQ(new_cf_opt.compression_opts.parallel_threads, 2u);
- ASSERT_EQ(new_cf_opt.compression_opts.enabled, true);
- ASSERT_EQ(new_cf_opt.compression_opts.max_dict_buffer_bytes, 100u);
- ASSERT_EQ(new_cf_opt.compression_opts.use_zstd_dict_trainer, false);
- ASSERT_EQ(new_cf_opt.bottommost_compression, kLZ4Compression);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.window_bits, 5);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.level, 6);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.strategy, 7);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.max_dict_bytes, 8u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.zstd_max_train_bytes, 10u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.parallel_threads,
- CompressionOptions().parallel_threads);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.enabled, true);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer,
- CompressionOptions().use_zstd_dict_trainer);
- ASSERT_EQ(new_cf_opt.num_levels, 8);
- ASSERT_EQ(new_cf_opt.level0_file_num_compaction_trigger, 8);
- ASSERT_EQ(new_cf_opt.level0_slowdown_writes_trigger, 9);
- ASSERT_EQ(new_cf_opt.level0_stop_writes_trigger, 10);
- ASSERT_EQ(new_cf_opt.target_file_size_base, static_cast<uint64_t>(12));
- ASSERT_EQ(new_cf_opt.target_file_size_multiplier, 13);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_base, 14U);
- ASSERT_EQ(new_cf_opt.level_compaction_dynamic_level_bytes, true);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier, 15.0);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional.size(), 3U);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional[0], 16);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional[1], 17);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional[2], 18);
- ASSERT_EQ(new_cf_opt.max_compaction_bytes, 21);
- ASSERT_EQ(new_cf_opt.hard_pending_compaction_bytes_limit, 211);
- ASSERT_EQ(new_cf_opt.arena_block_size, 22U);
- ASSERT_EQ(new_cf_opt.disable_auto_compactions, true);
- ASSERT_EQ(new_cf_opt.compaction_style, kCompactionStyleLevel);
- ASSERT_EQ(new_cf_opt.compaction_pri, kOldestSmallestSeqFirst);
- ASSERT_EQ(new_cf_opt.compaction_options_fifo.max_table_files_size,
- static_cast<uint64_t>(11002244));
- ASSERT_EQ(new_cf_opt.compaction_options_fifo.allow_compaction, true);
- ASSERT_EQ(
- new_cf_opt.compaction_options_fifo.file_temperature_age_thresholds.size(),
- 1);
- ASSERT_EQ(
- new_cf_opt.compaction_options_fifo.file_temperature_age_thresholds[0]
- .temperature,
- Temperature::kCold);
- ASSERT_EQ(
- new_cf_opt.compaction_options_fifo.file_temperature_age_thresholds[0].age,
- 12345);
- ASSERT_EQ(new_cf_opt.max_sequential_skip_in_iterations,
- static_cast<uint64_t>(24));
- ASSERT_EQ(new_cf_opt.inplace_update_support, true);
- ASSERT_EQ(new_cf_opt.inplace_update_num_locks, 25U);
- ASSERT_EQ(new_cf_opt.memtable_prefix_bloom_size_ratio, 0.26);
- ASSERT_EQ(new_cf_opt.memtable_whole_key_filtering, true);
- ASSERT_EQ(new_cf_opt.memtable_huge_page_size, 28U);
- ASSERT_EQ(new_cf_opt.bloom_locality, 29U);
- ASSERT_EQ(new_cf_opt.max_successive_merges, 30U);
- ASSERT_EQ(new_cf_opt.strict_max_successive_merges, true);
- ASSERT_TRUE(new_cf_opt.prefix_extractor != nullptr);
- ASSERT_EQ(new_cf_opt.optimize_filters_for_hits, true);
- ASSERT_EQ(new_cf_opt.prefix_extractor->AsString(), "rocksdb.FixedPrefix.31");
- ASSERT_EQ(new_cf_opt.experimental_mempurge_threshold, 0.003);
- ASSERT_EQ(new_cf_opt.enable_blob_files, true);
- ASSERT_EQ(new_cf_opt.min_blob_size, 1ULL << 10);
- ASSERT_EQ(new_cf_opt.blob_file_size, 1ULL << 30);
- ASSERT_EQ(new_cf_opt.blob_compression_type, kZSTD);
- ASSERT_EQ(new_cf_opt.enable_blob_garbage_collection, true);
- ASSERT_EQ(new_cf_opt.blob_garbage_collection_age_cutoff, 0.5);
- ASSERT_EQ(new_cf_opt.blob_garbage_collection_force_threshold, 0.75);
- ASSERT_EQ(new_cf_opt.blob_compaction_readahead_size, 262144);
- ASSERT_EQ(new_cf_opt.blob_file_starting_level, 1);
- ASSERT_EQ(new_cf_opt.prepopulate_blob_cache, PrepopulateBlobCache::kDisable);
- ASSERT_EQ(new_cf_opt.last_level_temperature, Temperature::kWarm);
- ASSERT_EQ(new_cf_opt.default_write_temperature, Temperature::kCold);
- ASSERT_EQ(new_cf_opt.default_temperature, Temperature::kHot);
- ASSERT_EQ(new_cf_opt.persist_user_defined_timestamps, true);
- ASSERT_EQ(new_cf_opt.memtable_max_range_deletions, 0);
- cf_options_map["write_buffer_size"] = "hello";
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(exact, base_cf_opt, cf_options_map,
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- cf_options_map["write_buffer_size"] = "1";
- ASSERT_OK(GetColumnFamilyOptionsFromMap(exact, base_cf_opt, cf_options_map,
- &new_cf_opt));
- cf_options_map["unknown_option"] = "1";
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(exact, base_cf_opt, cf_options_map,
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- // ignore_unknown_options=true;input_strings_escaped=false
- ASSERT_OK(GetColumnFamilyOptionsFromMap(loose, base_cf_opt, cf_options_map,
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(loose, base_cf_opt, new_cf_opt));
- ASSERT_NOK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- DBOptions base_db_opt;
- DBOptions new_db_opt;
- ASSERT_OK(
- GetDBOptionsFromMap(exact, base_db_opt, db_options_map, &new_db_opt));
- ASSERT_EQ(new_db_opt.create_if_missing, false);
- ASSERT_EQ(new_db_opt.create_missing_column_families, true);
- ASSERT_EQ(new_db_opt.error_if_exists, false);
- ASSERT_EQ(new_db_opt.paranoid_checks, true);
- ASSERT_EQ(new_db_opt.track_and_verify_wals_in_manifest, true);
- ASSERT_EQ(new_db_opt.track_and_verify_wals, true);
- ASSERT_EQ(new_db_opt.verify_sst_unique_id_in_manifest, true);
- ASSERT_EQ(new_db_opt.max_open_files, 32);
- ASSERT_EQ(new_db_opt.max_total_wal_size, static_cast<uint64_t>(33));
- ASSERT_EQ(new_db_opt.use_fsync, true);
- ASSERT_EQ(new_db_opt.db_log_dir, "/db_log_dir");
- ASSERT_EQ(new_db_opt.wal_dir, "/wal_dir");
- ASSERT_EQ(new_db_opt.delete_obsolete_files_period_micros,
- static_cast<uint64_t>(34));
- ASSERT_EQ(new_db_opt.max_background_compactions, 35);
- ASSERT_EQ(new_db_opt.max_background_flushes, 36);
- ASSERT_EQ(new_db_opt.max_log_file_size, 37U);
- ASSERT_EQ(new_db_opt.log_file_time_to_roll, 38U);
- ASSERT_EQ(new_db_opt.keep_log_file_num, 39U);
- ASSERT_EQ(new_db_opt.recycle_log_file_num, 5U);
- ASSERT_EQ(new_db_opt.max_manifest_file_size, static_cast<uint64_t>(40));
- ASSERT_EQ(new_db_opt.table_cache_numshardbits, 41);
- ASSERT_EQ(new_db_opt.WAL_ttl_seconds, static_cast<uint64_t>(43));
- ASSERT_EQ(new_db_opt.WAL_size_limit_MB, static_cast<uint64_t>(44));
- ASSERT_EQ(new_db_opt.manifest_preallocation_size, 45U);
- ASSERT_EQ(new_db_opt.allow_mmap_reads, true);
- ASSERT_EQ(new_db_opt.allow_mmap_writes, false);
- ASSERT_EQ(new_db_opt.use_direct_reads, false);
- ASSERT_EQ(new_db_opt.use_direct_io_for_flush_and_compaction, false);
- ASSERT_EQ(new_db_opt.is_fd_close_on_exec, true);
- ASSERT_EQ(new_db_opt.stats_dump_period_sec, 46U);
- ASSERT_EQ(new_db_opt.stats_persist_period_sec, 57U);
- ASSERT_EQ(new_db_opt.persist_stats_to_disk, false);
- ASSERT_EQ(new_db_opt.stats_history_buffer_size, 69U);
- ASSERT_EQ(new_db_opt.advise_random_on_open, true);
- ASSERT_EQ(new_db_opt.use_adaptive_mutex, false);
- ASSERT_EQ(new_db_opt.compaction_readahead_size, 100);
- ASSERT_EQ(new_db_opt.writable_file_max_buffer_size, 314159);
- ASSERT_EQ(new_db_opt.bytes_per_sync, static_cast<uint64_t>(47));
- ASSERT_EQ(new_db_opt.wal_bytes_per_sync, static_cast<uint64_t>(48));
- ASSERT_EQ(new_db_opt.strict_bytes_per_sync, true);
- ASSERT_EQ(new_db_opt.daily_offpeak_time_utc, "");
- db_options_map["max_open_files"] = "hello";
- Status s =
- GetDBOptionsFromMap(exact, base_db_opt, db_options_map, &new_db_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(loose, base_db_opt, new_db_opt));
- // unknow options should fail parsing without ignore_unknown_options = true
- db_options_map["unknown_db_option"] = "1";
- s = GetDBOptionsFromMap(exact, base_db_opt, db_options_map, &new_db_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- ASSERT_OK(
- GetDBOptionsFromMap(loose, base_db_opt, db_options_map, &new_db_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(loose, base_db_opt, new_db_opt));
- ASSERT_NOK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- }
- TEST_F(OptionsTest, GetColumnFamilyOptionsFromStringTest) {
- ColumnFamilyOptions base_cf_opt;
- ColumnFamilyOptions new_cf_opt;
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- config_options.ignore_unknown_options = false;
- base_cf_opt.table_factory.reset();
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt, "",
- &new_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=5", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 5U);
- ASSERT_TRUE(new_cf_opt.table_factory == nullptr);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=6;", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 6U);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, " write_buffer_size = 7 ", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 7U);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, " write_buffer_size = 8 ; ", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 8U);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=9;max_write_buffer_number=10", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 9U);
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 10);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=11; max_write_buffer_number = 12 ;", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 11U);
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 12);
- // Wrong name "max_write_buffer_number_"
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=13;max_write_buffer_number_=14;", &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- // Comparator from object registry
- std::string kCompName = "reverse_comp";
- ObjectLibrary::Default()->AddFactory<const Comparator>(
- kCompName,
- [](const std::string& /*name*/,
- std::unique_ptr<const Comparator>* /*guard*/,
- std::string* /* errmsg */) { return ReverseBytewiseComparator(); });
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "comparator=" + kCompName + ";",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.comparator, ReverseBytewiseComparator());
- // MergeOperator from object registry
- std::unique_ptr<BytesXOROperator> bxo(new BytesXOROperator());
- std::string kMoName = bxo->Name();
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "merge_operator=" + kMoName + ";",
- &new_cf_opt));
- ASSERT_EQ(kMoName, std::string(new_cf_opt.merge_operator->Name()));
- // Wrong key/value pair
- Status s = GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=13;max_write_buffer_number;", &new_cf_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- // Error Parsing value
- s = GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=13;max_write_buffer_number=;", &new_cf_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- // Missing option name
- s = GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=13; =100;", &new_cf_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- const uint64_t kilo = 1024UL;
- const uint64_t mega = 1024 * kilo;
- const uint64_t giga = 1024 * mega;
- const uint64_t tera = 1024 * giga;
- // Units (k)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "max_write_buffer_number=15K", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 15 * kilo);
- // Units (m)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "max_write_buffer_number=16m;inplace_update_num_locks=17M", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 16 * mega);
- ASSERT_EQ(new_cf_opt.inplace_update_num_locks, 17u * mega);
- // Units (g)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=18g;prefix_extractor=capped:8;"
- "arena_block_size=19G",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 18 * giga);
- ASSERT_EQ(new_cf_opt.arena_block_size, 19 * giga);
- ASSERT_TRUE(new_cf_opt.prefix_extractor.get() != nullptr);
- ASSERT_EQ(new_cf_opt.prefix_extractor->AsString(), "rocksdb.CappedPrefix.8");
- // Units (t)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=20t;arena_block_size=21T",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 20 * tera);
- ASSERT_EQ(new_cf_opt.arena_block_size, 21 * tera);
- // Nested block based table options
- // Empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={};arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- // Non-empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_cache=1M;block_size=4;};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- // Last one
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_cache=1M;block_size=4;}",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- // Mismatch curly braces
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={{{block_size=4;};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- // Unexpected chars after closing curly brace
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_size=4;}};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_size=4;}xdfa;"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_size=4;}xdfa",
- &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- // Invalid block based table option
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={xx_block_size=4;}",
- &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "optimize_filters_for_hits=true",
- &new_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "optimize_filters_for_hits=false",
- &new_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "optimize_filters_for_hits=junk",
- &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opt,
- new_cf_opt));
- // Nested plain table options
- // Empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "plain_table_factory={};arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- ASSERT_EQ(std::string(new_cf_opt.table_factory->Name()), "PlainTable");
- // Non-empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "plain_table_factory={user_key_len=66;bloom_bits_per_key=20;};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- ASSERT_EQ(std::string(new_cf_opt.table_factory->Name()), "PlainTable");
- // memtable factory
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "memtable=skip_list:10;arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.memtable_factory != nullptr);
- ASSERT_EQ(std::string(new_cf_opt.memtable_factory->Name()),
- "SkipListFactory");
- ASSERT_TRUE(new_cf_opt.memtable_factory->IsInstanceOf("SkipListFactory"));
- // blob cache
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "blob_cache={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;high_pri_pool_ratio=0.5;};",
- &new_cf_opt));
- ASSERT_NE(new_cf_opt.blob_cache, nullptr);
- ASSERT_EQ(new_cf_opt.blob_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(static_cast<ShardedCacheBase*>(new_cf_opt.blob_cache.get())
- ->GetNumShardBits(),
- 4);
- ASSERT_EQ(new_cf_opt.blob_cache->HasStrictCapacityLimit(), true);
- ASSERT_EQ(static_cast<LRUCache*>(new_cf_opt.blob_cache.get())
- ->GetHighPriPoolRatio(),
- 0.5);
- }
- TEST_F(OptionsTest, CompressionOptionsFromString) {
- ColumnFamilyOptions base_cf_opt;
- ColumnFamilyOptions new_cf_opt;
- ConfigOptions config_options;
- std::string opts_str;
- config_options.ignore_unknown_options = false;
- CompressionOptions dflt;
- // Test with some optional values removed....
- ASSERT_OK(
- GetColumnFamilyOptionsFromString(config_options, ColumnFamilyOptions(),
- "compression_opts=3:4:5; "
- "bottommost_compression_opts=4:5:6:7",
- &base_cf_opt));
- ASSERT_EQ(base_cf_opt.compression_opts.window_bits, 3);
- ASSERT_EQ(base_cf_opt.compression_opts.level, 4);
- ASSERT_EQ(base_cf_opt.compression_opts.strategy, 5);
- ASSERT_EQ(base_cf_opt.compression_opts.max_dict_bytes, dflt.max_dict_bytes);
- ASSERT_EQ(base_cf_opt.compression_opts.zstd_max_train_bytes,
- dflt.zstd_max_train_bytes);
- ASSERT_EQ(base_cf_opt.compression_opts.parallel_threads,
- dflt.parallel_threads);
- ASSERT_EQ(base_cf_opt.compression_opts.enabled, dflt.enabled);
- ASSERT_EQ(base_cf_opt.compression_opts.use_zstd_dict_trainer,
- dflt.use_zstd_dict_trainer);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.window_bits, 4);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.level, 5);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.strategy, 6);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.max_dict_bytes, 7u);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.zstd_max_train_bytes,
- dflt.zstd_max_train_bytes);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.parallel_threads,
- dflt.parallel_threads);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.enabled, dflt.enabled);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer,
- dflt.use_zstd_dict_trainer);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(),
- "compression_opts=4:5:6:7:8:9:true:10:false; "
- "bottommost_compression_opts=5:6:7:8:9:false",
- &base_cf_opt));
- ASSERT_EQ(base_cf_opt.compression_opts.window_bits, 4);
- ASSERT_EQ(base_cf_opt.compression_opts.level, 5);
- ASSERT_EQ(base_cf_opt.compression_opts.strategy, 6);
- ASSERT_EQ(base_cf_opt.compression_opts.max_dict_bytes, 7u);
- ASSERT_EQ(base_cf_opt.compression_opts.zstd_max_train_bytes, 8u);
- ASSERT_EQ(base_cf_opt.compression_opts.parallel_threads, 9u);
- ASSERT_EQ(base_cf_opt.compression_opts.enabled, true);
- ASSERT_EQ(base_cf_opt.compression_opts.max_dict_buffer_bytes, 10u);
- ASSERT_EQ(base_cf_opt.compression_opts.use_zstd_dict_trainer, false);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.window_bits, 5);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.level, 6);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.strategy, 7);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.max_dict_bytes, 8u);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.zstd_max_train_bytes, 9u);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.parallel_threads,
- dflt.parallel_threads);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.enabled, false);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer,
- dflt.use_zstd_dict_trainer);
- ASSERT_OK(
- GetStringFromColumnFamilyOptions(config_options, base_cf_opt, &opts_str));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(), opts_str, &new_cf_opt));
- ASSERT_EQ(new_cf_opt.compression_opts.window_bits, 4);
- ASSERT_EQ(new_cf_opt.compression_opts.level, 5);
- ASSERT_EQ(new_cf_opt.compression_opts.strategy, 6);
- ASSERT_EQ(new_cf_opt.compression_opts.max_dict_bytes, 7u);
- ASSERT_EQ(new_cf_opt.compression_opts.zstd_max_train_bytes, 8u);
- ASSERT_EQ(new_cf_opt.compression_opts.parallel_threads, 9u);
- ASSERT_EQ(new_cf_opt.compression_opts.enabled, true);
- ASSERT_EQ(base_cf_opt.compression_opts.max_dict_buffer_bytes, 10u);
- ASSERT_EQ(base_cf_opt.compression_opts.use_zstd_dict_trainer, false);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.window_bits, 5);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.level, 6);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.strategy, 7);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.max_dict_bytes, 8u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.zstd_max_train_bytes, 9u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.parallel_threads,
- dflt.parallel_threads);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.enabled, false);
- ASSERT_EQ(base_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer,
- dflt.use_zstd_dict_trainer);
- // Test as struct values
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(),
- "compression_opts={window_bits=5; level=6; strategy=7; max_dict_bytes=8;"
- "zstd_max_train_bytes=9;parallel_threads=10;enabled=true;use_zstd_dict_"
- "trainer=false}; "
- "bottommost_compression_opts={window_bits=4; level=5; strategy=6;"
- " max_dict_bytes=7;zstd_max_train_bytes=8;parallel_threads=9;"
- "enabled=false;use_zstd_dict_trainer=true}; ",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.compression_opts.window_bits, 5);
- ASSERT_EQ(new_cf_opt.compression_opts.level, 6);
- ASSERT_EQ(new_cf_opt.compression_opts.strategy, 7);
- ASSERT_EQ(new_cf_opt.compression_opts.max_dict_bytes, 8u);
- ASSERT_EQ(new_cf_opt.compression_opts.zstd_max_train_bytes, 9u);
- ASSERT_EQ(new_cf_opt.compression_opts.parallel_threads, 10u);
- ASSERT_EQ(new_cf_opt.compression_opts.enabled, true);
- ASSERT_EQ(new_cf_opt.compression_opts.use_zstd_dict_trainer, false);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.window_bits, 4);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.level, 5);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.strategy, 6);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.max_dict_bytes, 7u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.zstd_max_train_bytes, 8u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.parallel_threads, 9u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.enabled, false);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer, true);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "compression_opts={window_bits=4; strategy=5;};"
- "bottommost_compression_opts={level=6; strategy=7;}",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.compression_opts.window_bits, 4);
- ASSERT_EQ(new_cf_opt.compression_opts.strategy, 5);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.level, 6);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.strategy, 7);
- ASSERT_EQ(new_cf_opt.compression_opts.level,
- base_cf_opt.compression_opts.level);
- ASSERT_EQ(new_cf_opt.compression_opts.max_dict_bytes,
- base_cf_opt.compression_opts.max_dict_bytes);
- ASSERT_EQ(new_cf_opt.compression_opts.zstd_max_train_bytes,
- base_cf_opt.compression_opts.zstd_max_train_bytes);
- ASSERT_EQ(new_cf_opt.compression_opts.parallel_threads,
- base_cf_opt.compression_opts.parallel_threads);
- ASSERT_EQ(new_cf_opt.compression_opts.enabled,
- base_cf_opt.compression_opts.enabled);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.window_bits,
- base_cf_opt.bottommost_compression_opts.window_bits);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.max_dict_bytes,
- base_cf_opt.bottommost_compression_opts.max_dict_bytes);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.zstd_max_train_bytes,
- base_cf_opt.bottommost_compression_opts.zstd_max_train_bytes);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.parallel_threads,
- base_cf_opt.bottommost_compression_opts.parallel_threads);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.enabled,
- base_cf_opt.bottommost_compression_opts.enabled);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer,
- base_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer);
- // Test a few individual struct values
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "compression_opts.enabled=false; "
- "bottommost_compression_opts.enabled=true; ",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.compression_opts.enabled, false);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.enabled, true);
- // Now test some illegal values
- ConfigOptions ignore;
- ignore.ignore_unknown_options = true;
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(),
- "compression_opts=5:6:7:8:9:x:false", &base_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- ignore, ColumnFamilyOptions(), "compression_opts=5:6:7:8:9:x:false",
- &base_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(),
- "compression_opts=1:2:3:4:5:6:true:8", &base_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- ignore, ColumnFamilyOptions(), "compression_opts=1:2:3:4:5:6:true:8",
- &base_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(),
- "compression_opts=1:2:3:4:5:6:true:8:9", &base_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- ignore, ColumnFamilyOptions(), "compression_opts=1:2:3:4:5:6:true:8:9",
- &base_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(), "compression_opts={unknown=bad;}",
- &base_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(ignore, ColumnFamilyOptions(),
- "compression_opts={unknown=bad;}",
- &base_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, ColumnFamilyOptions(), "compression_opts.unknown=bad",
- &base_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(ignore, ColumnFamilyOptions(),
- "compression_opts.unknown=bad",
- &base_cf_opt));
- // Test with some additional values added
- config_options.ignore_unknown_options = false;
- ASSERT_NOK(
- GetColumnFamilyOptionsFromString(config_options, ColumnFamilyOptions(),
- "new_unknown_field=whatever; "
- "bottommost_compression_opts=4:5:6:7",
- &base_cf_opt));
- // Test Ignoring Unknown Options
- config_options.ignore_unknown_options = true;
- ASSERT_OK(
- GetColumnFamilyOptionsFromString(config_options, ColumnFamilyOptions(),
- "new_unknown_field=whatever; "
- "bottommost_compression_opts=4:5:6:7",
- &base_cf_opt));
- }
- TEST_F(OptionsTest, OldInterfaceTest) {
- ColumnFamilyOptions base_cf_opt;
- ColumnFamilyOptions new_cf_opt;
- ConfigOptions exact;
- ConfigOptions cf_config_options;
- cf_config_options.input_strings_escaped = false;
- cf_config_options.ignore_unknown_options = false;
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- cf_config_options, base_cf_opt,
- "write_buffer_size=18;prefix_extractor=capped:8;"
- "arena_block_size=19",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 18);
- ASSERT_EQ(new_cf_opt.arena_block_size, 19);
- ASSERT_TRUE(new_cf_opt.prefix_extractor.get() != nullptr);
- // And with a bad option
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- cf_config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={xx_block_size=4;}",
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- std::unordered_map<std::string, std::string> cf_options_map = {
- {"write_buffer_size", "1"},
- {"max_write_buffer_number", "2"},
- {"min_write_buffer_number_to_merge", "3"},
- };
- ASSERT_OK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- cf_options_map["unknown_option"] = "1";
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- cf_config_options.input_strings_escaped = true;
- cf_config_options.ignore_unknown_options = true;
- ASSERT_OK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- DBOptions base_db_opt;
- DBOptions new_db_opt;
- std::unordered_map<std::string, std::string> db_options_map = {
- {"create_if_missing", "false"},
- {"create_missing_column_families", "true"},
- {"error_if_exists", "false"},
- {"paranoid_checks", "true"},
- {"track_and_verify_wals_in_manifest", "true"},
- {"track_and_verify_wals", "true"},
- {"verify_sst_unique_id_in_manifest", "true"},
- {"max_open_files", "32"},
- {"daily_offpeak_time_utc", "06:30-23:30"},
- };
- ConfigOptions db_config_options(base_db_opt);
- db_config_options.input_strings_escaped = false;
- db_config_options.ignore_unknown_options = false;
- ASSERT_OK(GetDBOptionsFromMap(db_config_options, base_db_opt, db_options_map,
- &new_db_opt));
- ASSERT_EQ(new_db_opt.create_if_missing, false);
- ASSERT_EQ(new_db_opt.create_missing_column_families, true);
- ASSERT_EQ(new_db_opt.error_if_exists, false);
- ASSERT_EQ(new_db_opt.paranoid_checks, true);
- ASSERT_EQ(new_db_opt.track_and_verify_wals_in_manifest, true);
- ASSERT_EQ(new_db_opt.track_and_verify_wals, true);
- ASSERT_EQ(new_db_opt.verify_sst_unique_id_in_manifest, true);
- ASSERT_EQ(new_db_opt.max_open_files, 32);
- db_options_map["unknown_option"] = "1";
- Status s = GetDBOptionsFromMap(db_config_options, base_db_opt, db_options_map,
- &new_db_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- db_config_options.input_strings_escaped = true;
- db_config_options.ignore_unknown_options = true;
- ASSERT_OK(GetDBOptionsFromMap(db_config_options, base_db_opt, db_options_map,
- &new_db_opt));
- db_config_options.input_strings_escaped = false;
- db_config_options.ignore_unknown_options = false;
- ASSERT_OK(GetDBOptionsFromString(
- db_config_options, base_db_opt,
- "create_if_missing=false;error_if_exists=false;max_open_files=42;"
- "daily_offpeak_time_utc=08:30-19:00;",
- &new_db_opt));
- ASSERT_EQ(new_db_opt.create_if_missing, false);
- ASSERT_EQ(new_db_opt.error_if_exists, false);
- ASSERT_EQ(new_db_opt.max_open_files, 42);
- ASSERT_EQ(new_db_opt.daily_offpeak_time_utc, "08:30-19:00");
- s = GetDBOptionsFromString(
- db_config_options, base_db_opt,
- "create_if_missing=false;error_if_exists=false;max_open_files=42;"
- "unknown_option=1;",
- &new_db_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- }
- TEST_F(OptionsTest, GetBlockBasedTableOptionsFromString) {
- BlockBasedTableOptions table_opt;
- BlockBasedTableOptions new_opt;
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- config_options.ignore_unknown_options = false;
- config_options.ignore_unsupported_options = false;
- // make sure default values are overwritten by something else
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;index_type=kHashSearch;"
- "checksum=kxxHash;"
- "block_cache=1M;block_cache_compressed=1k;block_size=1024;"
- "block_size_deviation=8;block_restart_interval=4;"
- "format_version=5;whole_key_filtering=1;"
- "filter_policy=bloomfilter:4.567:false;detect_filter_construct_"
- "corruption=true;"
- // A bug caused read_amp_bytes_per_bit to be a large integer in OPTIONS
- // file generated by 6.10 to 6.14. Though bug is fixed in these releases,
- // we need to handle the case of loading OPTIONS file generated before the
- // fix.
- "read_amp_bytes_per_bit=17179869185;",
- &new_opt));
- ASSERT_TRUE(new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(new_opt.index_type, BlockBasedTableOptions::kHashSearch);
- ASSERT_EQ(new_opt.checksum, ChecksumType::kxxHash);
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(new_opt.block_size, 1024UL);
- ASSERT_EQ(new_opt.block_size_deviation, 8);
- ASSERT_EQ(new_opt.block_restart_interval, 4);
- ASSERT_EQ(new_opt.format_version, 5U);
- ASSERT_EQ(new_opt.whole_key_filtering, true);
- ASSERT_EQ(new_opt.detect_filter_construct_corruption, true);
- ASSERT_TRUE(new_opt.filter_policy != nullptr);
- auto bfp = new_opt.filter_policy->CheckedCast<BloomFilterPolicy>();
- ASSERT_NE(bfp, nullptr);
- EXPECT_EQ(bfp->GetMillibitsPerKey(), 4567);
- EXPECT_EQ(bfp->GetWholeBitsPerKey(), 5);
- // Verify that only the lower 32bits are stored in
- // new_opt.read_amp_bytes_per_bit.
- EXPECT_EQ(1U, new_opt.read_amp_bytes_per_bit);
- // unknown option
- Status s = GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;index_type=kBinarySearch;"
- "bad_option=1",
- &new_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_EQ(static_cast<bool>(table_opt.cache_index_and_filter_blocks),
- new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(table_opt.index_type, new_opt.index_type);
- // unrecognized index type
- s = GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;index_type=kBinarySearchXX", &new_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_EQ(table_opt.cache_index_and_filter_blocks,
- new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(table_opt.index_type, new_opt.index_type);
- // unrecognized checksum type
- ASSERT_NOK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;checksum=kxxHashXX", &new_opt));
- ASSERT_EQ(table_opt.cache_index_and_filter_blocks,
- new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(table_opt.index_type, new_opt.index_type);
- // unrecognized filter policy name
- s = GetBlockBasedTableOptionsFromString(config_options, table_opt,
- "filter_policy=bloomfilterxx:4:true",
- &new_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- // missing bits per key
- s = GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=bloomfilter", &new_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- // Used to be rejected, now accepted
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=bloomfilter:4", &new_opt));
- bfp = dynamic_cast<const BloomFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(bfp->GetMillibitsPerKey(), 4000);
- EXPECT_EQ(bfp->GetWholeBitsPerKey(), 4);
- // use_block_based_builder=true now ignored in public API (same as false)
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=bloomfilter:4:true", &new_opt));
- bfp = dynamic_cast<const BloomFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(bfp->GetMillibitsPerKey(), 4000);
- EXPECT_EQ(bfp->GetWholeBitsPerKey(), 4);
- // Test configuring using other internal names
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "filter_policy=rocksdb.internal.LegacyBloomFilter:3", &new_opt));
- auto builtin =
- dynamic_cast<const BuiltinFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(builtin->GetId(), "rocksdb.internal.LegacyBloomFilter:3");
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "filter_policy=rocksdb.internal.FastLocalBloomFilter:1.234", &new_opt));
- builtin =
- dynamic_cast<const BuiltinFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(builtin->GetId(), "rocksdb.internal.FastLocalBloomFilter:1.234");
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "filter_policy=rocksdb.internal.Standard128RibbonFilter:1.234",
- &new_opt));
- builtin =
- dynamic_cast<const BuiltinFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(builtin->GetId(), "rocksdb.internal.Standard128RibbonFilter:1.234");
- // Ribbon filter policy (no Bloom hybrid)
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=ribbonfilter:5.678:-1;",
- &new_opt));
- ASSERT_TRUE(new_opt.filter_policy != nullptr);
- auto rfp =
- dynamic_cast<const RibbonFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(rfp->GetMillibitsPerKey(), 5678);
- EXPECT_EQ(rfp->GetBloomBeforeLevel(), -1);
- // Ribbon filter policy (default Bloom hybrid)
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=ribbonfilter:6.789;",
- &new_opt));
- ASSERT_TRUE(new_opt.filter_policy != nullptr);
- rfp = dynamic_cast<const RibbonFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(rfp->GetMillibitsPerKey(), 6789);
- EXPECT_EQ(rfp->GetBloomBeforeLevel(), 0);
- // Ribbon filter policy (custom Bloom hybrid)
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=ribbonfilter:6.789:5;",
- &new_opt));
- ASSERT_TRUE(new_opt.filter_policy != nullptr);
- rfp = dynamic_cast<const RibbonFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(rfp->GetMillibitsPerKey(), 6789);
- EXPECT_EQ(rfp->GetBloomBeforeLevel(), 5);
- // Check block cache options are overwritten when specified
- // in new format as a struct.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;high_pri_pool_ratio=0.5;};"
- "block_cache_compressed={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;high_pri_pool_ratio=0.5;}",
- &new_opt));
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- 4);
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), true);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- // Set only block cache capacity. Check other values are
- // reset to default values.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={capacity=2M};"
- "block_cache_compressed={capacity=2M}",
- &new_opt));
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 2 * 1024UL * 1024UL);
- // Default values
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- GetDefaultCacheShardBits(new_opt.block_cache->GetCapacity()));
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), false);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- // Set couple of block cache options.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={num_shard_bits=5;high_pri_pool_ratio=0.5;};"
- "block_cache_compressed={num_shard_bits=5;"
- "high_pri_pool_ratio=0.0;}",
- &new_opt));
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 0);
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- 5);
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), false);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- // Set couple of block cache options.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;};"
- "block_cache_compressed={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;}",
- &new_opt));
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- 4);
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), true);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=rocksdb.BloomFilter:1.234",
- &new_opt));
- ASSERT_TRUE(new_opt.filter_policy != nullptr);
- ASSERT_TRUE(
- new_opt.filter_policy->IsInstanceOf(BloomFilterPolicy::kClassName()));
- ASSERT_TRUE(
- new_opt.filter_policy->IsInstanceOf(BloomFilterPolicy::kNickName()));
- // Ribbon filter policy alternative name
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=rocksdb.RibbonFilter:6.789:5;",
- &new_opt));
- ASSERT_TRUE(new_opt.filter_policy != nullptr);
- ASSERT_TRUE(
- new_opt.filter_policy->IsInstanceOf(RibbonFilterPolicy::kClassName()));
- ASSERT_TRUE(
- new_opt.filter_policy->IsInstanceOf(RibbonFilterPolicy::kNickName()));
- }
- TEST_F(OptionsTest, GetPlainTableOptionsFromString) {
- PlainTableOptions table_opt;
- PlainTableOptions new_opt;
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- config_options.ignore_unknown_options = false;
- // make sure default values are overwritten by something else
- ASSERT_OK(GetPlainTableOptionsFromString(
- config_options, table_opt,
- "user_key_len=66;bloom_bits_per_key=20;hash_table_ratio=0.5;"
- "index_sparseness=8;huge_page_tlb_size=4;encoding_type=kPrefix;"
- "full_scan_mode=true;store_index_in_file=true",
- &new_opt));
- ASSERT_EQ(new_opt.user_key_len, 66u);
- ASSERT_EQ(new_opt.bloom_bits_per_key, 20);
- ASSERT_EQ(new_opt.hash_table_ratio, 0.5);
- ASSERT_EQ(new_opt.index_sparseness, 8);
- ASSERT_EQ(new_opt.huge_page_tlb_size, 4);
- ASSERT_EQ(new_opt.encoding_type, EncodingType::kPrefix);
- ASSERT_TRUE(new_opt.full_scan_mode);
- ASSERT_TRUE(new_opt.store_index_in_file);
- // unknown option
- Status s = GetPlainTableOptionsFromString(
- config_options, table_opt,
- "user_key_len=66;bloom_bits_per_key=20;hash_table_ratio=0.5;"
- "bad_option=1",
- &new_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- // unrecognized EncodingType
- s = GetPlainTableOptionsFromString(
- config_options, table_opt,
- "user_key_len=66;bloom_bits_per_key=20;hash_table_ratio=0.5;"
- "encoding_type=kPrefixXX",
- &new_opt);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- }
- TEST_F(OptionsTest, GetMemTableRepFactoryFromString) {
- std::unique_ptr<MemTableRepFactory> new_mem_factory = nullptr;
- ASSERT_OK(GetMemTableRepFactoryFromString("skip_list", &new_mem_factory));
- ASSERT_OK(GetMemTableRepFactoryFromString("skip_list:16", &new_mem_factory));
- ASSERT_STREQ(new_mem_factory->Name(), "SkipListFactory");
- ASSERT_NOK(GetMemTableRepFactoryFromString("skip_list:16:invalid_opt",
- &new_mem_factory));
- ASSERT_OK(GetMemTableRepFactoryFromString("prefix_hash", &new_mem_factory));
- ASSERT_OK(
- GetMemTableRepFactoryFromString("prefix_hash:1000", &new_mem_factory));
- ASSERT_STREQ(new_mem_factory->Name(), "HashSkipListRepFactory");
- ASSERT_NOK(GetMemTableRepFactoryFromString("prefix_hash:1000:invalid_opt",
- &new_mem_factory));
- ASSERT_OK(
- GetMemTableRepFactoryFromString("hash_linkedlist", &new_mem_factory));
- ASSERT_OK(GetMemTableRepFactoryFromString("hash_linkedlist:1000",
- &new_mem_factory));
- ASSERT_EQ(std::string(new_mem_factory->Name()), "HashLinkListRepFactory");
- ASSERT_NOK(GetMemTableRepFactoryFromString("hash_linkedlist:1000:invalid_opt",
- &new_mem_factory));
- ASSERT_OK(GetMemTableRepFactoryFromString("vector", &new_mem_factory));
- ASSERT_OK(GetMemTableRepFactoryFromString("vector:1024", &new_mem_factory));
- ASSERT_EQ(std::string(new_mem_factory->Name()), "VectorRepFactory");
- ASSERT_NOK(GetMemTableRepFactoryFromString("vector:1024:invalid_opt",
- &new_mem_factory));
- ASSERT_NOK(GetMemTableRepFactoryFromString("cuckoo", &new_mem_factory));
- // CuckooHash memtable is already removed.
- ASSERT_NOK(GetMemTableRepFactoryFromString("cuckoo:1024", &new_mem_factory));
- ASSERT_NOK(GetMemTableRepFactoryFromString("bad_factory", &new_mem_factory));
- }
- TEST_F(OptionsTest, MemTableRepFactoryCreateFromString) {
- std::unique_ptr<MemTableRepFactory> new_mem_factory = nullptr;
- ConfigOptions config_options;
- config_options.ignore_unsupported_options = false;
- config_options.ignore_unknown_options = false;
- ASSERT_OK(MemTableRepFactory::CreateFromString(config_options, "skip_list",
- &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(config_options, "skip_list:16",
- &new_mem_factory));
- ASSERT_STREQ(new_mem_factory->Name(), "SkipListFactory");
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("skip_list"));
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("SkipListFactory"));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options, "skip_list:16:invalid_opt", &new_mem_factory));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options, "invalid_opt=10", &new_mem_factory));
- // Test a reset
- ASSERT_OK(MemTableRepFactory::CreateFromString(config_options, "",
- &new_mem_factory));
- ASSERT_EQ(new_mem_factory, nullptr);
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options, "invalid_opt=10", &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(
- config_options, "id=skip_list; lookahead=32", &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(config_options, "prefix_hash",
- &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(
- config_options, "prefix_hash:1000", &new_mem_factory));
- ASSERT_STREQ(new_mem_factory->Name(), "HashSkipListRepFactory");
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("prefix_hash"));
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("HashSkipListRepFactory"));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options, "prefix_hash:1000:invalid_opt", &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(
- config_options,
- "id=prefix_hash; bucket_count=32; skiplist_height=64; "
- "branching_factor=16",
- &new_mem_factory));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options,
- "id=prefix_hash; bucket_count=32; skiplist_height=64; "
- "branching_factor=16; invalid=unknown",
- &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(
- config_options, "hash_linkedlist", &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(
- config_options, "hash_linkedlist:1000", &new_mem_factory));
- ASSERT_STREQ(new_mem_factory->Name(), "HashLinkListRepFactory");
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("hash_linkedlist"));
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("HashLinkListRepFactory"));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options, "hash_linkedlist:1000:invalid_opt", &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(
- config_options,
- "id=hash_linkedlist; bucket_count=32; threshold=64; huge_page_size=16; "
- "logging_threshold=12; log_when_flash=true",
- &new_mem_factory));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options,
- "id=hash_linkedlist; bucket_count=32; threshold=64; huge_page_size=16; "
- "logging_threshold=12; log_when_flash=true; invalid=unknown",
- &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(config_options, "vector",
- &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(config_options, "vector:1024",
- &new_mem_factory));
- ASSERT_STREQ(new_mem_factory->Name(), "VectorRepFactory");
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("vector"));
- ASSERT_TRUE(new_mem_factory->IsInstanceOf("VectorRepFactory"));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options, "vector:1024:invalid_opt", &new_mem_factory));
- ASSERT_OK(MemTableRepFactory::CreateFromString(
- config_options, "id=vector; count=42", &new_mem_factory));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(
- config_options, "id=vector; invalid=unknown", &new_mem_factory));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(config_options, "cuckoo",
- &new_mem_factory));
- // CuckooHash memtable is already removed.
- ASSERT_NOK(MemTableRepFactory::CreateFromString(config_options, "cuckoo:1024",
- &new_mem_factory));
- ASSERT_NOK(MemTableRepFactory::CreateFromString(config_options, "bad_factory",
- &new_mem_factory));
- }
- class CustomEnv : public EnvWrapper {
- public:
- explicit CustomEnv(Env* _target) : EnvWrapper(_target) {}
- static const char* kClassName() { return "CustomEnv"; }
- const char* Name() const override { return kClassName(); }
- };
- TEST_F(OptionsTest, GetOptionsFromStringTest) {
- Options base_options, new_options;
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- config_options.ignore_unknown_options = false;
- base_options.write_buffer_size = 20;
- base_options.min_write_buffer_number_to_merge = 15;
- BlockBasedTableOptions block_based_table_options;
- block_based_table_options.cache_index_and_filter_blocks = true;
- base_options.table_factory.reset(
- NewBlockBasedTableFactory(block_based_table_options));
- // Register an Env with object registry.
- ObjectLibrary::Default()->AddFactory<Env>(
- CustomEnv::kClassName(),
- [](const std::string& /*name*/, std::unique_ptr<Env>* /*env_guard*/,
- std::string* /* errmsg */) {
- static CustomEnv env(Env::Default());
- return &env;
- });
- ASSERT_OK(GetOptionsFromString(
- config_options, base_options,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_cache=1M;block_size=4;};"
- "compression_opts=4:5:6;create_if_missing=true;max_open_files=1;"
- "bottommost_compression_opts=5:6:7;create_if_missing=true;max_open_files="
- "1;"
- "rate_limiter_bytes_per_sec=1024;env=CustomEnv",
- &new_options));
- ASSERT_EQ(new_options.compression_opts.window_bits, 4);
- ASSERT_EQ(new_options.compression_opts.level, 5);
- ASSERT_EQ(new_options.compression_opts.strategy, 6);
- ASSERT_EQ(new_options.compression_opts.max_dict_bytes, 0u);
- ASSERT_EQ(new_options.compression_opts.zstd_max_train_bytes, 0u);
- ASSERT_EQ(new_options.compression_opts.parallel_threads, 1u);
- ASSERT_EQ(new_options.compression_opts.enabled, false);
- ASSERT_EQ(new_options.compression_opts.use_zstd_dict_trainer, true);
- ASSERT_EQ(new_options.bottommost_compression, kDisableCompressionOption);
- ASSERT_EQ(new_options.bottommost_compression_opts.window_bits, 5);
- ASSERT_EQ(new_options.bottommost_compression_opts.level, 6);
- ASSERT_EQ(new_options.bottommost_compression_opts.strategy, 7);
- ASSERT_EQ(new_options.bottommost_compression_opts.max_dict_bytes, 0u);
- ASSERT_EQ(new_options.bottommost_compression_opts.zstd_max_train_bytes, 0u);
- ASSERT_EQ(new_options.bottommost_compression_opts.parallel_threads, 1u);
- ASSERT_EQ(new_options.bottommost_compression_opts.enabled, false);
- ASSERT_EQ(new_options.bottommost_compression_opts.use_zstd_dict_trainer,
- true);
- ASSERT_EQ(new_options.write_buffer_size, 10U);
- ASSERT_EQ(new_options.max_write_buffer_number, 16);
- const auto new_bbto =
- new_options.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_NE(new_bbto, nullptr);
- ASSERT_EQ(new_bbto->block_cache->GetCapacity(), 1U << 20);
- ASSERT_EQ(new_bbto->block_size, 4U);
- // don't overwrite block based table options
- ASSERT_TRUE(new_bbto->cache_index_and_filter_blocks);
- ASSERT_EQ(new_options.create_if_missing, true);
- ASSERT_EQ(new_options.max_open_files, 1);
- ASSERT_TRUE(new_options.rate_limiter.get() != nullptr);
- Env* newEnv = new_options.env;
- ASSERT_OK(Env::CreateFromString({}, CustomEnv::kClassName(), &newEnv));
- ASSERT_EQ(newEnv, new_options.env);
- config_options.ignore_unknown_options = false;
- // Test a bad value for a DBOption returns a failure
- base_options.dump_malloc_stats = false;
- base_options.write_buffer_size = 1024;
- Options bad_options = new_options;
- Status s = GetOptionsFromString(config_options, base_options,
- "create_if_missing=XX;dump_malloc_stats=true",
- &bad_options);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_EQ(bad_options.dump_malloc_stats, false);
- bad_options = new_options;
- s = GetOptionsFromString(config_options, base_options,
- "write_buffer_size=XX;dump_malloc_stats=true",
- &bad_options);
- ASSERT_NOK(s);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_EQ(bad_options.dump_malloc_stats, false);
- // Test a bad value for a TableFactory Option returns a failure
- bad_options = new_options;
- s = GetOptionsFromString(config_options, base_options,
- "write_buffer_size=16;dump_malloc_stats=true"
- "block_based_table_factory={block_size=XX;};",
- &bad_options);
- ASSERT_TRUE(s.IsInvalidArgument());
- ASSERT_EQ(bad_options.dump_malloc_stats, false);
- ASSERT_EQ(bad_options.write_buffer_size, 1024);
- config_options.ignore_unknown_options = true;
- ASSERT_OK(GetOptionsFromString(config_options, base_options,
- "create_if_missing=XX;dump_malloc_stats=true;"
- "write_buffer_size=XX;"
- "block_based_table_factory={block_size=XX;};",
- &bad_options));
- ASSERT_EQ(bad_options.create_if_missing, base_options.create_if_missing);
- ASSERT_EQ(bad_options.dump_malloc_stats, true);
- ASSERT_EQ(bad_options.write_buffer_size, base_options.write_buffer_size);
- // Test the old interface
- ASSERT_OK(GetOptionsFromString(
- base_options,
- "write_buffer_size=22;max_write_buffer_number=33;max_open_files=44;",
- &new_options));
- ASSERT_EQ(new_options.write_buffer_size, 22U);
- ASSERT_EQ(new_options.max_write_buffer_number, 33);
- ASSERT_EQ(new_options.max_open_files, 44);
- }
- TEST_F(OptionsTest, DBOptionsSerialization) {
- Options base_options, new_options;
- Random rnd(301);
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- config_options.ignore_unknown_options = false;
- // Phase 1: Make big change in base_options
- test::RandomInitDBOptions(&base_options, &rnd);
- // Phase 2: obtain a string from base_option
- std::string base_options_file_content;
- ASSERT_OK(GetStringFromDBOptions(config_options, base_options,
- &base_options_file_content));
- // Phase 3: Set new_options from the derived string and expect
- // new_options == base_options
- ASSERT_OK(GetDBOptionsFromString(config_options, DBOptions(),
- base_options_file_content, &new_options));
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(config_options, base_options,
- new_options));
- }
- TEST_F(OptionsTest, OptionsComposeDecompose) {
- // build an Options from DBOptions + CFOptions, then decompose it to verify
- // we get same constituent options.
- DBOptions base_db_opts;
- ColumnFamilyOptions base_cf_opts;
- ConfigOptions
- config_options; // Use default for ignore(false) and check (exact)
- config_options.input_strings_escaped = false;
- Random rnd(301);
- test::RandomInitDBOptions(&base_db_opts, &rnd);
- test::RandomInitCFOptions(&base_cf_opts, base_db_opts, &rnd);
- Options base_opts(base_db_opts, base_cf_opts);
- DBOptions new_db_opts(base_opts);
- ColumnFamilyOptions new_cf_opts(base_opts);
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(config_options, base_db_opts,
- new_db_opts));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_cf_opts,
- new_cf_opts));
- delete new_cf_opts.compaction_filter;
- }
- TEST_F(OptionsTest, DBOptionsComposeImmutable) {
- // Build a DBOptions from an Immutable/Mutable one and verify that
- // we get same constituent options.
- ConfigOptions config_options;
- Random rnd(301);
- DBOptions base_opts, new_opts;
- test::RandomInitDBOptions(&base_opts, &rnd);
- MutableDBOptions m_opts(base_opts);
- ImmutableDBOptions i_opts(base_opts);
- new_opts = BuildDBOptions(i_opts, m_opts);
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(config_options, base_opts,
- new_opts));
- }
- TEST_F(OptionsTest, GetMutableDBOptions) {
- Random rnd(228);
- DBOptions base_opts;
- std::string opts_str;
- std::unordered_map<std::string, std::string> opts_map;
- ConfigOptions config_options;
- test::RandomInitDBOptions(&base_opts, &rnd);
- ImmutableDBOptions i_opts(base_opts);
- MutableDBOptions m_opts(base_opts);
- MutableDBOptions new_opts;
- ASSERT_OK(GetStringFromMutableDBOptions(config_options, m_opts, &opts_str));
- ASSERT_OK(StringToMap(opts_str, &opts_map));
- ASSERT_OK(GetMutableDBOptionsFromStrings(m_opts, opts_map, &new_opts));
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(
- config_options, base_opts, BuildDBOptions(i_opts, new_opts)));
- }
- TEST_F(OptionsTest, CFOptionsComposeImmutable) {
- // Build a DBOptions from an Immutable/Mutable one and verify that
- // we get same constituent options.
- ConfigOptions config_options;
- Random rnd(301);
- ColumnFamilyOptions base_opts, new_opts;
- DBOptions dummy; // Needed to create ImmutableCFOptions
- test::RandomInitCFOptions(&base_opts, dummy, &rnd);
- MutableCFOptions m_opts(base_opts);
- ImmutableCFOptions i_opts(base_opts);
- UpdateColumnFamilyOptions(i_opts, &new_opts);
- UpdateColumnFamilyOptions(m_opts, &new_opts);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base_opts,
- new_opts));
- delete new_opts.compaction_filter;
- }
- TEST_F(OptionsTest, GetMutableCFOptions) {
- Random rnd(228);
- ColumnFamilyOptions base, copy;
- std::string opts_str;
- std::unordered_map<std::string, std::string> opts_map;
- ConfigOptions config_options;
- DBOptions dummy; // Needed to create ImmutableCFOptions
- test::RandomInitCFOptions(&base, dummy, &rnd);
- ColumnFamilyOptions result;
- MutableCFOptions m_opts(base), new_opts;
- ASSERT_OK(GetStringFromMutableCFOptions(config_options, m_opts, &opts_str));
- ASSERT_OK(StringToMap(opts_str, &opts_map));
- ASSERT_OK(GetMutableOptionsFromStrings(m_opts, opts_map, nullptr, &new_opts));
- UpdateColumnFamilyOptions(ImmutableCFOptions(base), ©);
- UpdateColumnFamilyOptions(new_opts, ©);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, base, copy));
- delete copy.compaction_filter;
- }
- TEST_F(OptionsTest, ColumnFamilyOptionsSerialization) {
- Options options;
- ColumnFamilyOptions base_opt, new_opt;
- base_opt.comparator = test::BytewiseComparatorWithU64TsWrapper();
- Random rnd(302);
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- // Phase 1: randomly assign base_opt
- // custom type options
- test::RandomInitCFOptions(&base_opt, options, &rnd);
- // Phase 2: obtain a string from base_opt
- std::string base_options_file_content;
- ASSERT_OK(GetStringFromColumnFamilyOptions(config_options, base_opt,
- &base_options_file_content));
- // Phase 3: Set new_opt from the derived string and expect
- // new_opt == base_opt
- ASSERT_OK(
- GetColumnFamilyOptionsFromString(config_options, ColumnFamilyOptions(),
- base_options_file_content, &new_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(config_options, base_opt, new_opt));
- ASSERT_EQ(base_opt.comparator, new_opt.comparator);
- if (base_opt.compaction_filter) {
- delete base_opt.compaction_filter;
- }
- }
- TEST_F(OptionsTest, CheckBlockBasedTableOptions) {
- ColumnFamilyOptions cf_opts;
- DBOptions db_opts;
- ConfigOptions config_opts;
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_opts, cf_opts, "prefix_extractor=capped:8", &cf_opts));
- ASSERT_OK(TableFactory::CreateFromString(config_opts, "BlockBasedTable",
- &cf_opts.table_factory));
- ASSERT_NE(cf_opts.table_factory.get(), nullptr);
- ASSERT_TRUE(cf_opts.table_factory->IsInstanceOf(
- TableFactory::kBlockBasedTableName()));
- auto bbto = cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_OK(cf_opts.table_factory->ConfigureFromString(
- config_opts,
- "block_cache={capacity=1M;num_shard_bits=4;};"
- "block_size_deviation=101;"
- "block_restart_interval=0;"
- "index_block_restart_interval=5;"
- "partition_filters=true;"
- "index_type=kHashSearch;"
- "no_block_cache=1;"));
- ASSERT_NE(bbto, nullptr);
- ASSERT_EQ(bbto->block_cache.get(), nullptr);
- ASSERT_EQ(bbto->block_size_deviation, 0);
- ASSERT_EQ(bbto->block_restart_interval, 1);
- ASSERT_EQ(bbto->index_block_restart_interval, 1);
- ASSERT_FALSE(bbto->partition_filters);
- ASSERT_OK(TableFactory::CreateFromString(config_opts, "BlockBasedTable",
- &cf_opts.table_factory));
- bbto = cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_OK(cf_opts.table_factory->ConfigureFromString(config_opts,
- "no_block_cache=0;"));
- ASSERT_NE(bbto->block_cache.get(), nullptr);
- ASSERT_OK(cf_opts.table_factory->ValidateOptions(db_opts, cf_opts));
- }
- TEST_F(OptionsTest, MutableTableOptions) {
- ConfigOptions config_options;
- std::shared_ptr<TableFactory> bbtf;
- bbtf.reset(NewBlockBasedTableFactory());
- auto bbto = bbtf->GetOptions<BlockBasedTableOptions>();
- ASSERT_NE(bbto, nullptr);
- ASSERT_OK(bbtf->ConfigureOption(config_options, "no_block_cache", "true"));
- ASSERT_OK(bbtf->ConfigureOption(config_options, "block_size", "1024"));
- ASSERT_EQ(bbto->no_block_cache, true);
- ASSERT_EQ(bbto->block_size, 1024);
- ASSERT_OK(bbtf->PrepareOptions(config_options));
- config_options.mutable_options_only = true;
- // Options on BlockBasedTableOptions/Factory are no longer directly mutable
- // but have to be mutated on a live DB with SetOptions replacing the
- // table_factory with a copy using the new options.
- ASSERT_NOK(bbtf->ConfigureOption(config_options, "no_block_cache", "false"));
- ASSERT_NOK(bbtf->ConfigureOption(config_options, "block_size", "2048"));
- ASSERT_EQ(bbto->no_block_cache, true);
- ASSERT_EQ(bbto->block_size, 1024);
- ColumnFamilyOptions cf_opts;
- cf_opts.table_factory = bbtf;
- // FIXME: find a way to make this fail again
- /*
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, cf_opts, "block_based_table_factory.no_block_cache=false",
- &cf_opts));
- */
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, cf_opts, "block_based_table_factory.block_size=8192",
- &cf_opts));
- const auto new_bbto =
- cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_NE(new_bbto, nullptr);
- ASSERT_NE(new_bbto, bbto);
- ASSERT_EQ(new_bbto->no_block_cache, true);
- ASSERT_EQ(new_bbto->block_size, 8192);
- ASSERT_EQ(bbto->block_size, 1024);
- }
- TEST_F(OptionsTest, MutableCFOptions) {
- ConfigOptions config_options;
- ColumnFamilyOptions cf_opts;
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, cf_opts,
- "paranoid_file_checks=true; block_based_table_factory.block_align=false; "
- "block_based_table_factory.super_block_alignment_size=65536; "
- "block_based_table_factory.super_block_alignment_space_overhead_ratio="
- "4096; "
- "block_based_table_factory.block_size=8192;",
- &cf_opts));
- ASSERT_TRUE(cf_opts.paranoid_file_checks);
- ASSERT_NE(cf_opts.table_factory.get(), nullptr);
- auto* bbto = cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_NE(bbto, nullptr);
- ASSERT_EQ(bbto->block_size, 8192);
- ASSERT_EQ(bbto->block_align, false);
- ASSERT_EQ(bbto->super_block_alignment_size, 65536);
- ASSERT_EQ(bbto->super_block_alignment_space_overhead_ratio, 4096);
- std::unordered_map<std::string, std::string> unused_opts;
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts, {{"paranoid_file_checks", "false"}}, &cf_opts));
- ASSERT_EQ(cf_opts.paranoid_file_checks, false);
- // Should replace the factory with the new setting
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"block_based_table_factory.block_size", "16384"}}, &cf_opts));
- bbto = cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_EQ(bbto->block_size, 16384);
- config_options.mutable_options_only = true;
- // Force consistency checks is not mutable
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts, {{"force_consistency_checks", "true"}},
- &cf_opts));
- // Attempt to change the table factory kind. This was previously disallowed
- // and is a dubious operation but is tricky to disallow without breaking
- // other things (FIXME?)
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts, {{"table_factory", "PlainTable"}}, &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(), TableFactory::kPlainTableName());
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts, {{"table_factory", "BlockBasedTable"}},
- &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(),
- TableFactory::kBlockBasedTableName());
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts, {{"table_factory.id", "PlainTable"}}, &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(), TableFactory::kPlainTableName());
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts, {{"table_factory.id", "BlockBasedTable"}},
- &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(),
- TableFactory::kBlockBasedTableName());
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"table_factory", "{id=PlainTable;bloom_bits_per_key=42}"}}, &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(), TableFactory::kPlainTableName());
- // Should at least be allowed to instantiate in place of nullptr, for
- // initialization purposes.
- cf_opts.table_factory = nullptr;
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"table_factory", "{id=BlockBasedTable;block_size=12345}"}}, &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(),
- TableFactory::kBlockBasedTableName());
- bbto = cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_EQ(bbto->block_size, 12345);
- // Accessing through the wrong factory alias fails gracefully
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"plain_table_factory", "{bloom_bits_per_key=42}"}}, &cf_opts));
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"plain_table_factory.bloom_bits_per_key", "42"}}, &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(),
- TableFactory::kBlockBasedTableName());
- // Change the block size.
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"block_based_table_factory.block_size", "8192"}}, &cf_opts));
- bbto = cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_EQ(bbto->block_size, 8192);
- // Attempt to turn off block cache fails, as this option is not mutable
- // FIXME: find a way to make this fail again
- /*
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"block_based_table_factory.no_block_cache", "true"}}, &cf_opts));
- */
- // Attempt to change the block size via a config string/map.
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"block_based_table_factory", "{block_size=32768}"}}, &cf_opts));
- bbto = cf_opts.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_EQ(bbto->block_size, 32768);
- // Attempt to change the block size and no cache through the map. Should
- // fail, leaving the old values intact
- // FIXME: find a way to make this fail again
- /*
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"block_based_table_factory",
- "{block_size=16384; no_block_cache=true}"}},
- &cf_opts));
- */
- ASSERT_EQ(bbto->block_size, 32768);
- // Switch to plain table for some tests
- cf_opts.table_factory = nullptr;
- ASSERT_OK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"table_factory", "{id=PlainTable;bloom_bits_per_key=42}"}}, &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(), TableFactory::kPlainTableName());
- auto* pto = cf_opts.table_factory->GetOptions<PlainTableOptions>();
- ASSERT_EQ(pto->bloom_bits_per_key, 42);
- // Accessing through the wrong factory alias fails gracefully
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"block_based_table_factory.block_size", "8192"}}, &cf_opts));
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(
- config_options, cf_opts,
- {{"block_based_table_factory", "{block_size=32768}"}}, &cf_opts));
- ASSERT_STREQ(cf_opts.table_factory->Name(), TableFactory::kPlainTableName());
- ASSERT_EQ(pto, cf_opts.table_factory->GetOptions<PlainTableOptions>());
- }
- Status StringToMap(const std::string& opts_str,
- std::unordered_map<std::string, std::string>* opts_map);
- TEST_F(OptionsTest, StringToMapTest) {
- std::unordered_map<std::string, std::string> opts_map;
- // Regular options
- ASSERT_OK(StringToMap("k1=v1;k2=v2;k3=v3", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "v2");
- ASSERT_EQ(opts_map["k3"], "v3");
- // Value with '='
- opts_map.clear();
- ASSERT_OK(StringToMap("k1==v1;k2=v2=;", &opts_map));
- ASSERT_EQ(opts_map["k1"], "=v1");
- ASSERT_EQ(opts_map["k2"], "v2=");
- // Overwrriten option
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k1=v2;k3=v3", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v2");
- ASSERT_EQ(opts_map["k3"], "v3");
- // Empty value
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2=;k3=v3;k4=", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_TRUE(opts_map.find("k2") != opts_map.end());
- ASSERT_EQ(opts_map["k2"], "");
- ASSERT_EQ(opts_map["k3"], "v3");
- ASSERT_TRUE(opts_map.find("k4") != opts_map.end());
- ASSERT_EQ(opts_map["k4"], "");
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2=;k3=v3;k4= ", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_TRUE(opts_map.find("k2") != opts_map.end());
- ASSERT_EQ(opts_map["k2"], "");
- ASSERT_EQ(opts_map["k3"], "v3");
- ASSERT_TRUE(opts_map.find("k4") != opts_map.end());
- ASSERT_EQ(opts_map["k4"], "");
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2=;k3=", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_TRUE(opts_map.find("k2") != opts_map.end());
- ASSERT_EQ(opts_map["k2"], "");
- ASSERT_TRUE(opts_map.find("k3") != opts_map.end());
- ASSERT_EQ(opts_map["k3"], "");
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2=;k3=;", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_TRUE(opts_map.find("k2") != opts_map.end());
- ASSERT_EQ(opts_map["k2"], "");
- ASSERT_TRUE(opts_map.find("k3") != opts_map.end());
- ASSERT_EQ(opts_map["k3"], "");
- // Regular nested options
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2={nk1=nv1;nk2=nv2};k3=v3", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "nk1=nv1;nk2=nv2");
- ASSERT_EQ(opts_map["k3"], "v3");
- // Multi-level nested options
- opts_map.clear();
- ASSERT_OK(
- StringToMap("k1=v1;k2={nk1=nv1;nk2={nnk1=nnk2}};"
- "k3={nk1={nnk1={nnnk1=nnnv1;nnnk2;nnnv2}}};k4=v4",
- &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "nk1=nv1;nk2={nnk1=nnk2}");
- ASSERT_EQ(opts_map["k3"], "nk1={nnk1={nnnk1=nnnv1;nnnk2;nnnv2}}");
- ASSERT_EQ(opts_map["k4"], "v4");
- // Garbage inside curly braces
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2={dfad=};k3={=};k4=v4", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "dfad=");
- ASSERT_EQ(opts_map["k3"], "=");
- ASSERT_EQ(opts_map["k4"], "v4");
- // Empty nested options
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2={};", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "");
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2={{{{}}}{}{}};", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "{{{}}}{}{}");
- // With random spaces
- opts_map.clear();
- ASSERT_OK(
- StringToMap(" k1 = v1 ; k2= {nk1=nv1; nk2={nnk1=nnk2}} ; "
- "k3={ { } }; k4= v4 ",
- &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "nk1=nv1; nk2={nnk1=nnk2}");
- ASSERT_EQ(opts_map["k3"], "{ }");
- ASSERT_EQ(opts_map["k4"], "v4");
- // Empty key
- ASSERT_NOK(StringToMap("k1=v1;k2=v2;=", &opts_map));
- ASSERT_NOK(StringToMap("=v1;k2=v2", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2v2;", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2=v2;fadfa", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2=v2;;", &opts_map));
- // Mismatch curly braces
- ASSERT_NOK(StringToMap("k1=v1;k2={;k3=v3", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={{};k3=v3", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={}};k3=v3", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={{}{}}};k3=v3", &opts_map));
- // However this is valid!
- opts_map.clear();
- ASSERT_OK(StringToMap("k1=v1;k2=};k3=v3", &opts_map));
- ASSERT_EQ(opts_map["k1"], "v1");
- ASSERT_EQ(opts_map["k2"], "}");
- ASSERT_EQ(opts_map["k3"], "v3");
- // Invalid chars after closing curly brace
- ASSERT_NOK(StringToMap("k1=v1;k2={{}}{};k3=v3", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={{}}cfda;k3=v3", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={{}} cfda;k3=v3", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={{}} cfda", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={{}}{}", &opts_map));
- ASSERT_NOK(StringToMap("k1=v1;k2={{dfdl}adfa}{}", &opts_map));
- }
- TEST_F(OptionsTest, StringToMapRandomTest) {
- std::unordered_map<std::string, std::string> opts_map;
- // Make sure segfault is not hit by semi-random strings
- std::vector<std::string> bases = {
- "a={aa={};tt={xxx={}}};c=defff",
- "a={aa={};tt={xxx={}}};c=defff;d={{}yxx{}3{xx}}",
- "abc={{}{}{}{{{}}}{{}{}{}{}{}{}{}"};
- for (const std::string& base : bases) {
- for (int rand_seed = 301; rand_seed < 401; rand_seed++) {
- Random rnd(rand_seed);
- for (int attempt = 0; attempt < 10; attempt++) {
- std::string str = base;
- // Replace random position to space
- size_t pos =
- static_cast<size_t>(rnd.Uniform(static_cast<int>(base.size())));
- str[pos] = ' ';
- Status s = StringToMap(str, &opts_map);
- ASSERT_TRUE(s.ok() || s.IsInvalidArgument());
- opts_map.clear();
- }
- }
- }
- // Random Construct a string
- std::vector<char> chars = {'{', '}', ' ', '=', ';', 'c'};
- for (int rand_seed = 301; rand_seed < 1301; rand_seed++) {
- Random rnd(rand_seed);
- int len = rnd.Uniform(30);
- std::string str;
- for (int attempt = 0; attempt < len; attempt++) {
- // Add a random character
- size_t pos =
- static_cast<size_t>(rnd.Uniform(static_cast<int>(chars.size())));
- str.append(1, chars[pos]);
- }
- Status s = StringToMap(str, &opts_map);
- ASSERT_TRUE(s.ok() || s.IsInvalidArgument());
- s = StringToMap("name=" + str, &opts_map);
- ASSERT_TRUE(s.ok() || s.IsInvalidArgument());
- opts_map.clear();
- }
- }
- TEST_F(OptionsTest, GetStringFromCompressionType) {
- std::string res;
- ASSERT_OK(GetStringFromCompressionType(&res, kNoCompression));
- ASSERT_EQ(res, "kNoCompression");
- ASSERT_OK(GetStringFromCompressionType(&res, kSnappyCompression));
- ASSERT_EQ(res, "kSnappyCompression");
- ASSERT_OK(GetStringFromCompressionType(&res, kDisableCompressionOption));
- ASSERT_EQ(res, "kDisableCompressionOption");
- ASSERT_OK(GetStringFromCompressionType(&res, kLZ4Compression));
- ASSERT_EQ(res, "kLZ4Compression");
- ASSERT_OK(GetStringFromCompressionType(&res, kZlibCompression));
- ASSERT_EQ(res, "kZlibCompression");
- ASSERT_NOK(
- GetStringFromCompressionType(&res, static_cast<CompressionType>(0x7F)));
- }
- TEST_F(OptionsTest, OnlyMutableDBOptions) {
- std::string opt_str;
- Random rnd(302);
- ConfigOptions cfg_opts;
- DBOptions db_opts;
- DBOptions mdb_opts;
- std::unordered_set<std::string> m_names;
- std::unordered_set<std::string> a_names;
- test::RandomInitDBOptions(&db_opts, &rnd);
- auto db_config = DBOptionsAsConfigurable(db_opts);
- // Get all of the DB Option names (mutable or not)
- ASSERT_OK(db_config->GetOptionNames(cfg_opts, &a_names));
- // Get only the mutable options from db_opts and set those in mdb_opts
- cfg_opts.mutable_options_only = true;
- // Get only the Mutable DB Option names
- ASSERT_OK(db_config->GetOptionNames(cfg_opts, &m_names));
- ASSERT_OK(GetStringFromDBOptions(cfg_opts, db_opts, &opt_str));
- ASSERT_OK(GetDBOptionsFromString(cfg_opts, mdb_opts, opt_str, &mdb_opts));
- std::string mismatch;
- // Comparing only the mutable options, the two are equivalent
- auto mdb_config = DBOptionsAsConfigurable(mdb_opts);
- ASSERT_TRUE(mdb_config->AreEquivalent(cfg_opts, db_config.get(), &mismatch));
- ASSERT_TRUE(db_config->AreEquivalent(cfg_opts, mdb_config.get(), &mismatch));
- ASSERT_GT(a_names.size(), m_names.size());
- for (const auto& n : m_names) {
- std::string m, d;
- ASSERT_OK(mdb_config->GetOption(cfg_opts, n, &m));
- ASSERT_OK(db_config->GetOption(cfg_opts, n, &d));
- ASSERT_EQ(m, d);
- }
- cfg_opts.mutable_options_only = false;
- // Comparing all of the options, the two are not equivalent
- ASSERT_FALSE(mdb_config->AreEquivalent(cfg_opts, db_config.get(), &mismatch));
- ASSERT_FALSE(db_config->AreEquivalent(cfg_opts, mdb_config.get(), &mismatch));
- // Make sure there are only mutable options being configured
- ASSERT_OK(GetDBOptionsFromString(cfg_opts, DBOptions(), opt_str, &db_opts));
- }
- TEST_F(OptionsTest, OnlyMutableCFOptions) {
- std::string opt_str;
- Random rnd(302);
- ConfigOptions cfg_opts;
- DBOptions db_opts;
- ColumnFamilyOptions mcf_opts;
- ColumnFamilyOptions cf_opts;
- std::unordered_set<std::string> m_names;
- std::unordered_set<std::string> a_names;
- test::RandomInitCFOptions(&cf_opts, db_opts, &rnd);
- cf_opts.comparator = ReverseBytewiseComparator();
- auto cf_config = CFOptionsAsConfigurable(cf_opts);
- // Get all of the CF Option names (mutable or not)
- ASSERT_OK(cf_config->GetOptionNames(cfg_opts, &a_names));
- // Get only the mutable options from cf_opts and set those in mcf_opts
- cfg_opts.mutable_options_only = true;
- // Get only the Mutable CF Option names
- ASSERT_OK(cf_config->GetOptionNames(cfg_opts, &m_names));
- ASSERT_OK(GetStringFromColumnFamilyOptions(cfg_opts, cf_opts, &opt_str));
- ASSERT_OK(
- GetColumnFamilyOptionsFromString(cfg_opts, mcf_opts, opt_str, &mcf_opts));
- std::string mismatch;
- auto mcf_config = CFOptionsAsConfigurable(mcf_opts);
- // Comparing only the mutable options, the two are equivalent
- ASSERT_TRUE(mcf_config->AreEquivalent(cfg_opts, cf_config.get(), &mismatch));
- ASSERT_TRUE(cf_config->AreEquivalent(cfg_opts, mcf_config.get(), &mismatch));
- ASSERT_GT(a_names.size(), m_names.size());
- for (const auto& n : m_names) {
- std::string m, d;
- ASSERT_OK(mcf_config->GetOption(cfg_opts, n, &m));
- ASSERT_OK(cf_config->GetOption(cfg_opts, n, &d));
- ASSERT_EQ(m, d);
- }
- cfg_opts.mutable_options_only = false;
- // Comparing all of the options, the two are not equivalent
- ASSERT_FALSE(mcf_config->AreEquivalent(cfg_opts, cf_config.get(), &mismatch));
- ASSERT_FALSE(cf_config->AreEquivalent(cfg_opts, mcf_config.get(), &mismatch));
- delete cf_opts.compaction_filter;
- // Make sure the options string contains only mutable options
- ASSERT_OK(GetColumnFamilyOptionsFromString(cfg_opts, ColumnFamilyOptions(),
- opt_str, &cf_opts));
- delete cf_opts.compaction_filter;
- }
- TEST_F(OptionsTest, SstPartitionerTest) {
- ConfigOptions cfg_opts;
- ColumnFamilyOptions cf_opts, new_opt;
- std::string opts_str, mismatch;
- ASSERT_OK(SstPartitionerFactory::CreateFromString(
- cfg_opts, SstPartitionerFixedPrefixFactory::kClassName(),
- &cf_opts.sst_partitioner_factory));
- ASSERT_NE(cf_opts.sst_partitioner_factory, nullptr);
- ASSERT_STREQ(cf_opts.sst_partitioner_factory->Name(),
- SstPartitionerFixedPrefixFactory::kClassName());
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- cfg_opts, ColumnFamilyOptions(),
- std::string("sst_partitioner_factory={id=") +
- SstPartitionerFixedPrefixFactory::kClassName() + "; unknown=10;}",
- &cf_opts));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- cfg_opts, ColumnFamilyOptions(),
- std::string("sst_partitioner_factory={id=") +
- SstPartitionerFixedPrefixFactory::kClassName() + "; length=10;}",
- &cf_opts));
- ASSERT_NE(cf_opts.sst_partitioner_factory, nullptr);
- ASSERT_STREQ(cf_opts.sst_partitioner_factory->Name(),
- SstPartitionerFixedPrefixFactory::kClassName());
- ASSERT_OK(GetStringFromColumnFamilyOptions(cfg_opts, cf_opts, &opts_str));
- ASSERT_OK(
- GetColumnFamilyOptionsFromString(cfg_opts, cf_opts, opts_str, &new_opt));
- ASSERT_NE(new_opt.sst_partitioner_factory, nullptr);
- ASSERT_STREQ(new_opt.sst_partitioner_factory->Name(),
- SstPartitionerFixedPrefixFactory::kClassName());
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(cfg_opts, cf_opts, new_opt));
- ASSERT_TRUE(cf_opts.sst_partitioner_factory->AreEquivalent(
- cfg_opts, new_opt.sst_partitioner_factory.get(), &mismatch));
- }
- TEST_F(OptionsTest, FileChecksumGenFactoryTest) {
- ConfigOptions cfg_opts;
- DBOptions db_opts, new_opt;
- std::string opts_str, mismatch;
- auto factory = GetFileChecksumGenCrc32cFactory();
- cfg_opts.ignore_unsupported_options = false;
- ASSERT_OK(GetStringFromDBOptions(cfg_opts, db_opts, &opts_str));
- ASSERT_OK(GetDBOptionsFromString(cfg_opts, db_opts, opts_str, &new_opt));
- ASSERT_NE(factory, nullptr);
- ASSERT_OK(FileChecksumGenFactory::CreateFromString(
- cfg_opts, factory->Name(), &db_opts.file_checksum_gen_factory));
- ASSERT_NE(db_opts.file_checksum_gen_factory, nullptr);
- ASSERT_STREQ(db_opts.file_checksum_gen_factory->Name(), factory->Name());
- ASSERT_NOK(GetDBOptionsFromString(
- cfg_opts, DBOptions(), "file_checksum_gen_factory=unknown", &db_opts));
- ASSERT_OK(GetDBOptionsFromString(
- cfg_opts, DBOptions(),
- std::string("file_checksum_gen_factory=") + factory->Name(), &db_opts));
- ASSERT_NE(db_opts.file_checksum_gen_factory, nullptr);
- ASSERT_STREQ(db_opts.file_checksum_gen_factory->Name(), factory->Name());
- ASSERT_OK(GetStringFromDBOptions(cfg_opts, db_opts, &opts_str));
- ASSERT_OK(GetDBOptionsFromString(cfg_opts, db_opts, opts_str, &new_opt));
- ASSERT_NE(new_opt.file_checksum_gen_factory, nullptr);
- ASSERT_STREQ(new_opt.file_checksum_gen_factory->Name(), factory->Name());
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(cfg_opts, db_opts, new_opt));
- ASSERT_TRUE(factory->AreEquivalent(
- cfg_opts, new_opt.file_checksum_gen_factory.get(), &mismatch));
- ASSERT_TRUE(db_opts.file_checksum_gen_factory->AreEquivalent(
- cfg_opts, new_opt.file_checksum_gen_factory.get(), &mismatch));
- }
- class TestTablePropertiesCollectorFactory
- : public TablePropertiesCollectorFactory {
- private:
- std::string id_;
- public:
- explicit TestTablePropertiesCollectorFactory(const std::string& id)
- : id_(id) {}
- TablePropertiesCollector* CreateTablePropertiesCollector(
- TablePropertiesCollectorFactory::Context /*context*/) override {
- return nullptr;
- }
- static const char* kClassName() { return "TestCollector"; }
- const char* Name() const override { return kClassName(); }
- std::string GetId() const override {
- return std::string(kClassName()) + ":" + id_;
- }
- };
- TEST_F(OptionsTest, OptionTablePropertiesTest) {
- ConfigOptions cfg_opts;
- ColumnFamilyOptions orig, copy;
- orig.table_properties_collector_factories.push_back(
- std::make_shared<TestTablePropertiesCollectorFactory>("1"));
- orig.table_properties_collector_factories.push_back(
- std::make_shared<TestTablePropertiesCollectorFactory>("2"));
- // Push two TablePropertiesCollectorFactories then create a new
- // ColumnFamilyOptions based on those settings. The copy should
- // have no properties but still match the original
- std::string opts_str;
- ASSERT_OK(GetStringFromColumnFamilyOptions(cfg_opts, orig, &opts_str));
- ASSERT_OK(GetColumnFamilyOptionsFromString(cfg_opts, orig, opts_str, ©));
- ASSERT_EQ(copy.table_properties_collector_factories.size(), 0);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(cfg_opts, orig, copy));
- // Now register a TablePropertiesCollectorFactory
- // Repeat the experiment. The copy should have the same
- // properties as the original
- cfg_opts.registry->AddLibrary("collector")
- ->AddFactory<TablePropertiesCollectorFactory>(
- ObjectLibrary::PatternEntry(
- TestTablePropertiesCollectorFactory::kClassName(), false)
- .AddSeparator(":"),
- [](const std::string& name,
- std::unique_ptr<TablePropertiesCollectorFactory>* guard,
- std::string* /* errmsg */) {
- std::string id = name.substr(
- strlen(TestTablePropertiesCollectorFactory::kClassName()) + 1);
- guard->reset(new TestTablePropertiesCollectorFactory(id));
- return guard->get();
- });
- ASSERT_OK(GetColumnFamilyOptionsFromString(cfg_opts, orig, opts_str, ©));
- ASSERT_EQ(copy.table_properties_collector_factories.size(), 2);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(cfg_opts, orig, copy));
- }
- TEST_F(OptionsTest, ConvertOptionsTest) {
- LevelDBOptions leveldb_opt;
- Options converted_opt = ConvertOptions(leveldb_opt);
- ASSERT_EQ(converted_opt.create_if_missing, leveldb_opt.create_if_missing);
- ASSERT_EQ(converted_opt.error_if_exists, leveldb_opt.error_if_exists);
- ASSERT_EQ(converted_opt.paranoid_checks, leveldb_opt.paranoid_checks);
- ASSERT_EQ(converted_opt.env, leveldb_opt.env);
- ASSERT_EQ(converted_opt.info_log.get(), leveldb_opt.info_log);
- ASSERT_EQ(converted_opt.write_buffer_size, leveldb_opt.write_buffer_size);
- ASSERT_EQ(converted_opt.max_open_files, leveldb_opt.max_open_files);
- ASSERT_EQ(converted_opt.compression, leveldb_opt.compression);
- std::shared_ptr<TableFactory> table_factory = converted_opt.table_factory;
- const auto table_opt = table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_NE(table_opt, nullptr);
- ASSERT_EQ(table_opt->block_cache->GetCapacity(), 32UL << 20);
- ASSERT_EQ(table_opt->block_size, leveldb_opt.block_size);
- ASSERT_EQ(table_opt->block_restart_interval,
- leveldb_opt.block_restart_interval);
- ASSERT_EQ(table_opt->filter_policy.get(), leveldb_opt.filter_policy);
- }
- class TestEventListener : public EventListener {
- private:
- std::string id_;
- public:
- explicit TestEventListener(const std::string& id) : id_("Test" + id) {}
- const char* Name() const override { return id_.c_str(); }
- };
- static std::unordered_map<std::string, OptionTypeInfo>
- test_listener_option_info = {
- {"s",
- {0, OptionType::kString, OptionVerificationType::kNormal,
- OptionTypeFlags::kNone}},
- };
- class TestConfigEventListener : public TestEventListener {
- private:
- std::string s_;
- public:
- explicit TestConfigEventListener(const std::string& id)
- : TestEventListener("Config" + id) {
- s_ = id;
- RegisterOptions("Test", &s_, &test_listener_option_info);
- }
- };
- static int RegisterTestEventListener(ObjectLibrary& library,
- const std::string& arg) {
- library.AddFactory<EventListener>(
- "Test" + arg,
- [](const std::string& name, std::unique_ptr<EventListener>* guard,
- std::string* /* errmsg */) {
- guard->reset(new TestEventListener(name.substr(4)));
- return guard->get();
- });
- library.AddFactory<EventListener>(
- "TestConfig" + arg,
- [](const std::string& name, std::unique_ptr<EventListener>* guard,
- std::string* /* errmsg */) {
- guard->reset(new TestConfigEventListener(name.substr(10)));
- return guard->get();
- });
- return 1;
- }
- TEST_F(OptionsTest, OptionsListenerTest) {
- DBOptions orig, copy;
- orig.listeners.push_back(std::make_shared<TestEventListener>("1"));
- orig.listeners.push_back(std::make_shared<TestEventListener>("2"));
- orig.listeners.push_back(std::make_shared<TestEventListener>(""));
- orig.listeners.push_back(std::make_shared<TestConfigEventListener>("1"));
- orig.listeners.push_back(std::make_shared<TestConfigEventListener>("2"));
- orig.listeners.push_back(std::make_shared<TestConfigEventListener>(""));
- ConfigOptions config_opts(orig);
- config_opts.registry->AddLibrary("listener", RegisterTestEventListener, "1");
- std::string opts_str;
- ASSERT_OK(GetStringFromDBOptions(config_opts, orig, &opts_str));
- ASSERT_OK(GetDBOptionsFromString(config_opts, orig, opts_str, ©));
- ASSERT_OK(GetStringFromDBOptions(config_opts, copy, &opts_str));
- ASSERT_EQ(
- copy.listeners.size(),
- 2); // The Test{Config}1 Listeners could be loaded but not the others
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(config_opts, orig, copy));
- }
- const static std::string kCustomEnvName = "Custom";
- const static std::string kCustomEnvProp = "env=" + kCustomEnvName;
- static int RegisterCustomEnv(ObjectLibrary& library, const std::string& arg) {
- library.AddFactory<Env>(
- arg, [](const std::string& /*name*/, std::unique_ptr<Env>* /*env_guard*/,
- std::string* /* errmsg */) {
- static CustomEnv env(Env::Default());
- return &env;
- });
- return 1;
- }
- // This test suite tests the old APIs into the Configure options methods.
- // Once those APIs are officially deprecated, this test suite can be deleted.
- class OptionsOldApiTest : public testing::Test {};
- TEST_F(OptionsOldApiTest, GetOptionsFromMapTest) {
- std::unordered_map<std::string, std::string> cf_options_map = {
- {"write_buffer_size", "1"},
- {"max_write_buffer_number", "2"},
- {"min_write_buffer_number_to_merge", "3"},
- {"max_write_buffer_number_to_maintain", "99"},
- {"max_write_buffer_size_to_maintain", "-99999"},
- {"compression", "kSnappyCompression"},
- {"compression_per_level",
- "kNoCompression:"
- "kSnappyCompression:"
- "kZlibCompression:"
- "kBZip2Compression:"
- "kLZ4Compression:"
- "kLZ4HCCompression:"
- "kXpressCompression:"
- "kZSTD"},
- {"bottommost_compression", "kLZ4Compression"},
- {"bottommost_compression_opts", "5:6:7:8:9:true"},
- {"compression_opts", "4:5:6:7:8:9:true:10:false"},
- {"num_levels", "8"},
- {"level0_file_num_compaction_trigger", "8"},
- {"level0_slowdown_writes_trigger", "9"},
- {"level0_stop_writes_trigger", "10"},
- {"target_file_size_base", "12"},
- {"target_file_size_multiplier", "13"},
- {"max_bytes_for_level_base", "14"},
- {"level_compaction_dynamic_level_bytes", "true"},
- {"level_compaction_dynamic_file_size", "true"},
- {"max_bytes_for_level_multiplier", "15.0"},
- {"max_bytes_for_level_multiplier_additional", "16:17:18"},
- {"max_compaction_bytes", "21"},
- {"soft_rate_limit", "1.1"},
- {"hard_rate_limit", "2.1"},
- {"rate_limit_delay_max_milliseconds", "100"},
- {"hard_pending_compaction_bytes_limit", "211"},
- {"arena_block_size", "22"},
- {"disable_auto_compactions", "true"},
- {"compaction_style", "kCompactionStyleLevel"},
- {"compaction_pri", "kOldestSmallestSeqFirst"},
- {"verify_checksums_in_compaction", "false"},
- {"compaction_options_fifo",
- "{allow_compaction=true;max_table_files_size=11002244;"
- "file_temperature_age_thresholds={{temperature=kCold;age=12345}}}"},
- {"max_sequential_skip_in_iterations", "24"},
- {"inplace_update_support", "true"},
- {"report_bg_io_stats", "true"},
- {"compaction_measure_io_stats", "false"},
- {"purge_redundant_kvs_while_flush", "false"},
- {"inplace_update_num_locks", "25"},
- {"memtable_prefix_bloom_size_ratio", "0.26"},
- {"memtable_whole_key_filtering", "true"},
- {"memtable_huge_page_size", "28"},
- {"bloom_locality", "29"},
- {"max_successive_merges", "30"},
- {"strict_max_successive_merges", "true"},
- {"min_partial_merge_operands", "31"},
- {"prefix_extractor", "fixed:31"},
- {"experimental_mempurge_threshold", "0.003"},
- {"optimize_filters_for_hits", "true"},
- {"enable_blob_files", "true"},
- {"min_blob_size", "1K"},
- {"blob_file_size", "1G"},
- {"blob_compression_type", "kZSTD"},
- {"enable_blob_garbage_collection", "true"},
- {"blob_garbage_collection_age_cutoff", "0.5"},
- {"blob_garbage_collection_force_threshold", "0.75"},
- {"blob_compaction_readahead_size", "256K"},
- {"blob_file_starting_level", "1"},
- {"prepopulate_blob_cache", "kDisable"},
- {"last_level_temperature", "kWarm"},
- {"default_write_temperature", "kCold"},
- {"default_temperature", "kHot"},
- {"persist_user_defined_timestamps", "true"},
- {"memtable_max_range_deletions", "0"},
- };
- std::unordered_map<std::string, std::string> db_options_map = {
- {"create_if_missing", "false"},
- {"create_missing_column_families", "true"},
- {"error_if_exists", "false"},
- {"paranoid_checks", "true"},
- {"track_and_verify_wals_in_manifest", "true"},
- {"track_and_verify_wals", "true"},
- {"verify_sst_unique_id_in_manifest", "true"},
- {"max_open_files", "32"},
- {"max_total_wal_size", "33"},
- {"use_fsync", "true"},
- {"db_log_dir", "/db_log_dir"},
- {"wal_dir", "/wal_dir"},
- {"delete_obsolete_files_period_micros", "34"},
- {"max_background_compactions", "35"},
- {"max_background_flushes", "36"},
- {"max_log_file_size", "37"},
- {"log_file_time_to_roll", "38"},
- {"keep_log_file_num", "39"},
- {"recycle_log_file_num", "5"},
- {"max_manifest_file_size", "40"},
- {"table_cache_numshardbits", "41"},
- {"WAL_ttl_seconds", "43"},
- {"WAL_size_limit_MB", "44"},
- {"manifest_preallocation_size", "45"},
- {"allow_mmap_reads", "true"},
- {"allow_mmap_writes", "false"},
- {"use_direct_reads", "false"},
- {"use_direct_io_for_flush_and_compaction", "false"},
- {"is_fd_close_on_exec", "true"},
- {"skip_log_error_on_recovery", "false"},
- {"stats_dump_period_sec", "46"},
- {"stats_persist_period_sec", "57"},
- {"persist_stats_to_disk", "false"},
- {"stats_history_buffer_size", "69"},
- {"advise_random_on_open", "true"},
- {"use_adaptive_mutex", "false"},
- {"compaction_readahead_size", "100"},
- {"writable_file_max_buffer_size", "314159"},
- {"bytes_per_sync", "47"},
- {"wal_bytes_per_sync", "48"},
- {"strict_bytes_per_sync", "true"},
- {"preserve_deletes", "false"},
- };
- ColumnFamilyOptions base_cf_opt;
- ColumnFamilyOptions new_cf_opt;
- ConfigOptions cf_config_options;
- cf_config_options.ignore_unknown_options = false;
- cf_config_options.input_strings_escaped = false;
- ASSERT_OK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 1U);
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 2);
- ASSERT_EQ(new_cf_opt.min_write_buffer_number_to_merge, 3);
- ASSERT_EQ(new_cf_opt.max_write_buffer_size_to_maintain, -99999);
- ASSERT_EQ(new_cf_opt.compression, kSnappyCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level.size(), 8U);
- ASSERT_EQ(new_cf_opt.compression_per_level[0], kNoCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[1], kSnappyCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[2], kZlibCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[3], kBZip2Compression);
- ASSERT_EQ(new_cf_opt.compression_per_level[4], kLZ4Compression);
- ASSERT_EQ(new_cf_opt.compression_per_level[5], kLZ4HCCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[6], kXpressCompression);
- ASSERT_EQ(new_cf_opt.compression_per_level[7], kZSTD);
- ASSERT_EQ(new_cf_opt.compression_opts.window_bits, 4);
- ASSERT_EQ(new_cf_opt.compression_opts.level, 5);
- ASSERT_EQ(new_cf_opt.compression_opts.strategy, 6);
- ASSERT_EQ(new_cf_opt.compression_opts.max_dict_bytes, 7u);
- ASSERT_EQ(new_cf_opt.compression_opts.zstd_max_train_bytes, 8u);
- ASSERT_EQ(new_cf_opt.compression_opts.parallel_threads, 9u);
- ASSERT_EQ(new_cf_opt.compression_opts.enabled, true);
- ASSERT_EQ(new_cf_opt.compression_opts.max_dict_buffer_bytes, 10u);
- ASSERT_EQ(new_cf_opt.compression_opts.use_zstd_dict_trainer, false);
- ASSERT_EQ(new_cf_opt.bottommost_compression, kLZ4Compression);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.window_bits, 5);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.level, 6);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.strategy, 7);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.max_dict_bytes, 8u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.zstd_max_train_bytes, 9u);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.parallel_threads,
- CompressionOptions().parallel_threads);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.enabled, true);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.max_dict_buffer_bytes,
- CompressionOptions().max_dict_buffer_bytes);
- ASSERT_EQ(new_cf_opt.bottommost_compression_opts.use_zstd_dict_trainer,
- CompressionOptions().use_zstd_dict_trainer);
- ASSERT_EQ(new_cf_opt.num_levels, 8);
- ASSERT_EQ(new_cf_opt.level0_file_num_compaction_trigger, 8);
- ASSERT_EQ(new_cf_opt.level0_slowdown_writes_trigger, 9);
- ASSERT_EQ(new_cf_opt.level0_stop_writes_trigger, 10);
- ASSERT_EQ(new_cf_opt.target_file_size_base, static_cast<uint64_t>(12));
- ASSERT_EQ(new_cf_opt.target_file_size_multiplier, 13);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_base, 14U);
- ASSERT_EQ(new_cf_opt.level_compaction_dynamic_level_bytes, true);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier, 15.0);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional.size(), 3U);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional[0], 16);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional[1], 17);
- ASSERT_EQ(new_cf_opt.max_bytes_for_level_multiplier_additional[2], 18);
- ASSERT_EQ(new_cf_opt.max_compaction_bytes, 21);
- ASSERT_EQ(new_cf_opt.hard_pending_compaction_bytes_limit, 211);
- ASSERT_EQ(new_cf_opt.arena_block_size, 22U);
- ASSERT_EQ(new_cf_opt.disable_auto_compactions, true);
- ASSERT_EQ(new_cf_opt.compaction_style, kCompactionStyleLevel);
- ASSERT_EQ(new_cf_opt.compaction_pri, kOldestSmallestSeqFirst);
- ASSERT_EQ(new_cf_opt.compaction_options_fifo.max_table_files_size,
- static_cast<uint64_t>(11002244));
- ASSERT_EQ(new_cf_opt.compaction_options_fifo.allow_compaction, true);
- ASSERT_EQ(
- new_cf_opt.compaction_options_fifo.file_temperature_age_thresholds.size(),
- 1);
- ASSERT_EQ(
- new_cf_opt.compaction_options_fifo.file_temperature_age_thresholds[0]
- .temperature,
- Temperature::kCold);
- ASSERT_EQ(
- new_cf_opt.compaction_options_fifo.file_temperature_age_thresholds[0].age,
- 12345);
- ASSERT_EQ(new_cf_opt.max_sequential_skip_in_iterations,
- static_cast<uint64_t>(24));
- ASSERT_EQ(new_cf_opt.inplace_update_support, true);
- ASSERT_EQ(new_cf_opt.inplace_update_num_locks, 25U);
- ASSERT_EQ(new_cf_opt.memtable_prefix_bloom_size_ratio, 0.26);
- ASSERT_EQ(new_cf_opt.memtable_whole_key_filtering, true);
- ASSERT_EQ(new_cf_opt.memtable_huge_page_size, 28U);
- ASSERT_EQ(new_cf_opt.bloom_locality, 29U);
- ASSERT_EQ(new_cf_opt.max_successive_merges, 30U);
- ASSERT_EQ(new_cf_opt.strict_max_successive_merges, true);
- ASSERT_TRUE(new_cf_opt.prefix_extractor != nullptr);
- ASSERT_EQ(new_cf_opt.optimize_filters_for_hits, true);
- ASSERT_EQ(new_cf_opt.prefix_extractor->AsString(), "rocksdb.FixedPrefix.31");
- ASSERT_EQ(new_cf_opt.experimental_mempurge_threshold, 0.003);
- ASSERT_EQ(new_cf_opt.enable_blob_files, true);
- ASSERT_EQ(new_cf_opt.min_blob_size, 1ULL << 10);
- ASSERT_EQ(new_cf_opt.blob_file_size, 1ULL << 30);
- ASSERT_EQ(new_cf_opt.blob_compression_type, kZSTD);
- ASSERT_EQ(new_cf_opt.enable_blob_garbage_collection, true);
- ASSERT_EQ(new_cf_opt.blob_garbage_collection_age_cutoff, 0.5);
- ASSERT_EQ(new_cf_opt.blob_garbage_collection_force_threshold, 0.75);
- ASSERT_EQ(new_cf_opt.blob_compaction_readahead_size, 262144);
- ASSERT_EQ(new_cf_opt.blob_file_starting_level, 1);
- ASSERT_EQ(new_cf_opt.prepopulate_blob_cache, PrepopulateBlobCache::kDisable);
- ASSERT_EQ(new_cf_opt.last_level_temperature, Temperature::kWarm);
- ASSERT_EQ(new_cf_opt.default_write_temperature, Temperature::kCold);
- ASSERT_EQ(new_cf_opt.default_temperature, Temperature::kHot);
- ASSERT_EQ(new_cf_opt.persist_user_defined_timestamps, true);
- ASSERT_EQ(new_cf_opt.memtable_max_range_deletions, 0);
- cf_options_map["write_buffer_size"] = "hello";
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- ConfigOptions exact, loose;
- exact.sanity_level = ConfigOptions::kSanityLevelExactMatch;
- loose.sanity_level = ConfigOptions::kSanityLevelLooselyCompatible;
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- cf_options_map["write_buffer_size"] = "1";
- ASSERT_OK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- cf_options_map["unknown_option"] = "1";
- ASSERT_NOK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- cf_config_options.input_strings_escaped = false;
- cf_config_options.ignore_unknown_options = true;
- ASSERT_OK(GetColumnFamilyOptionsFromMap(cf_config_options, base_cf_opt,
- cf_options_map, &new_cf_opt));
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- loose, base_cf_opt, new_cf_opt, nullptr /* new_opt_map */));
- ASSERT_NOK(RocksDBOptionsParser::VerifyCFOptions(
- exact /* default for VerifyCFOptions */, base_cf_opt, new_cf_opt,
- nullptr));
- DBOptions base_db_opt;
- DBOptions new_db_opt;
- ConfigOptions db_config_options(base_db_opt);
- db_config_options.input_strings_escaped = false;
- db_config_options.ignore_unknown_options = false;
- ASSERT_OK(GetDBOptionsFromMap(db_config_options, base_db_opt, db_options_map,
- &new_db_opt));
- ASSERT_EQ(new_db_opt.create_if_missing, false);
- ASSERT_EQ(new_db_opt.create_missing_column_families, true);
- ASSERT_EQ(new_db_opt.error_if_exists, false);
- ASSERT_EQ(new_db_opt.paranoid_checks, true);
- ASSERT_EQ(new_db_opt.track_and_verify_wals_in_manifest, true);
- ASSERT_EQ(new_db_opt.track_and_verify_wals, true);
- ASSERT_EQ(new_db_opt.max_open_files, 32);
- ASSERT_EQ(new_db_opt.max_total_wal_size, static_cast<uint64_t>(33));
- ASSERT_EQ(new_db_opt.use_fsync, true);
- ASSERT_EQ(new_db_opt.db_log_dir, "/db_log_dir");
- ASSERT_EQ(new_db_opt.wal_dir, "/wal_dir");
- ASSERT_EQ(new_db_opt.delete_obsolete_files_period_micros,
- static_cast<uint64_t>(34));
- ASSERT_EQ(new_db_opt.max_background_compactions, 35);
- ASSERT_EQ(new_db_opt.max_background_flushes, 36);
- ASSERT_EQ(new_db_opt.max_log_file_size, 37U);
- ASSERT_EQ(new_db_opt.log_file_time_to_roll, 38U);
- ASSERT_EQ(new_db_opt.keep_log_file_num, 39U);
- ASSERT_EQ(new_db_opt.recycle_log_file_num, 5U);
- ASSERT_EQ(new_db_opt.max_manifest_file_size, static_cast<uint64_t>(40));
- ASSERT_EQ(new_db_opt.table_cache_numshardbits, 41);
- ASSERT_EQ(new_db_opt.WAL_ttl_seconds, static_cast<uint64_t>(43));
- ASSERT_EQ(new_db_opt.WAL_size_limit_MB, static_cast<uint64_t>(44));
- ASSERT_EQ(new_db_opt.manifest_preallocation_size, 45U);
- ASSERT_EQ(new_db_opt.allow_mmap_reads, true);
- ASSERT_EQ(new_db_opt.allow_mmap_writes, false);
- ASSERT_EQ(new_db_opt.use_direct_reads, false);
- ASSERT_EQ(new_db_opt.use_direct_io_for_flush_and_compaction, false);
- ASSERT_EQ(new_db_opt.is_fd_close_on_exec, true);
- ASSERT_EQ(new_db_opt.stats_dump_period_sec, 46U);
- ASSERT_EQ(new_db_opt.stats_persist_period_sec, 57U);
- ASSERT_EQ(new_db_opt.persist_stats_to_disk, false);
- ASSERT_EQ(new_db_opt.stats_history_buffer_size, 69U);
- ASSERT_EQ(new_db_opt.advise_random_on_open, true);
- ASSERT_EQ(new_db_opt.use_adaptive_mutex, false);
- ASSERT_EQ(new_db_opt.compaction_readahead_size, 100);
- ASSERT_EQ(new_db_opt.writable_file_max_buffer_size, 314159);
- ASSERT_EQ(new_db_opt.bytes_per_sync, static_cast<uint64_t>(47));
- ASSERT_EQ(new_db_opt.wal_bytes_per_sync, static_cast<uint64_t>(48));
- ASSERT_EQ(new_db_opt.strict_bytes_per_sync, true);
- db_options_map["max_open_files"] = "hello";
- ASSERT_NOK(GetDBOptionsFromMap(db_config_options, base_db_opt, db_options_map,
- &new_db_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(loose, base_db_opt, new_db_opt));
- // unknow options should fail parsing without ignore_unknown_options = true
- db_options_map["unknown_db_option"] = "1";
- ASSERT_NOK(GetDBOptionsFromMap(db_config_options, base_db_opt, db_options_map,
- &new_db_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- db_config_options.input_strings_escaped = false;
- db_config_options.ignore_unknown_options = true;
- ASSERT_OK(GetDBOptionsFromMap(db_config_options, base_db_opt, db_options_map,
- &new_db_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(loose, base_db_opt, new_db_opt));
- ASSERT_NOK(
- RocksDBOptionsParser::VerifyDBOptions(exact, base_db_opt, new_db_opt));
- }
- TEST_F(OptionsOldApiTest, GetColumnFamilyOptionsFromStringTest) {
- ColumnFamilyOptions base_cf_opt;
- ColumnFamilyOptions new_cf_opt;
- base_cf_opt.table_factory.reset();
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- config_options.ignore_unknown_options = false;
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt, "",
- &new_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=5", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 5U);
- ASSERT_TRUE(new_cf_opt.table_factory == nullptr);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=6;", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 6U);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, " write_buffer_size = 7 ", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 7U);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, " write_buffer_size = 8 ; ", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 8U);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=9;max_write_buffer_number=10", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 9U);
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 10);
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=11; max_write_buffer_number = 12 ;", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 11U);
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 12);
- // Wrong name "max_write_buffer_number_"
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=13;max_write_buffer_number_=14;", &new_cf_opt));
- ConfigOptions exact;
- exact.sanity_level = ConfigOptions::kSanityLevelExactMatch;
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- // Comparator from object registry
- std::string kCompName = "reverse_comp";
- ObjectLibrary::Default()->AddFactory<const Comparator>(
- kCompName,
- [](const std::string& /*name*/,
- std::unique_ptr<const Comparator>* /*guard*/,
- std::string* /* errmsg */) { return ReverseBytewiseComparator(); });
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "comparator=" + kCompName + ";",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.comparator, ReverseBytewiseComparator());
- // MergeOperator from object registry
- std::unique_ptr<BytesXOROperator> bxo(new BytesXOROperator());
- std::string kMoName = bxo->Name();
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "merge_operator=" + kMoName + ";",
- &new_cf_opt));
- ASSERT_EQ(kMoName, std::string(new_cf_opt.merge_operator->Name()));
- // Wrong key/value pair
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=13;max_write_buffer_number;", &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- // Error Paring value
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=13;max_write_buffer_number=;", &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- // Missing option name
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=13; =100;", &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- const uint64_t kilo = 1024UL;
- const uint64_t mega = 1024 * kilo;
- const uint64_t giga = 1024 * mega;
- const uint64_t tera = 1024 * giga;
- // Units (k)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "max_write_buffer_number=15K", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 15 * kilo);
- // Units (m)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "max_write_buffer_number=16m;inplace_update_num_locks=17M", &new_cf_opt));
- ASSERT_EQ(new_cf_opt.max_write_buffer_number, 16 * mega);
- ASSERT_EQ(new_cf_opt.inplace_update_num_locks, 17u * mega);
- // Units (g)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=18g;prefix_extractor=capped:8;"
- "arena_block_size=19G",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 18 * giga);
- ASSERT_EQ(new_cf_opt.arena_block_size, 19 * giga);
- ASSERT_TRUE(new_cf_opt.prefix_extractor.get() != nullptr);
- ASSERT_EQ(new_cf_opt.prefix_extractor->AsString(), "rocksdb.CappedPrefix.8");
- // Units (t)
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt, "write_buffer_size=20t;arena_block_size=21T",
- &new_cf_opt));
- ASSERT_EQ(new_cf_opt.write_buffer_size, 20 * tera);
- ASSERT_EQ(new_cf_opt.arena_block_size, 21 * tera);
- // Nested block based table options
- // Empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={};arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- // Non-empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_cache=1M;block_size=4;};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- // Last one
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_cache=1M;block_size=4;}",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- // Mismatch curly braces
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={{{block_size=4;};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- // Unexpected chars after closing curly brace
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_size=4;}};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_size=4;}xdfa;"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_size=4;}xdfa",
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- // Invalid block based table option
- ASSERT_NOK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={xx_block_size=4;}",
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "optimize_filters_for_hits=true",
- &new_cf_opt));
- ASSERT_OK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "optimize_filters_for_hits=false",
- &new_cf_opt));
- ASSERT_NOK(GetColumnFamilyOptionsFromString(config_options, base_cf_opt,
- "optimize_filters_for_hits=junk",
- &new_cf_opt));
- ASSERT_OK(
- RocksDBOptionsParser::VerifyCFOptions(exact, base_cf_opt, new_cf_opt));
- // Nested plain table options
- // Empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "plain_table_factory={};arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- ASSERT_EQ(std::string(new_cf_opt.table_factory->Name()), "PlainTable");
- // Non-empty
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "plain_table_factory={user_key_len=66;bloom_bits_per_key=20;};"
- "arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.table_factory != nullptr);
- ASSERT_EQ(std::string(new_cf_opt.table_factory->Name()), "PlainTable");
- // memtable factory
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "memtable=skip_list:10;arena_block_size=1024",
- &new_cf_opt));
- ASSERT_TRUE(new_cf_opt.memtable_factory != nullptr);
- ASSERT_TRUE(new_cf_opt.memtable_factory->IsInstanceOf("SkipListFactory"));
- // blob cache
- ASSERT_OK(GetColumnFamilyOptionsFromString(
- config_options, base_cf_opt,
- "blob_cache={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;high_pri_pool_ratio=0.5;};",
- &new_cf_opt));
- ASSERT_NE(new_cf_opt.blob_cache, nullptr);
- ASSERT_EQ(new_cf_opt.blob_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(static_cast<ShardedCacheBase*>(new_cf_opt.blob_cache.get())
- ->GetNumShardBits(),
- 4);
- ASSERT_EQ(new_cf_opt.blob_cache->HasStrictCapacityLimit(), true);
- ASSERT_EQ(static_cast<LRUCache*>(new_cf_opt.blob_cache.get())
- ->GetHighPriPoolRatio(),
- 0.5);
- }
- TEST_F(OptionsTest, SliceTransformCreateFromString) {
- std::shared_ptr<const SliceTransform> transform = nullptr;
- ConfigOptions config_options;
- config_options.ignore_unsupported_options = false;
- config_options.ignore_unknown_options = false;
- ASSERT_OK(
- SliceTransform::CreateFromString(config_options, "fixed:31", &transform));
- ASSERT_NE(transform, nullptr);
- ASSERT_FALSE(transform->IsInstanceOf("capped"));
- ASSERT_TRUE(transform->IsInstanceOf("fixed"));
- ASSERT_TRUE(transform->IsInstanceOf("rocksdb.FixedPrefix"));
- ASSERT_EQ(transform->GetId(), "rocksdb.FixedPrefix.31");
- ASSERT_OK(SliceTransform::CreateFromString(
- config_options, "rocksdb.FixedPrefix.42", &transform));
- ASSERT_NE(transform, nullptr);
- ASSERT_EQ(transform->GetId(), "rocksdb.FixedPrefix.42");
- ASSERT_OK(SliceTransform::CreateFromString(config_options, "capped:16",
- &transform));
- ASSERT_NE(transform, nullptr);
- ASSERT_FALSE(transform->IsInstanceOf("fixed"));
- ASSERT_TRUE(transform->IsInstanceOf("capped"));
- ASSERT_TRUE(transform->IsInstanceOf("rocksdb.CappedPrefix"));
- ASSERT_EQ(transform->GetId(), "rocksdb.CappedPrefix.16");
- ASSERT_OK(SliceTransform::CreateFromString(
- config_options, "rocksdb.CappedPrefix.42", &transform));
- ASSERT_NE(transform, nullptr);
- ASSERT_EQ(transform->GetId(), "rocksdb.CappedPrefix.42");
- ASSERT_OK(SliceTransform::CreateFromString(config_options, "rocksdb.Noop",
- &transform));
- ASSERT_NE(transform, nullptr);
- ASSERT_NOK(SliceTransform::CreateFromString(config_options,
- "fixed:21:invalid", &transform));
- ASSERT_NOK(SliceTransform::CreateFromString(config_options,
- "capped:21:invalid", &transform));
- ASSERT_NOK(
- SliceTransform::CreateFromString(config_options, "fixed", &transform));
- ASSERT_NOK(
- SliceTransform::CreateFromString(config_options, "capped", &transform));
- ASSERT_NOK(
- SliceTransform::CreateFromString(config_options, "fixed:", &transform));
- ASSERT_NOK(
- SliceTransform::CreateFromString(config_options, "capped:", &transform));
- ASSERT_NOK(SliceTransform::CreateFromString(
- config_options, "rocksdb.FixedPrefix:42", &transform));
- ASSERT_NOK(SliceTransform::CreateFromString(
- config_options, "rocksdb.CappedPrefix:42", &transform));
- ASSERT_NOK(SliceTransform::CreateFromString(
- config_options, "rocksdb.FixedPrefix", &transform));
- ASSERT_NOK(SliceTransform::CreateFromString(
- config_options, "rocksdb.CappedPrefix", &transform));
- ASSERT_NOK(SliceTransform::CreateFromString(
- config_options, "rocksdb.FixedPrefix.", &transform));
- ASSERT_NOK(SliceTransform::CreateFromString(
- config_options, "rocksdb.CappedPrefix.", &transform));
- ASSERT_NOK(
- SliceTransform::CreateFromString(config_options, "invalid", &transform));
- ASSERT_OK(SliceTransform::CreateFromString(
- config_options, "rocksdb.CappedPrefix.11", &transform));
- ASSERT_NE(transform, nullptr);
- ASSERT_EQ(transform->GetId(), "rocksdb.CappedPrefix.11");
- ASSERT_TRUE(transform->IsInstanceOf("capped"));
- ASSERT_TRUE(transform->IsInstanceOf("capped:11"));
- ASSERT_TRUE(transform->IsInstanceOf("rocksdb.CappedPrefix"));
- ASSERT_TRUE(transform->IsInstanceOf("rocksdb.CappedPrefix.11"));
- ASSERT_FALSE(transform->IsInstanceOf("fixed"));
- ASSERT_FALSE(transform->IsInstanceOf("fixed:11"));
- ASSERT_FALSE(transform->IsInstanceOf("rocksdb.FixedPrefix"));
- ASSERT_FALSE(transform->IsInstanceOf("rocksdb.FixedPrefix.11"));
- ASSERT_OK(SliceTransform::CreateFromString(
- config_options, "rocksdb.FixedPrefix.11", &transform));
- ASSERT_TRUE(transform->IsInstanceOf("fixed"));
- ASSERT_TRUE(transform->IsInstanceOf("fixed:11"));
- ASSERT_TRUE(transform->IsInstanceOf("rocksdb.FixedPrefix"));
- ASSERT_TRUE(transform->IsInstanceOf("rocksdb.FixedPrefix.11"));
- ASSERT_FALSE(transform->IsInstanceOf("capped"));
- ASSERT_FALSE(transform->IsInstanceOf("capped:11"));
- ASSERT_FALSE(transform->IsInstanceOf("rocksdb.CappedPrefix"));
- ASSERT_FALSE(transform->IsInstanceOf("rocksdb.CappedPrefix.11"));
- }
- TEST_F(OptionsOldApiTest, GetBlockBasedTableOptionsFromString) {
- BlockBasedTableOptions table_opt;
- BlockBasedTableOptions new_opt;
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- config_options.ignore_unknown_options = false;
- config_options.invoke_prepare_options = false;
- config_options.ignore_unsupported_options = false;
- // make sure default values are overwritten by something else
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;index_type=kHashSearch;"
- "checksum=kxxHash;no_block_cache=1;"
- "block_cache=1M;block_cache_compressed=1k;block_size=1024;"
- "block_size_deviation=8;block_restart_interval=4;"
- "format_version=5;whole_key_filtering=1;"
- "filter_policy=bloomfilter:4.567:false;",
- &new_opt));
- ASSERT_TRUE(new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(new_opt.index_type, BlockBasedTableOptions::kHashSearch);
- ASSERT_EQ(new_opt.checksum, ChecksumType::kxxHash);
- ASSERT_TRUE(new_opt.no_block_cache);
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(new_opt.block_size, 1024UL);
- ASSERT_EQ(new_opt.block_size_deviation, 8);
- ASSERT_EQ(new_opt.block_restart_interval, 4);
- ASSERT_EQ(new_opt.format_version, 5U);
- ASSERT_EQ(new_opt.whole_key_filtering, true);
- ASSERT_TRUE(new_opt.filter_policy != nullptr);
- const BloomFilterPolicy* bfp =
- dynamic_cast<const BloomFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(bfp->GetMillibitsPerKey(), 4567);
- EXPECT_EQ(bfp->GetWholeBitsPerKey(), 5);
- // unknown option
- ASSERT_NOK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;index_type=kBinarySearch;"
- "bad_option=1",
- &new_opt));
- ASSERT_EQ(static_cast<bool>(table_opt.cache_index_and_filter_blocks),
- new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(table_opt.index_type, new_opt.index_type);
- // unrecognized index type
- ASSERT_NOK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;index_type=kBinarySearchXX", &new_opt));
- ASSERT_EQ(table_opt.cache_index_and_filter_blocks,
- new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(table_opt.index_type, new_opt.index_type);
- // unrecognized checksum type
- ASSERT_NOK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "cache_index_and_filter_blocks=1;checksum=kxxHashXX", &new_opt));
- ASSERT_EQ(table_opt.cache_index_and_filter_blocks,
- new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(table_opt.index_type, new_opt.index_type);
- // unrecognized filter policy name
- ASSERT_NOK(
- GetBlockBasedTableOptionsFromString(config_options, table_opt,
- "cache_index_and_filter_blocks=1;"
- "filter_policy=bloomfilterxx:4:true",
- &new_opt));
- ASSERT_EQ(table_opt.cache_index_and_filter_blocks,
- new_opt.cache_index_and_filter_blocks);
- ASSERT_EQ(table_opt.filter_policy, new_opt.filter_policy);
- // Used to be rejected, now accepted
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt, "filter_policy=bloomfilter:4", &new_opt));
- bfp = dynamic_cast<const BloomFilterPolicy*>(new_opt.filter_policy.get());
- EXPECT_EQ(bfp->GetMillibitsPerKey(), 4000);
- EXPECT_EQ(bfp->GetWholeBitsPerKey(), 4);
- // Check block cache options are overwritten when specified
- // in new format as a struct.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;high_pri_pool_ratio=0.5;};"
- "block_cache_compressed={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;high_pri_pool_ratio=0.5;}",
- &new_opt));
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- 4);
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), true);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- // Set only block cache capacity. Check other values are
- // reset to default values.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={capacity=2M};"
- "block_cache_compressed={capacity=2M}",
- &new_opt));
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 2 * 1024UL * 1024UL);
- // Default values
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- GetDefaultCacheShardBits(new_opt.block_cache->GetCapacity()));
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), false);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- // Set couple of block cache options.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={num_shard_bits=5;high_pri_pool_ratio=0.5;};"
- "block_cache_compressed={num_shard_bits=5;"
- "high_pri_pool_ratio=0.0;}",
- &new_opt));
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 0);
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- 5);
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), false);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- // Set couple of block cache options.
- ASSERT_OK(GetBlockBasedTableOptionsFromString(
- config_options, table_opt,
- "block_cache={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;};"
- "block_cache_compressed={capacity=1M;num_shard_bits=4;"
- "strict_capacity_limit=true;}",
- &new_opt));
- ASSERT_TRUE(new_opt.block_cache != nullptr);
- ASSERT_EQ(new_opt.block_cache->GetCapacity(), 1024UL * 1024UL);
- ASSERT_EQ(std::dynamic_pointer_cast<ShardedCacheBase>(new_opt.block_cache)
- ->GetNumShardBits(),
- 4);
- ASSERT_EQ(new_opt.block_cache->HasStrictCapacityLimit(), true);
- ASSERT_EQ(std::dynamic_pointer_cast<LRUCache>(new_opt.block_cache)
- ->GetHighPriPoolRatio(),
- 0.5);
- }
- TEST_F(OptionsOldApiTest, GetPlainTableOptionsFromString) {
- PlainTableOptions table_opt;
- PlainTableOptions new_opt;
- // make sure default values are overwritten by something else
- ConfigOptions config_options_from_string;
- config_options_from_string.input_strings_escaped = false;
- config_options_from_string.ignore_unknown_options = false;
- config_options_from_string.invoke_prepare_options = false;
- ASSERT_OK(GetPlainTableOptionsFromString(
- config_options_from_string, table_opt,
- "user_key_len=66;bloom_bits_per_key=20;hash_table_ratio=0.5;"
- "index_sparseness=8;huge_page_tlb_size=4;encoding_type=kPrefix;"
- "full_scan_mode=true;store_index_in_file=true",
- &new_opt));
- ASSERT_EQ(new_opt.user_key_len, 66u);
- ASSERT_EQ(new_opt.bloom_bits_per_key, 20);
- ASSERT_EQ(new_opt.hash_table_ratio, 0.5);
- ASSERT_EQ(new_opt.index_sparseness, 8);
- ASSERT_EQ(new_opt.huge_page_tlb_size, 4);
- ASSERT_EQ(new_opt.encoding_type, EncodingType::kPrefix);
- ASSERT_TRUE(new_opt.full_scan_mode);
- ASSERT_TRUE(new_opt.store_index_in_file);
- std::unordered_map<std::string, std::string> opt_map;
- ASSERT_OK(StringToMap(
- "user_key_len=55;bloom_bits_per_key=10;huge_page_tlb_size=8;", &opt_map));
- ConfigOptions config_options_from_map;
- config_options_from_map.input_strings_escaped = false;
- config_options_from_map.ignore_unknown_options = false;
- ASSERT_OK(GetPlainTableOptionsFromMap(config_options_from_map, table_opt,
- opt_map, &new_opt));
- ASSERT_EQ(new_opt.user_key_len, 55u);
- ASSERT_EQ(new_opt.bloom_bits_per_key, 10);
- ASSERT_EQ(new_opt.huge_page_tlb_size, 8);
- // unknown option
- ASSERT_NOK(GetPlainTableOptionsFromString(
- config_options_from_string, table_opt,
- "user_key_len=66;bloom_bits_per_key=20;hash_table_ratio=0.5;"
- "bad_option=1",
- &new_opt));
- // unrecognized EncodingType
- ASSERT_NOK(GetPlainTableOptionsFromString(
- config_options_from_string, table_opt,
- "user_key_len=66;bloom_bits_per_key=20;hash_table_ratio=0.5;"
- "encoding_type=kPrefixXX",
- &new_opt));
- }
- TEST_F(OptionsOldApiTest, GetOptionsFromStringTest) {
- Options base_options, new_options;
- base_options.write_buffer_size = 20;
- base_options.min_write_buffer_number_to_merge = 15;
- BlockBasedTableOptions block_based_table_options;
- block_based_table_options.cache_index_and_filter_blocks = true;
- base_options.table_factory.reset(
- NewBlockBasedTableFactory(block_based_table_options));
- // Register an Env with object registry.
- ObjectLibrary::Default()->AddFactory<Env>(
- "CustomEnvDefault",
- [](const std::string& /*name*/, std::unique_ptr<Env>* /*env_guard*/,
- std::string* /* errmsg */) {
- static CustomEnv env(Env::Default());
- return &env;
- });
- ASSERT_OK(GetOptionsFromString(
- base_options,
- "write_buffer_size=10;max_write_buffer_number=16;"
- "block_based_table_factory={block_cache=1M;block_size=4;};"
- "compression_opts=4:5:6;create_if_missing=true;max_open_files=1;"
- "bottommost_compression_opts=5:6:7;create_if_missing=true;max_open_files="
- "1;"
- "rate_limiter_bytes_per_sec=1024;env=CustomEnvDefault",
- &new_options));
- ASSERT_EQ(new_options.compression_opts.window_bits, 4);
- ASSERT_EQ(new_options.compression_opts.level, 5);
- ASSERT_EQ(new_options.compression_opts.strategy, 6);
- ASSERT_EQ(new_options.compression_opts.max_dict_bytes, 0u);
- ASSERT_EQ(new_options.compression_opts.zstd_max_train_bytes, 0u);
- ASSERT_EQ(new_options.compression_opts.parallel_threads, 1u);
- ASSERT_EQ(new_options.compression_opts.enabled, false);
- ASSERT_EQ(new_options.compression_opts.use_zstd_dict_trainer, true);
- ASSERT_EQ(new_options.bottommost_compression, kDisableCompressionOption);
- ASSERT_EQ(new_options.bottommost_compression_opts.window_bits, 5);
- ASSERT_EQ(new_options.bottommost_compression_opts.level, 6);
- ASSERT_EQ(new_options.bottommost_compression_opts.strategy, 7);
- ASSERT_EQ(new_options.bottommost_compression_opts.max_dict_bytes, 0u);
- ASSERT_EQ(new_options.bottommost_compression_opts.zstd_max_train_bytes, 0u);
- ASSERT_EQ(new_options.bottommost_compression_opts.parallel_threads, 1u);
- ASSERT_EQ(new_options.bottommost_compression_opts.enabled, false);
- ASSERT_EQ(new_options.bottommost_compression_opts.use_zstd_dict_trainer,
- true);
- ASSERT_EQ(new_options.write_buffer_size, 10U);
- ASSERT_EQ(new_options.max_write_buffer_number, 16);
- auto new_block_based_table_options =
- new_options.table_factory->GetOptions<BlockBasedTableOptions>();
- ASSERT_NE(new_block_based_table_options, nullptr);
- ASSERT_EQ(new_block_based_table_options->block_cache->GetCapacity(),
- 1U << 20);
- ASSERT_EQ(new_block_based_table_options->block_size, 4U);
- // don't overwrite block based table options
- ASSERT_TRUE(new_block_based_table_options->cache_index_and_filter_blocks);
- ASSERT_EQ(new_options.create_if_missing, true);
- ASSERT_EQ(new_options.max_open_files, 1);
- ASSERT_TRUE(new_options.rate_limiter.get() != nullptr);
- Env* newEnv = new_options.env;
- ASSERT_OK(Env::CreateFromString({}, "CustomEnvDefault", &newEnv));
- ASSERT_EQ(newEnv, new_options.env);
- }
- TEST_F(OptionsOldApiTest, DBOptionsSerialization) {
- Options base_options, new_options;
- Random rnd(301);
- // Phase 1: Make big change in base_options
- test::RandomInitDBOptions(&base_options, &rnd);
- // Phase 2: obtain a string from base_option
- std::string base_options_file_content;
- ASSERT_OK(GetStringFromDBOptions(&base_options_file_content, base_options));
- // Phase 3: Set new_options from the derived string and expect
- // new_options == base_options
- const DBOptions base_db_options;
- ConfigOptions db_config_options(base_db_options);
- db_config_options.input_strings_escaped = false;
- db_config_options.ignore_unknown_options = false;
- ASSERT_OK(GetDBOptionsFromString(db_config_options, base_db_options,
- base_options_file_content, &new_options));
- ConfigOptions verify_db_config_options;
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(verify_db_config_options,
- base_options, new_options));
- }
- TEST_F(OptionsOldApiTest, ColumnFamilyOptionsSerialization) {
- Options options;
- ColumnFamilyOptions base_opt, new_opt;
- Random rnd(302);
- // Phase 1: randomly assign base_opt
- // custom type options
- test::RandomInitCFOptions(&base_opt, options, &rnd);
- // Phase 2: obtain a string from base_opt
- std::string base_options_file_content;
- ASSERT_OK(
- GetStringFromColumnFamilyOptions(&base_options_file_content, base_opt));
- // Phase 3: Set new_opt from the derived string and expect
- // new_opt == base_opt
- ConfigOptions cf_config_options;
- cf_config_options.input_strings_escaped = false;
- cf_config_options.ignore_unknown_options = false;
- ASSERT_OK(
- GetColumnFamilyOptionsFromString(cf_config_options, ColumnFamilyOptions(),
- base_options_file_content, &new_opt));
- ConfigOptions verify_cf_config_options;
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(verify_cf_config_options,
- base_opt, new_opt));
- if (base_opt.compaction_filter) {
- delete base_opt.compaction_filter;
- }
- }
- class OptionsParserTest : public testing::Test {
- public:
- OptionsParserTest() { fs_.reset(new test::StringFS(FileSystem::Default())); }
- protected:
- std::shared_ptr<test::StringFS> fs_;
- };
- TEST_F(OptionsParserTest, Comment) {
- DBOptions db_opt;
- db_opt.max_open_files = 12345;
- db_opt.max_background_flushes = 301;
- db_opt.max_total_wal_size = 1024;
- ColumnFamilyOptions cf_opt;
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=3.14.0\n"
- " options_file_version=1\n"
- "[ DBOptions ]\n"
- " # note that we don't support space around \"=\"\n"
- " max_open_files=12345;\n"
- " max_background_flushes=301 # comment after a statement is fine\n"
- " # max_background_flushes=1000 # this line would be ignored\n"
- " # max_background_compactions=2000 # so does this one\n"
- " max_total_wal_size=1024 # keep_log_file_num=1000\n"
- "[CFOptions \"default\"] # column family must be specified\n"
- " # in the correct order\n"
- " # if a section is blank, we will use the default\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_OK(
- parser.Parse(kTestFileName, fs_.get(), false, 4096 /* readahead_size */));
- ConfigOptions exact;
- exact.input_strings_escaped = false;
- exact.sanity_level = ConfigOptions::kSanityLevelExactMatch;
- ASSERT_OK(
- RocksDBOptionsParser::VerifyDBOptions(exact, *parser.db_opt(), db_opt));
- ASSERT_EQ(parser.NumColumnFamilies(), 1U);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- exact, *parser.GetCFOptions("default"), cf_opt));
- }
- TEST_F(OptionsParserTest, ExtraSpace) {
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[ Version ]\n"
- " rocksdb_version = 3.14.0 \n"
- " options_file_version=1 # some comment\n"
- "[DBOptions ] # some comment\n"
- "max_open_files=12345 \n"
- " max_background_flushes = 301 \n"
- " max_total_wal_size = 1024 # keep_log_file_num=1000\n"
- " [CFOptions \"default\" ]\n"
- " # if a section is blank, we will use the default\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_OK(
- parser.Parse(kTestFileName, fs_.get(), false, 4096 /* readahead_size */));
- }
- TEST_F(OptionsParserTest, MissingDBOptions) {
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=3.14.0\n"
- " options_file_version=1\n"
- "[CFOptions \"default\"]\n"
- " # if a section is blank, we will use the default\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_NOK(
- parser.Parse(kTestFileName, fs_.get(), false, 4096 /* readahead_size */));
- ;
- }
- TEST_F(OptionsParserTest, DoubleDBOptions) {
- DBOptions db_opt;
- db_opt.max_open_files = 12345;
- db_opt.max_background_flushes = 301;
- db_opt.max_total_wal_size = 1024;
- ColumnFamilyOptions cf_opt;
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=3.14.0\n"
- " options_file_version=1\n"
- "[DBOptions]\n"
- " max_open_files=12345\n"
- " max_background_flushes=301\n"
- " max_total_wal_size=1024 # keep_log_file_num=1000\n"
- "[DBOptions]\n"
- "[CFOptions \"default\"]\n"
- " # if a section is blank, we will use the default\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_NOK(
- parser.Parse(kTestFileName, fs_.get(), false, 4096 /* readahead_size */));
- }
- TEST_F(OptionsParserTest, NoDefaultCFOptions) {
- DBOptions db_opt;
- db_opt.max_open_files = 12345;
- db_opt.max_background_flushes = 301;
- db_opt.max_total_wal_size = 1024;
- ColumnFamilyOptions cf_opt;
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=3.14.0\n"
- " options_file_version=1\n"
- "[DBOptions]\n"
- " max_open_files=12345\n"
- " max_background_flushes=301\n"
- " max_total_wal_size=1024 # keep_log_file_num=1000\n"
- "[CFOptions \"something_else\"]\n"
- " # if a section is blank, we will use the default\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_NOK(
- parser.Parse(kTestFileName, fs_.get(), false, 4096 /* readahead_size */));
- }
- TEST_F(OptionsParserTest, DefaultCFOptionsMustBeTheFirst) {
- DBOptions db_opt;
- db_opt.max_open_files = 12345;
- db_opt.max_background_flushes = 301;
- db_opt.max_total_wal_size = 1024;
- ColumnFamilyOptions cf_opt;
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=3.14.0\n"
- " options_file_version=1\n"
- "[DBOptions]\n"
- " max_open_files=12345\n"
- " max_background_flushes=301\n"
- " max_total_wal_size=1024 # keep_log_file_num=1000\n"
- "[CFOptions \"something_else\"]\n"
- " # if a section is blank, we will use the default\n"
- "[CFOptions \"default\"]\n"
- " # if a section is blank, we will use the default\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_NOK(
- parser.Parse(kTestFileName, fs_.get(), false, 4096 /* readahead_size */));
- }
- TEST_F(OptionsParserTest, DuplicateCFOptions) {
- DBOptions db_opt;
- db_opt.max_open_files = 12345;
- db_opt.max_background_flushes = 301;
- db_opt.max_total_wal_size = 1024;
- ColumnFamilyOptions cf_opt;
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=3.14.0\n"
- " options_file_version=1\n"
- "[DBOptions]\n"
- " max_open_files=12345\n"
- " max_background_flushes=301\n"
- " max_total_wal_size=1024 # keep_log_file_num=1000\n"
- "[CFOptions \"default\"]\n"
- "[CFOptions \"something_else\"]\n"
- "[CFOptions \"something_else\"]\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_NOK(
- parser.Parse(kTestFileName, fs_.get(), false, 4096 /* readahead_size */));
- }
- TEST_F(OptionsParserTest, IgnoreUnknownOptions) {
- auto testCase = [&](bool should_ignore, const std::string& version_string) {
- SCOPED_TRACE(std::to_string(should_ignore) + ", " + version_string);
- std::string options_file_content =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=" +
- version_string +
- "\n"
- " options_file_version=1\n"
- "[DBOptions]\n"
- " max_open_files=12345\n"
- " max_background_flushes=301\n"
- " max_total_wal_size=1024 # keep_log_file_num=1000\n"
- " unknown_db_option1=321\n"
- " unknown_db_option2=false\n"
- "[CFOptions \"default\"]\n"
- " unknown_cf_option1=hello\n"
- "[CFOptions \"something_else\"]\n"
- " unknown_cf_option2=world\n"
- " # if a section is blank, we will use the default\n";
- const std::string kTestFileName = "test-rocksdb-options.ini";
- auto s = fs_->FileExists(kTestFileName, IOOptions(), nullptr);
- ASSERT_TRUE(s.ok() || s.IsNotFound());
- if (s.ok()) {
- ASSERT_OK(fs_->DeleteFile(kTestFileName, IOOptions(), nullptr));
- }
- ASSERT_OK(fs_->WriteToNewFile(kTestFileName, options_file_content));
- RocksDBOptionsParser parser;
- ASSERT_NOK(parser.Parse(kTestFileName, fs_.get(), false,
- 4096 /* readahead_size */));
- Status parse_status = parser.Parse(kTestFileName, fs_.get(),
- true /* ignore_unknown_options */,
- 4096 /* readahead_size */);
- if (should_ignore) {
- ASSERT_OK(parse_status);
- } else {
- ASSERT_NOK(parse_status);
- }
- };
- // Same version
- testCase(false, GetRocksVersionAsString());
- // Same except .0 patch
- testCase(false, std::to_string(ROCKSDB_MAJOR) + "." +
- std::to_string(ROCKSDB_MINOR) + ".0");
- // Higher major version
- testCase(true, std::to_string(ROCKSDB_MAJOR + 1) + "." +
- std::to_string(ROCKSDB_MINOR) + ".0");
- // Higher minor version
- testCase(true, std::to_string(ROCKSDB_MAJOR) + "." +
- std::to_string(ROCKSDB_MINOR + 1) + ".0");
- // Higher patch version
- testCase(true, std::to_string(ROCKSDB_MAJOR) + "." +
- std::to_string(ROCKSDB_MINOR) + "." +
- std::to_string(ROCKSDB_PATCH + 1));
- // Lower major version
- testCase(false, std::to_string(ROCKSDB_MAJOR - 1) + "." +
- std::to_string(ROCKSDB_MINOR) + ".0");
- #if ROCKSDB_MINOR > 0
- // Lower minor version
- testCase(false, std::to_string(ROCKSDB_MAJOR) + "." +
- std::to_string(ROCKSDB_MINOR - 1) + ".0");
- #endif
- #if ROCKSDB_PATCH > 0
- // Lower patch version
- testCase(false, std::to_string(ROCKSDB_MAJOR) + "." +
- std::to_string(ROCKSDB_MINOR - 1) + "." +
- std::to_string(ROCKSDB_PATCH - 1));
- #endif
- }
- TEST_F(OptionsParserTest, ParseVersion) {
- DBOptions db_opt;
- db_opt.max_open_files = 12345;
- db_opt.max_background_flushes = 301;
- db_opt.max_total_wal_size = 1024;
- ColumnFamilyOptions cf_opt;
- std::string file_template =
- "# This is a testing option string.\n"
- "# Currently we only support \"#\" styled comment.\n"
- "\n"
- "[Version]\n"
- " rocksdb_version=3.13.1\n"
- " options_file_version=%s\n"
- "[DBOptions]\n"
- "[CFOptions \"default\"]\n";
- const int kLength = 1000;
- char buffer[kLength];
- RocksDBOptionsParser parser;
- const std::vector<std::string> invalid_versions = {
- "a.b.c",
- "3.2.2b",
- "3.-12",
- "3. 1", // only digits and dots are allowed
- "1.2.3.4",
- "1.2.3" // can only contains at most one dot.
- "0", // options_file_version must be at least one
- "3..2",
- ".",
- ".1.2", // must have at least one digit before each dot
- "1.2.",
- "1.",
- "2.34."}; // must have at least one digit after each dot
- for (const auto& iv : invalid_versions) {
- snprintf(buffer, kLength - 1, file_template.c_str(), iv.c_str());
- parser.Reset();
- ASSERT_OK(fs_->WriteToNewFile(iv, buffer));
- ASSERT_NOK(parser.Parse(iv, fs_.get(), false, 0 /* readahead_size */));
- }
- const std::vector<std::string> valid_versions = {
- "1.232", "100", "3.12", "1", "12.3 ", " 1.25 "};
- for (const auto& vv : valid_versions) {
- snprintf(buffer, kLength - 1, file_template.c_str(), vv.c_str());
- parser.Reset();
- ASSERT_OK(fs_->WriteToNewFile(vv, buffer));
- ASSERT_OK(parser.Parse(vv, fs_.get(), false, 0 /* readahead_size */));
- }
- }
- void VerifyCFPointerTypedOptions(
- ColumnFamilyOptions* base_cf_opt, const ColumnFamilyOptions* new_cf_opt,
- const std::unordered_map<std::string, std::string>* new_cf_opt_map) {
- std::string name_buffer;
- ConfigOptions config_options;
- config_options.input_strings_escaped = false;
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(config_options, *base_cf_opt,
- *new_cf_opt, new_cf_opt_map));
- // change the name of merge operator back-and-forth
- {
- auto* merge_operator = base_cf_opt->merge_operator
- ->CheckedCast<test::ChanglingMergeOperator>();
- if (merge_operator != nullptr) {
- name_buffer = merge_operator->Name();
- // change the name and expect non-ok status
- merge_operator->SetName("some-other-name");
- ASSERT_NOK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- // change the name back and expect ok status
- merge_operator->SetName(name_buffer);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- }
- }
- // change the name of the compaction filter factory back-and-forth
- {
- auto* compaction_filter_factory =
- base_cf_opt->compaction_filter_factory
- ->CheckedCast<test::ChanglingCompactionFilterFactory>();
- if (compaction_filter_factory != nullptr) {
- name_buffer = compaction_filter_factory->Name();
- // change the name and expect non-ok status
- compaction_filter_factory->SetName("some-other-name");
- ASSERT_NOK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- // change the name back and expect ok status
- compaction_filter_factory->SetName(name_buffer);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- }
- }
- // test by setting compaction_filter to nullptr
- {
- auto* tmp_compaction_filter = base_cf_opt->compaction_filter;
- if (tmp_compaction_filter != nullptr) {
- base_cf_opt->compaction_filter = nullptr;
- // set compaction_filter to nullptr and expect non-ok status
- ASSERT_NOK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- // set the value back and expect ok status
- base_cf_opt->compaction_filter = tmp_compaction_filter;
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- }
- }
- // test by setting table_factory to nullptr
- {
- auto tmp_table_factory = base_cf_opt->table_factory;
- if (tmp_table_factory != nullptr) {
- base_cf_opt->table_factory.reset();
- // set table_factory to nullptr and expect non-ok status
- ASSERT_NOK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- // set the value back and expect ok status
- base_cf_opt->table_factory = tmp_table_factory;
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- }
- }
- // test by setting memtable_factory to nullptr
- {
- auto tmp_memtable_factory = base_cf_opt->memtable_factory;
- if (tmp_memtable_factory != nullptr) {
- base_cf_opt->memtable_factory.reset();
- // set memtable_factory to nullptr and expect non-ok status
- ASSERT_NOK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- // set the value back and expect ok status
- base_cf_opt->memtable_factory = tmp_memtable_factory;
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, *base_cf_opt, *new_cf_opt, new_cf_opt_map));
- }
- }
- }
- TEST_F(OptionsParserTest, Readahead) {
- DBOptions base_db_opt;
- std::vector<ColumnFamilyOptions> base_cf_opts;
- base_cf_opts.emplace_back();
- base_cf_opts.emplace_back();
- std::string one_mb_string = std::string(1024 * 1024, 'x');
- std::vector<std::string> cf_names = {"default", one_mb_string};
- const std::string kOptionsFileName = "test-persisted-options.ini";
- ASSERT_OK(PersistRocksDBOptions(WriteOptions(), base_db_opt, cf_names,
- base_cf_opts, kOptionsFileName, fs_.get()));
- uint64_t file_size = 0;
- ASSERT_OK(
- fs_->GetFileSize(kOptionsFileName, IOOptions(), &file_size, nullptr));
- assert(file_size > 0);
- RocksDBOptionsParser parser;
- fs_->num_seq_file_read_ = 0;
- size_t readahead_size = 128 * 1024;
- ASSERT_OK(parser.Parse(kOptionsFileName, fs_.get(), false, readahead_size));
- ASSERT_EQ(fs_->num_seq_file_read_.load(),
- (file_size - 1) / readahead_size + 1);
- fs_->num_seq_file_read_.store(0);
- readahead_size = 1024 * 1024;
- ASSERT_OK(parser.Parse(kOptionsFileName, fs_.get(), false, readahead_size));
- ASSERT_EQ(fs_->num_seq_file_read_.load(),
- (file_size - 1) / readahead_size + 1);
- // Tiny readahead. 8 KB is read each time.
- fs_->num_seq_file_read_.store(0);
- ASSERT_OK(
- parser.Parse(kOptionsFileName, fs_.get(), false, 1 /* readahead_size */));
- ASSERT_GE(fs_->num_seq_file_read_.load(), file_size / (8 * 1024));
- ASSERT_LT(fs_->num_seq_file_read_.load(), file_size / (8 * 1024) * 2);
- // Disable readahead means 512KB readahead.
- fs_->num_seq_file_read_.store(0);
- ASSERT_OK(
- parser.Parse(kOptionsFileName, fs_.get(), false, 0 /* readahead_size */));
- ASSERT_GE(fs_->num_seq_file_read_.load(), (file_size - 1) / (512 * 1024) + 1);
- }
- TEST_F(OptionsParserTest, DumpAndParse) {
- DBOptions base_db_opt;
- std::vector<ColumnFamilyOptions> base_cf_opts;
- std::vector<std::string> cf_names = {"default",
- "cf1",
- "cf2",
- "cf3",
- "c:f:4:4:4"
- "p\\i\\k\\a\\chu\\\\\\",
- "###rocksdb#1-testcf#2###"};
- const int num_cf = static_cast<int>(cf_names.size());
- Random rnd(302);
- test::RandomInitDBOptions(&base_db_opt, &rnd);
- base_db_opt.db_log_dir += "/#odd #but #could #happen #path #/\\\\#OMG";
- BlockBasedTableOptions special_bbto;
- special_bbto.cache_index_and_filter_blocks = true;
- special_bbto.block_size = 999999;
- for (int c = 0; c < num_cf; ++c) {
- ColumnFamilyOptions cf_opt;
- Random cf_rnd(0xFB + c);
- test::RandomInitCFOptions(&cf_opt, base_db_opt, &cf_rnd);
- if (c < 4) {
- cf_opt.prefix_extractor.reset(test::RandomSliceTransform(&rnd, c));
- }
- if (c < 3) {
- cf_opt.table_factory.reset(test::RandomTableFactory(&rnd, c));
- } else if (c == 4) {
- cf_opt.table_factory.reset(NewBlockBasedTableFactory(special_bbto));
- } else if (c == 5) {
- // A table factory that doesn't support deserialization should be
- // supported.
- cf_opt.table_factory.reset(new UnregisteredTableFactory());
- }
- base_cf_opts.emplace_back(cf_opt);
- }
- const std::string kOptionsFileName = "test-persisted-options.ini";
- // Use default for escaped(true), unknown(false) and check (exact)
- ConfigOptions config_options;
- ASSERT_OK(PersistRocksDBOptions(WriteOptions(), base_db_opt, cf_names,
- base_cf_opts, kOptionsFileName, fs_.get()));
- RocksDBOptionsParser parser;
- ASSERT_OK(parser.Parse(config_options, kOptionsFileName, fs_.get()));
- // Make sure block-based table factory options was deserialized correctly
- std::shared_ptr<TableFactory> ttf = (*parser.cf_opts())[4].table_factory;
- ASSERT_EQ(TableFactory::kBlockBasedTableName(), std::string(ttf->Name()));
- const auto parsed_bbto = ttf->GetOptions<BlockBasedTableOptions>();
- ASSERT_NE(parsed_bbto, nullptr);
- ASSERT_EQ(special_bbto.block_size, parsed_bbto->block_size);
- ASSERT_EQ(special_bbto.cache_index_and_filter_blocks,
- parsed_bbto->cache_index_and_filter_blocks);
- ASSERT_OK(RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
- config_options, base_db_opt, cf_names, base_cf_opts, kOptionsFileName,
- fs_.get()));
- ASSERT_OK(RocksDBOptionsParser::VerifyDBOptions(
- config_options, *parser.db_opt(), base_db_opt));
- for (int c = 0; c < num_cf; ++c) {
- const auto* cf_opt = parser.GetCFOptions(cf_names[c]);
- ASSERT_NE(cf_opt, nullptr);
- ASSERT_OK(RocksDBOptionsParser::VerifyCFOptions(
- config_options, base_cf_opts[c], *cf_opt,
- &(parser.cf_opt_maps()->at(c))));
- }
- // Further verify pointer-typed options
- for (int c = 0; c < num_cf; ++c) {
- const auto* cf_opt = parser.GetCFOptions(cf_names[c]);
- ASSERT_NE(cf_opt, nullptr);
- VerifyCFPointerTypedOptions(&base_cf_opts[c], cf_opt,
- &(parser.cf_opt_maps()->at(c)));
- }
- ASSERT_EQ(parser.GetCFOptions("does not exist"), nullptr);
- base_db_opt.max_open_files++;
- ASSERT_NOK(RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
- config_options, base_db_opt, cf_names, base_cf_opts, kOptionsFileName,
- fs_.get()));
- for (int c = 0; c < num_cf; ++c) {
- if (base_cf_opts[c].compaction_filter) {
- delete base_cf_opts[c].compaction_filter;
- }
- }
- }
- TEST_F(OptionsParserTest, DifferentDefault) {
- const std::string kOptionsFileName = "test-persisted-options.ini";
- ColumnFamilyOptions cf_level_opts;
- ASSERT_EQ(CompactionPri::kMinOverlappingRatio, cf_level_opts.compaction_pri);
- cf_level_opts.OptimizeLevelStyleCompaction();
- ColumnFamilyOptions cf_univ_opts;
- cf_univ_opts.OptimizeUniversalStyleCompaction();
- ASSERT_OK(PersistRocksDBOptions(
- WriteOptions(), DBOptions(), {"default", "universal"},
- {cf_level_opts, cf_univ_opts}, kOptionsFileName, fs_.get()));
- RocksDBOptionsParser parser;
- ASSERT_OK(parser.Parse(kOptionsFileName, fs_.get(), false,
- 4096 /* readahead_size */));
- {
- Options old_default_opts;
- old_default_opts.OldDefaults();
- ASSERT_EQ(10 * 1048576, old_default_opts.max_bytes_for_level_base);
- ASSERT_EQ(5000, old_default_opts.max_open_files);
- ASSERT_EQ(2 * 1024U * 1024U, old_default_opts.delayed_write_rate);
- ASSERT_EQ(WALRecoveryMode::kTolerateCorruptedTailRecords,
- old_default_opts.wal_recovery_mode);
- }
- {
- Options old_default_opts;
- old_default_opts.OldDefaults(4, 6);
- ASSERT_EQ(10 * 1048576, old_default_opts.max_bytes_for_level_base);
- ASSERT_EQ(5000, old_default_opts.max_open_files);
- }
- {
- Options old_default_opts;
- old_default_opts.OldDefaults(4, 7);
- ASSERT_NE(10 * 1048576, old_default_opts.max_bytes_for_level_base);
- ASSERT_NE(4, old_default_opts.table_cache_numshardbits);
- ASSERT_EQ(5000, old_default_opts.max_open_files);
- ASSERT_EQ(2 * 1024U * 1024U, old_default_opts.delayed_write_rate);
- }
- {
- ColumnFamilyOptions old_default_cf_opts;
- old_default_cf_opts.OldDefaults();
- ASSERT_EQ(2 * 1048576, old_default_cf_opts.target_file_size_base);
- ASSERT_EQ(4 << 20, old_default_cf_opts.write_buffer_size);
- ASSERT_EQ(2 * 1048576, old_default_cf_opts.target_file_size_base);
- ASSERT_EQ(0, old_default_cf_opts.soft_pending_compaction_bytes_limit);
- ASSERT_EQ(0, old_default_cf_opts.hard_pending_compaction_bytes_limit);
- ASSERT_EQ(CompactionPri::kByCompensatedSize,
- old_default_cf_opts.compaction_pri);
- }
- {
- ColumnFamilyOptions old_default_cf_opts;
- old_default_cf_opts.OldDefaults(4, 6);
- ASSERT_EQ(2 * 1048576, old_default_cf_opts.target_file_size_base);
- ASSERT_EQ(CompactionPri::kByCompensatedSize,
- old_default_cf_opts.compaction_pri);
- }
- {
- ColumnFamilyOptions old_default_cf_opts;
- old_default_cf_opts.OldDefaults(4, 7);
- ASSERT_NE(2 * 1048576, old_default_cf_opts.target_file_size_base);
- ASSERT_EQ(CompactionPri::kByCompensatedSize,
- old_default_cf_opts.compaction_pri);
- }
- {
- Options old_default_opts;
- old_default_opts.OldDefaults(5, 1);
- ASSERT_EQ(2 * 1024U * 1024U, old_default_opts.delayed_write_rate);
- }
- {
- Options old_default_opts;
- old_default_opts.OldDefaults(5, 2);
- ASSERT_EQ(16 * 1024U * 1024U, old_default_opts.delayed_write_rate);
- ASSERT_TRUE(old_default_opts.compaction_pri ==
- CompactionPri::kByCompensatedSize);
- }
- {
- Options old_default_opts;
- old_default_opts.OldDefaults(5, 18);
- ASSERT_TRUE(old_default_opts.compaction_pri ==
- CompactionPri::kByCompensatedSize);
- }
- Options small_opts;
- small_opts.OptimizeForSmallDb();
- ASSERT_EQ(2 << 20, small_opts.write_buffer_size);
- ASSERT_EQ(5000, small_opts.max_open_files);
- }
- class OptionsSanityCheckTest : public OptionsParserTest,
- public ::testing::WithParamInterface<bool> {
- protected:
- ConfigOptions config_options_;
- public:
- OptionsSanityCheckTest() {
- config_options_.ignore_unknown_options = false;
- config_options_.ignore_unsupported_options = GetParam();
- config_options_.input_strings_escaped = true;
- }
- protected:
- Status SanityCheckOptions(const DBOptions& db_opts,
- const ColumnFamilyOptions& cf_opts,
- ConfigOptions::SanityLevel level) {
- config_options_.sanity_level = level;
- return RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
- config_options_, db_opts, {"default"}, {cf_opts}, kOptionsFileName,
- fs_.get());
- }
- Status SanityCheckCFOptions(const ColumnFamilyOptions& cf_opts,
- ConfigOptions::SanityLevel level) {
- return SanityCheckOptions(DBOptions(), cf_opts, level);
- }
- void SanityCheckCFOptions(const ColumnFamilyOptions& opts, bool exact) {
- ASSERT_OK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- if (exact) {
- ASSERT_OK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- } else {
- ASSERT_NOK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- }
- }
- Status SanityCheckDBOptions(const DBOptions& db_opts,
- ConfigOptions::SanityLevel level) {
- return SanityCheckOptions(db_opts, ColumnFamilyOptions(), level);
- }
- void SanityCheckDBOptions(const DBOptions& opts, bool exact) {
- ASSERT_OK(SanityCheckDBOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelNone));
- if (exact) {
- ASSERT_OK(
- SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- } else {
- ASSERT_NOK(
- SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- }
- }
- Status PersistOptions(const DBOptions& db_opts,
- const ColumnFamilyOptions& cf_opts) {
- Status s = fs_->DeleteFile(kOptionsFileName, IOOptions(), nullptr);
- if (!s.ok()) {
- return s;
- }
- return PersistRocksDBOptions(WriteOptions(), db_opts, {"default"},
- {cf_opts}, kOptionsFileName, fs_.get());
- }
- Status PersistCFOptions(const ColumnFamilyOptions& cf_opts) {
- return PersistOptions(DBOptions(), cf_opts);
- }
- Status PersistDBOptions(const DBOptions& db_opts) {
- return PersistOptions(db_opts, ColumnFamilyOptions());
- }
- const std::string kOptionsFileName = "OPTIONS";
- };
- TEST_P(OptionsSanityCheckTest, MergeOperatorErrorMessage) {
- ColumnFamilyOptions opts;
- Random rnd(301);
- opts.merge_operator.reset(test::RandomMergeOperator(&rnd));
- std::string merge_op_name = opts.merge_operator->Name();
- ASSERT_OK(PersistCFOptions(opts));
- // Test when going from merge operator -> nullptr
- opts.merge_operator = nullptr;
- Status s =
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelLooselyCompatible);
- ASSERT_TRUE(s.IsInvalidArgument());
- std::string err_msg = s.ToString();
- std::string specified = "The specified one is " + kNullptrString;
- std::string persisted = "the persisted one is " + merge_op_name;
- ASSERT_TRUE(err_msg.find(specified) != std::string::npos);
- ASSERT_TRUE(err_msg.find(persisted) != std::string::npos);
- // Test when using a different merge operator
- opts.merge_operator.reset(test::RandomMergeOperator(&rnd));
- s = SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelLooselyCompatible);
- ASSERT_TRUE(s.IsInvalidArgument());
- err_msg = s.ToString();
- specified =
- "The specified one is " + std::string(opts.merge_operator->Name());
- persisted = "the persisted one is " + merge_op_name;
- ASSERT_TRUE(err_msg.find(specified) != std::string::npos);
- ASSERT_TRUE(err_msg.find(persisted) != std::string::npos);
- }
- TEST_P(OptionsSanityCheckTest, CFOptionsSanityCheck) {
- ColumnFamilyOptions opts;
- Random rnd(301);
- // default ColumnFamilyOptions
- {
- ASSERT_OK(PersistCFOptions(opts));
- ASSERT_OK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- }
- // prefix_extractor
- {
- // Okay to change prefix_extractor form nullptr to non-nullptr
- ASSERT_EQ(opts.prefix_extractor.get(), nullptr);
- opts.prefix_extractor.reset(NewCappedPrefixTransform(10));
- ASSERT_OK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- ASSERT_OK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- // use same prefix extractor but with different parameter
- opts.prefix_extractor.reset(NewCappedPrefixTransform(15));
- // expect pass only in
- // ConfigOptions::kSanityLevelLooselyCompatible
- ASSERT_NOK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- ASSERT_OK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- // repeat the test with FixedPrefixTransform
- opts.prefix_extractor.reset(NewFixedPrefixTransform(10));
- ASSERT_NOK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- ASSERT_OK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- // persist the change of prefix_extractor
- ASSERT_OK(PersistCFOptions(opts));
- ASSERT_OK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- // use same prefix extractor but with different parameter
- opts.prefix_extractor.reset(NewFixedPrefixTransform(15));
- // expect pass only in
- // ConfigOptions::kSanityLevelLooselyCompatible
- SanityCheckCFOptions(opts, false);
- // Change prefix extractor from non-nullptr to nullptr
- opts.prefix_extractor.reset();
- // expect pass as it's safe to change prefix_extractor
- // from non-null to null
- ASSERT_OK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- }
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- // table_factory
- {
- for (int tb = 0; tb <= 2; ++tb) {
- // change the table factory
- opts.table_factory.reset(test::RandomTableFactory(&rnd, tb));
- ASSERT_NOK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- ASSERT_OK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- }
- }
- // merge_operator
- {
- // Test when going from nullptr -> merge operator
- opts.merge_operator.reset(test::RandomMergeOperator(&rnd));
- ASSERT_OK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
- for (int test = 0; test < 5; ++test) {
- // change the merge operator
- opts.merge_operator.reset(test::RandomMergeOperator(&rnd));
- ASSERT_NOK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
- }
- // Test when going from merge operator -> nullptr
- opts.merge_operator = nullptr;
- ASSERT_NOK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- SanityCheckCFOptions(opts, true);
- }
- // compaction_filter
- {
- for (int test = 0; test < 5; ++test) {
- // change the compaction filter
- opts.compaction_filter = test::RandomCompactionFilter(&rnd);
- SanityCheckCFOptions(opts, false);
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
- delete opts.compaction_filter;
- opts.compaction_filter = nullptr;
- }
- }
- // compaction_filter_factory
- {
- for (int test = 0; test < 5; ++test) {
- // change the compaction filter factory
- opts.compaction_filter_factory.reset(
- test::RandomCompactionFilterFactory(&rnd));
- SanityCheckCFOptions(opts, false);
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
- }
- }
- // persist_user_defined_timestamps
- {
- // Test change from true to false not allowed in loose and exact mode.
- opts.persist_user_defined_timestamps = false;
- ASSERT_NOK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_NOK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
- // Test change from false to true not allowed in loose and exact mode.
- opts.persist_user_defined_timestamps = true;
- ASSERT_NOK(SanityCheckCFOptions(
- opts, ConfigOptions::kSanityLevelLooselyCompatible));
- ASSERT_NOK(
- SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- // persist the change
- ASSERT_OK(PersistCFOptions(opts));
- }
- }
- TEST_P(OptionsSanityCheckTest, DBOptionsSanityCheck) {
- DBOptions opts;
- Random rnd(301);
- // default DBOptions
- {
- ASSERT_OK(PersistDBOptions(opts));
- ASSERT_OK(
- SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- }
- // File checksum generator
- {
- class MockFileChecksumGenFactory : public FileChecksumGenFactory {
- public:
- static const char* kClassName() { return "Mock"; }
- const char* Name() const override { return kClassName(); }
- std::unique_ptr<FileChecksumGenerator> CreateFileChecksumGenerator(
- const FileChecksumGenContext& /*context*/) override {
- return nullptr;
- }
- };
- // Okay to change file_checksum_gen_factory form nullptr to non-nullptr
- ASSERT_EQ(opts.file_checksum_gen_factory.get(), nullptr);
- opts.file_checksum_gen_factory.reset(new MockFileChecksumGenFactory());
- // persist the change
- ASSERT_OK(PersistDBOptions(opts));
- SanityCheckDBOptions(opts, config_options_.ignore_unsupported_options);
- // Change file_checksum_gen_factory from non-nullptr to nullptr
- opts.file_checksum_gen_factory.reset();
- // expect pass as it's safe to change file_checksum_gen_factory
- // from non-null to null
- SanityCheckDBOptions(opts, false);
- }
- // persist the change
- ASSERT_OK(PersistDBOptions(opts));
- ASSERT_OK(SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
- }
- namespace {
- bool IsEscapedString(const std::string& str) {
- for (size_t i = 0; i < str.size(); ++i) {
- if (str[i] == '\\') {
- // since we already handle those two consecutive '\'s in
- // the next if-then branch, any '\' appear at the end
- // of an escaped string in such case is not valid.
- if (i == str.size() - 1) {
- return false;
- }
- if (str[i + 1] == '\\') {
- // if there're two consecutive '\'s, skip the second one.
- i++;
- continue;
- }
- switch (str[i + 1]) {
- case ':':
- case '\\':
- case '#':
- continue;
- default:
- // if true, '\' together with str[i + 1] is not a valid escape.
- if (UnescapeChar(str[i + 1]) == str[i + 1]) {
- return false;
- }
- }
- } else if (isSpecialChar(str[i]) && (i == 0 || str[i - 1] != '\\')) {
- return false;
- }
- }
- return true;
- }
- } // namespace
- TEST_F(OptionsParserTest, IntegerParsing) {
- ASSERT_EQ(ParseUint64("18446744073709551615"), 18446744073709551615U);
- ASSERT_EQ(ParseUint32("4294967295"), 4294967295U);
- ASSERT_EQ(ParseSizeT("18446744073709551615"), 18446744073709551615U);
- ASSERT_EQ(ParseInt64("9223372036854775807"), 9223372036854775807);
- ASSERT_EQ(ParseInt64("-9223372036854775808"),
- std::numeric_limits<int64_t>::min());
- ASSERT_EQ(ParseInt32("2147483647"), 2147483647);
- ASSERT_EQ(ParseInt32("-2147483648"), std::numeric_limits<int32_t>::min());
- ASSERT_EQ(ParseInt("-32767"), -32767);
- ASSERT_EQ(ParseDouble("-1.234567"), -1.234567);
- }
- TEST_F(OptionsParserTest, EscapeOptionString) {
- ASSERT_EQ(UnescapeOptionString(
- "This is a test string with \\# \\: and \\\\ escape chars."),
- "This is a test string with # : and \\ escape chars.");
- ASSERT_EQ(
- EscapeOptionString("This is a test string with # : and \\ escape chars."),
- "This is a test string with \\# \\: and \\\\ escape chars.");
- std::string readible_chars =
- "A String like this \"1234567890-=_)(*&^%$#@!ertyuiop[]{POIU"
- "YTREWQasdfghjkl;':LKJHGFDSAzxcvbnm,.?>"
- "<MNBVCXZ\\\" should be okay to \\#\\\\\\:\\#\\#\\#\\ "
- "be serialized and deserialized";
- std::string escaped_string = EscapeOptionString(readible_chars);
- ASSERT_TRUE(IsEscapedString(escaped_string));
- // This two transformations should be canceled and should output
- // the original input.
- ASSERT_EQ(UnescapeOptionString(escaped_string), readible_chars);
- std::string all_chars;
- for (unsigned char c = 0;; ++c) {
- all_chars += c;
- if (c == 255) {
- break;
- }
- }
- escaped_string = EscapeOptionString(all_chars);
- ASSERT_TRUE(IsEscapedString(escaped_string));
- ASSERT_EQ(UnescapeOptionString(escaped_string), all_chars);
- ASSERT_EQ(RocksDBOptionsParser::TrimAndRemoveComment(
- " A simple statement with a comment. # like this :)"),
- "A simple statement with a comment.");
- ASSERT_EQ(RocksDBOptionsParser::TrimAndRemoveComment(
- "Escape \\# and # comment together ."),
- "Escape \\# and");
- }
- static void TestAndCompareOption(const ConfigOptions& config_options,
- const OptionTypeInfo& opt_info,
- const std::string& opt_name, void* base_ptr,
- void* comp_ptr, bool strip = false) {
- std::string result, mismatch;
- ASSERT_OK(opt_info.Serialize(config_options, opt_name, base_ptr, &result));
- if (strip) {
- ASSERT_EQ(result.at(0), '{');
- ASSERT_EQ(result.at(result.size() - 1), '}');
- result = result.substr(1, result.size() - 2);
- }
- ASSERT_OK(opt_info.Parse(config_options, opt_name, result, comp_ptr));
- ASSERT_TRUE(opt_info.AreEqual(config_options, opt_name, base_ptr, comp_ptr,
- &mismatch));
- }
- static void TestParseAndCompareOption(const ConfigOptions& config_options,
- const OptionTypeInfo& opt_info,
- const std::string& opt_name,
- const std::string& opt_value,
- void* base_ptr, void* comp_ptr,
- bool strip = false) {
- ASSERT_OK(opt_info.Parse(config_options, opt_name, opt_value, base_ptr));
- TestAndCompareOption(config_options, opt_info, opt_name, base_ptr, comp_ptr,
- strip);
- }
- template <typename T>
- void TestOptInfo(const ConfigOptions& config_options, OptionType opt_type,
- T* base, T* comp) {
- std::string result;
- OptionTypeInfo opt_info(0, opt_type);
- ASSERT_FALSE(opt_info.AreEqual(config_options, "base", base, comp, &result));
- ASSERT_EQ(result, "base");
- ASSERT_NE(*base, *comp);
- TestAndCompareOption(config_options, opt_info, "base", base, comp);
- ASSERT_EQ(*base, *comp);
- }
- class OptionTypeInfoTest : public testing::Test {};
- TEST_F(OptionTypeInfoTest, BasicTypes) {
- ConfigOptions config_options;
- {
- bool a = true, b = false;
- TestOptInfo(config_options, OptionType::kBoolean, &a, &b);
- }
- {
- int a = 100, b = 200;
- TestOptInfo(config_options, OptionType::kInt, &a, &b);
- }
- {
- int32_t a = 100, b = 200;
- TestOptInfo(config_options, OptionType::kInt32T, &a, &b);
- }
- {
- int64_t a = 100, b = 200;
- TestOptInfo(config_options, OptionType::kInt64T, &a, &b);
- }
- {
- unsigned int a = 100, b = 200;
- TestOptInfo(config_options, OptionType::kUInt, &a, &b);
- }
- {
- uint32_t a = 100, b = 200;
- TestOptInfo(config_options, OptionType::kUInt32T, &a, &b);
- }
- {
- uint64_t a = 100, b = 200;
- TestOptInfo(config_options, OptionType::kUInt64T, &a, &b);
- }
- {
- size_t a = 100, b = 200;
- TestOptInfo(config_options, OptionType::kSizeT, &a, &b);
- }
- {
- std::string a = "100", b = "200";
- TestOptInfo(config_options, OptionType::kString, &a, &b);
- }
- {
- double a = 1.0, b = 2.0;
- TestOptInfo(config_options, OptionType::kDouble, &a, &b);
- }
- }
- TEST_F(OptionTypeInfoTest, TestInvalidArgs) {
- ConfigOptions config_options;
- bool b;
- int i;
- int32_t i32;
- int64_t i64;
- unsigned int u;
- int32_t u32;
- int64_t u64;
- size_t sz;
- double d;
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kBoolean)
- .Parse(config_options, "b", "x", &b));
- ASSERT_NOK(
- OptionTypeInfo(0, OptionType::kInt).Parse(config_options, "b", "x", &i));
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kInt32T)
- .Parse(config_options, "b", "x", &i32));
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kInt64T)
- .Parse(config_options, "b", "x", &i64));
- ASSERT_NOK(
- OptionTypeInfo(0, OptionType::kUInt).Parse(config_options, "b", "x", &u));
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kUInt32T)
- .Parse(config_options, "b", "x", &u32));
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kUInt64T)
- .Parse(config_options, "b", "x", &u64));
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kSizeT)
- .Parse(config_options, "b", "x", &sz));
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kDouble)
- .Parse(config_options, "b", "x", &d));
- // Don't know how to convert Unknowns to anything else
- ASSERT_NOK(OptionTypeInfo(0, OptionType::kUnknown)
- .Parse(config_options, "b", "x", &d));
- // Verify that if the parse function throws an exception, it is also trapped
- OptionTypeInfo func_info(0, OptionType::kUnknown,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kNone,
- [](const ConfigOptions&, const std::string&,
- const std::string& value, void* addr) {
- auto ptr = static_cast<int*>(addr);
- *ptr = ParseInt(value);
- return Status::OK();
- });
- ASSERT_OK(func_info.Parse(config_options, "b", "1", &i));
- ASSERT_NOK(func_info.Parse(config_options, "b", "x", &i));
- }
- TEST_F(OptionTypeInfoTest, TestParseFunc) {
- OptionTypeInfo opt_info(0, OptionType::kUnknown,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kNone);
- opt_info.SetParseFunc([](const ConfigOptions& /*opts*/,
- const std::string& name, const std::string& value,
- void* addr) {
- auto ptr = static_cast<std::string*>(addr);
- if (name == "Oops") {
- return Status::InvalidArgument(value);
- } else {
- *ptr = value + " " + name;
- return Status::OK();
- }
- });
- ConfigOptions config_options;
- std::string base;
- ASSERT_OK(opt_info.Parse(config_options, "World", "Hello", &base));
- ASSERT_EQ(base, "Hello World");
- ASSERT_NOK(opt_info.Parse(config_options, "Oops", "Hello", &base));
- }
- TEST_F(OptionTypeInfoTest, TestSerializeFunc) {
- OptionTypeInfo opt_info(0, OptionType::kString,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kNone);
- opt_info.SetSerializeFunc([](const ConfigOptions& /*opts*/,
- const std::string& name, const void* /*addr*/,
- std::string* value) {
- if (name == "Oops") {
- return Status::InvalidArgument(name);
- } else {
- *value = name;
- return Status::OK();
- }
- });
- ConfigOptions config_options;
- std::string base;
- std::string value;
- ASSERT_OK(opt_info.Serialize(config_options, "Hello", &base, &value));
- ASSERT_EQ(value, "Hello");
- ASSERT_NOK(opt_info.Serialize(config_options, "Oops", &base, &value));
- }
- TEST_F(OptionTypeInfoTest, TestEqualsFunc) {
- OptionTypeInfo opt_info(0, OptionType::kInt, OptionVerificationType::kNormal,
- OptionTypeFlags::kNone);
- opt_info.SetEqualsFunc([](const ConfigOptions& /*opts*/,
- const std::string& name, const void* addr1,
- const void* addr2, std::string* mismatch) {
- auto i1 = *(static_cast<const int*>(addr1));
- auto i2 = *(static_cast<const int*>(addr2));
- if (name == "LT") {
- return i1 < i2;
- } else if (name == "GT") {
- return i1 > i2;
- } else if (name == "EQ") {
- return i1 == i2;
- } else {
- *mismatch = name + "???";
- return false;
- }
- });
- ConfigOptions config_options;
- int int1 = 100;
- int int2 = 200;
- std::string mismatch;
- ASSERT_TRUE(opt_info.AreEqual(config_options, "LT", &int1, &int2, &mismatch));
- ASSERT_EQ(mismatch, "");
- ASSERT_FALSE(
- opt_info.AreEqual(config_options, "GT", &int1, &int2, &mismatch));
- ASSERT_EQ(mismatch, "GT");
- ASSERT_FALSE(
- opt_info.AreEqual(config_options, "NO", &int1, &int2, &mismatch));
- ASSERT_EQ(mismatch, "NO???");
- }
- TEST_F(OptionTypeInfoTest, TestPrepareFunc) {
- OptionTypeInfo opt_info(0, OptionType::kInt, OptionVerificationType::kNormal,
- OptionTypeFlags::kNone);
- opt_info.SetPrepareFunc(
- [](const ConfigOptions& /*opts*/, const std::string& name, void* addr) {
- auto i1 = static_cast<int*>(addr);
- if (name == "x2") {
- *i1 *= 2;
- } else if (name == "/2") {
- *i1 /= 2;
- } else {
- return Status::InvalidArgument("Bad Argument", name);
- }
- return Status::OK();
- });
- ConfigOptions config_options;
- int int1 = 100;
- ASSERT_OK(opt_info.Prepare(config_options, "x2", &int1));
- ASSERT_EQ(int1, 200);
- ASSERT_OK(opt_info.Prepare(config_options, "/2", &int1));
- ASSERT_EQ(int1, 100);
- ASSERT_NOK(opt_info.Prepare(config_options, "??", &int1));
- ASSERT_EQ(int1, 100);
- }
- TEST_F(OptionTypeInfoTest, TestValidateFunc) {
- OptionTypeInfo opt_info(0, OptionType::kSizeT,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kNone);
- opt_info.SetValidateFunc([](const DBOptions& db_opts,
- const ColumnFamilyOptions& cf_opts,
- const std::string& name, const void* addr) {
- const auto sz = static_cast<const size_t*>(addr);
- bool is_valid = false;
- if (name == "keep_log_file_num") {
- is_valid = (*sz == db_opts.keep_log_file_num);
- } else if (name == "write_buffer_size") {
- is_valid = (*sz == cf_opts.write_buffer_size);
- }
- if (is_valid) {
- return Status::OK();
- } else {
- return Status::InvalidArgument("Mismatched value", name);
- }
- });
- ConfigOptions config_options;
- DBOptions db_options;
- ColumnFamilyOptions cf_options;
- ASSERT_OK(opt_info.Validate(db_options, cf_options, "keep_log_file_num",
- &db_options.keep_log_file_num));
- ASSERT_OK(opt_info.Validate(db_options, cf_options, "write_buffer_size",
- &cf_options.write_buffer_size));
- ASSERT_NOK(opt_info.Validate(db_options, cf_options, "keep_log_file_num",
- &cf_options.write_buffer_size));
- ASSERT_NOK(opt_info.Validate(db_options, cf_options, "write_buffer_size",
- &db_options.keep_log_file_num));
- }
- TEST_F(OptionTypeInfoTest, TestOptionFlags) {
- OptionTypeInfo opt_none(0, OptionType::kString,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kDontSerialize);
- OptionTypeInfo opt_never(0, OptionType::kString,
- OptionVerificationType::kNormal,
- OptionTypeFlags::kCompareNever);
- OptionTypeInfo opt_alias(0, OptionType::kString,
- OptionVerificationType::kAlias,
- OptionTypeFlags::kNone);
- OptionTypeInfo opt_deprecated(0, OptionType::kString,
- OptionVerificationType::kDeprecated,
- OptionTypeFlags::kNone);
- ConfigOptions config_options;
- std::string opts_str;
- std::string base = "base";
- std::string comp = "comp";
- // If marked string none, the serialization returns not supported
- ASSERT_NOK(opt_none.Serialize(config_options, "None", &base, &opts_str));
- // If marked never compare, they match even when they do not
- ASSERT_TRUE(opt_never.AreEqual(config_options, "Never", &base, &comp, &base));
- ASSERT_FALSE(opt_none.AreEqual(config_options, "Never", &base, &comp, &base));
- // An alias can change the value via parse, but does nothing on serialize on
- // match
- std::string result;
- ASSERT_OK(opt_alias.Parse(config_options, "Alias", "Alias", &base));
- ASSERT_OK(opt_alias.Serialize(config_options, "Alias", &base, &result));
- ASSERT_TRUE(
- opt_alias.AreEqual(config_options, "Alias", &base, &comp, &result));
- ASSERT_EQ(base, "Alias");
- ASSERT_NE(base, comp);
- // Deprecated options do nothing on any of the commands
- ASSERT_OK(opt_deprecated.Parse(config_options, "Alias", "Deprecated", &base));
- ASSERT_OK(opt_deprecated.Serialize(config_options, "Alias", &base, &result));
- ASSERT_TRUE(
- opt_deprecated.AreEqual(config_options, "Alias", &base, &comp, &result));
- ASSERT_EQ(base, "Alias");
- ASSERT_NE(base, comp);
- }
- TEST_F(OptionTypeInfoTest, TestCustomEnum) {
- enum TestEnum { kA, kB, kC };
- std::unordered_map<std::string, TestEnum> enum_map = {
- {"A", TestEnum::kA},
- {"B", TestEnum::kB},
- {"C", TestEnum::kC},
- };
- OptionTypeInfo opt_info = OptionTypeInfo::Enum<TestEnum>(0, &enum_map);
- TestEnum e1, e2;
- ConfigOptions config_options;
- std::string result, mismatch;
- e2 = TestEnum::kA;
- ASSERT_OK(opt_info.Parse(config_options, "", "B", &e1));
- ASSERT_OK(opt_info.Serialize(config_options, "", &e1, &result));
- ASSERT_EQ(e1, TestEnum::kB);
- ASSERT_EQ(result, "B");
- ASSERT_FALSE(opt_info.AreEqual(config_options, "Enum", &e1, &e2, &mismatch));
- ASSERT_EQ(mismatch, "Enum");
- TestParseAndCompareOption(config_options, opt_info, "", "C", &e1, &e2);
- ASSERT_EQ(e2, TestEnum::kC);
- ASSERT_NOK(opt_info.Parse(config_options, "", "D", &e1));
- ASSERT_EQ(e1, TestEnum::kC);
- }
- TEST_F(OptionTypeInfoTest, TestBuiltinEnum) {
- ConfigOptions config_options;
- for (const auto& iter : OptionsHelper::compaction_style_string_map) {
- CompactionStyle e1, e2;
- TestParseAndCompareOption(config_options,
- OptionTypeInfo(0, OptionType::kCompactionStyle),
- "CompactionStyle", iter.first, &e1, &e2);
- ASSERT_EQ(e1, iter.second);
- }
- for (const auto& iter : OptionsHelper::compaction_pri_string_map) {
- CompactionPri e1, e2;
- TestParseAndCompareOption(config_options,
- OptionTypeInfo(0, OptionType::kCompactionPri),
- "CompactionPri", iter.first, &e1, &e2);
- ASSERT_EQ(e1, iter.second);
- }
- for (const auto& iter : OptionsHelper::compression_type_string_map) {
- CompressionType e1, e2;
- TestParseAndCompareOption(config_options,
- OptionTypeInfo(0, OptionType::kCompressionType),
- "CompressionType", iter.first, &e1, &e2);
- ASSERT_EQ(e1, iter.second);
- }
- for (const auto& iter : OptionsHelper::compaction_stop_style_string_map) {
- CompactionStopStyle e1, e2;
- TestParseAndCompareOption(
- config_options, OptionTypeInfo(0, OptionType::kCompactionStopStyle),
- "CompactionStopStyle", iter.first, &e1, &e2);
- ASSERT_EQ(e1, iter.second);
- }
- for (const auto& iter : OptionsHelper::checksum_type_string_map) {
- ChecksumType e1, e2;
- TestParseAndCompareOption(config_options,
- OptionTypeInfo(0, OptionType::kChecksumType),
- "CheckSumType", iter.first, &e1, &e2);
- ASSERT_EQ(e1, iter.second);
- }
- for (const auto& iter : OptionsHelper::encoding_type_string_map) {
- EncodingType e1, e2;
- TestParseAndCompareOption(config_options,
- OptionTypeInfo(0, OptionType::kEncodingType),
- "EncodingType", iter.first, &e1, &e2);
- ASSERT_EQ(e1, iter.second);
- }
- }
- TEST_F(OptionTypeInfoTest, TestStruct) {
- struct Basic {
- int i = 42;
- std::string s = "Hello";
- };
- struct Extended {
- int j = 11;
- Basic b;
- };
- std::unordered_map<std::string, OptionTypeInfo> basic_type_map = {
- {"i", {offsetof(struct Basic, i), OptionType::kInt}},
- {"s", {offsetof(struct Basic, s), OptionType::kString}},
- };
- OptionTypeInfo basic_info = OptionTypeInfo::Struct(
- "b", &basic_type_map, 0, OptionVerificationType::kNormal,
- OptionTypeFlags::kMutable);
- std::unordered_map<std::string, OptionTypeInfo> extended_type_map = {
- {"j", {offsetof(struct Extended, j), OptionType::kInt}},
- {"b", OptionTypeInfo::Struct(
- "b", &basic_type_map, offsetof(struct Extended, b),
- OptionVerificationType::kNormal, OptionTypeFlags::kNone)},
- {"m", OptionTypeInfo::Struct(
- "m", &basic_type_map, offsetof(struct Extended, b),
- OptionVerificationType::kNormal, OptionTypeFlags::kMutable)},
- };
- OptionTypeInfo extended_info = OptionTypeInfo::Struct(
- "e", &extended_type_map, 0, OptionVerificationType::kNormal,
- OptionTypeFlags::kMutable);
- Extended e1, e2;
- ConfigOptions config_options;
- std::string mismatch;
- TestParseAndCompareOption(config_options, basic_info, "b", "{i=33;s=33}",
- &e1.b, &e2.b);
- ASSERT_EQ(e1.b.i, 33);
- ASSERT_EQ(e1.b.s, "33");
- TestParseAndCompareOption(config_options, basic_info, "b.i", "44", &e1.b,
- &e2.b);
- ASSERT_EQ(e1.b.i, 44);
- TestParseAndCompareOption(config_options, basic_info, "i", "55", &e1.b,
- &e2.b);
- ASSERT_EQ(e1.b.i, 55);
- e1.b.i = 0;
- ASSERT_FALSE(
- basic_info.AreEqual(config_options, "b", &e1.b, &e2.b, &mismatch));
- ASSERT_EQ(mismatch, "b.i");
- mismatch.clear();
- ASSERT_FALSE(
- basic_info.AreEqual(config_options, "b.i", &e1.b, &e2.b, &mismatch));
- ASSERT_EQ(mismatch, "b.i");
- mismatch.clear();
- ASSERT_FALSE(
- basic_info.AreEqual(config_options, "i", &e1.b, &e2.b, &mismatch));
- ASSERT_EQ(mismatch, "b.i");
- mismatch.clear();
- e1 = e2;
- ASSERT_NOK(basic_info.Parse(config_options, "b", "{i=33;s=33;j=44}", &e1.b));
- ASSERT_NOK(basic_info.Parse(config_options, "b.j", "44", &e1.b));
- ASSERT_NOK(basic_info.Parse(config_options, "j", "44", &e1.b));
- TestParseAndCompareOption(config_options, extended_info, "e",
- "b={i=55;s=55}; j=22;", &e1, &e2);
- ASSERT_EQ(e1.b.i, 55);
- ASSERT_EQ(e1.j, 22);
- ASSERT_EQ(e1.b.s, "55");
- TestParseAndCompareOption(config_options, extended_info, "e.b",
- "{i=66;s=66;}", &e1, &e2);
- ASSERT_EQ(e1.b.i, 66);
- ASSERT_EQ(e1.j, 22);
- ASSERT_EQ(e1.b.s, "66");
- TestParseAndCompareOption(config_options, extended_info, "e.b.i", "77", &e1,
- &e2);
- ASSERT_EQ(e1.b.i, 77);
- ASSERT_EQ(e1.j, 22);
- ASSERT_EQ(e1.b.s, "66");
- }
- TEST_F(OptionTypeInfoTest, TestArrayType) {
- OptionTypeInfo array_info = OptionTypeInfo::Array<std::string, 4>(
- 0, OptionVerificationType::kNormal, OptionTypeFlags::kNone,
- {0, OptionType::kString});
- std::array<std::string, 4> array1, array2;
- std::string mismatch;
- ConfigOptions config_options;
- TestParseAndCompareOption(config_options, array_info, "v", "a:b:c:d", &array1,
- &array2);
- ASSERT_EQ(array1.size(), 4);
- ASSERT_EQ(array1[0], "a");
- ASSERT_EQ(array1[1], "b");
- ASSERT_EQ(array1[2], "c");
- ASSERT_EQ(array1[3], "d");
- array1[3] = "e";
- ASSERT_FALSE(
- array_info.AreEqual(config_options, "v", &array1, &array2, &mismatch));
- ASSERT_EQ(mismatch, "v");
- // Test vectors with inner brackets
- TestParseAndCompareOption(config_options, array_info, "v", "a:{b}:c:d",
- &array1, &array2);
- ASSERT_EQ(array1.size(), 4);
- ASSERT_EQ(array1[0], "a");
- ASSERT_EQ(array1[1], "b");
- ASSERT_EQ(array1[2], "c");
- ASSERT_EQ(array1[3], "d");
- std::array<std::string, 3> array3, array4;
- OptionTypeInfo bar_info = OptionTypeInfo::Array<std::string, 3>(
- 0, OptionVerificationType::kNormal, OptionTypeFlags::kNone,
- {0, OptionType::kString}, '|');
- TestParseAndCompareOption(config_options, bar_info, "v", "x|y|z", &array3,
- &array4);
- // Test arrays with inner array
- TestParseAndCompareOption(config_options, bar_info, "v",
- "a|{b1|b2}|{c1|c2|{d1|d2}}", &array3, &array4,
- false);
- ASSERT_EQ(array3.size(), 3);
- ASSERT_EQ(array3[0], "a");
- ASSERT_EQ(array3[1], "b1|b2");
- ASSERT_EQ(array3[2], "c1|c2|{d1|d2}");
- TestParseAndCompareOption(config_options, bar_info, "v",
- "{a1|a2}|{b1|{c1|c2}}|d1", &array3, &array4, true);
- ASSERT_EQ(array3.size(), 3);
- ASSERT_EQ(array3[0], "a1|a2");
- ASSERT_EQ(array3[1], "b1|{c1|c2}");
- ASSERT_EQ(array3[2], "d1");
- // Test invalid input: less element than requested
- auto s = bar_info.Parse(config_options, "opt_name1", "a1|a2", &array3);
- ASSERT_TRUE(s.IsInvalidArgument());
- // Test invalid input: more element than requested
- s = bar_info.Parse(config_options, "opt_name2", "a1|b|c1|d3", &array3);
- ASSERT_TRUE(s.IsInvalidArgument());
- }
- TEST_F(OptionTypeInfoTest, TestVectorType) {
- OptionTypeInfo vec_info = OptionTypeInfo::Vector<std::string>(
- 0, OptionVerificationType::kNormal, OptionTypeFlags::kNone,
- {0, OptionType::kString});
- std::vector<std::string> vec1, vec2;
- std::string mismatch;
- ConfigOptions config_options;
- TestParseAndCompareOption(config_options, vec_info, "v", "a:b:c:d", &vec1,
- &vec2);
- ASSERT_EQ(vec1.size(), 4);
- ASSERT_EQ(vec1[0], "a");
- ASSERT_EQ(vec1[1], "b");
- ASSERT_EQ(vec1[2], "c");
- ASSERT_EQ(vec1[3], "d");
- vec1[3] = "e";
- ASSERT_FALSE(vec_info.AreEqual(config_options, "v", &vec1, &vec2, &mismatch));
- ASSERT_EQ(mismatch, "v");
- // Test vectors with inner brackets
- TestParseAndCompareOption(config_options, vec_info, "v", "a:{b}:c:d", &vec1,
- &vec2);
- ASSERT_EQ(vec1.size(), 4);
- ASSERT_EQ(vec1[0], "a");
- ASSERT_EQ(vec1[1], "b");
- ASSERT_EQ(vec1[2], "c");
- ASSERT_EQ(vec1[3], "d");
- OptionTypeInfo bar_info = OptionTypeInfo::Vector<std::string>(
- 0, OptionVerificationType::kNormal, OptionTypeFlags::kNone,
- {0, OptionType::kString}, '|');
- TestParseAndCompareOption(config_options, vec_info, "v", "x|y|z", &vec1,
- &vec2);
- // Test vectors with inner vector
- TestParseAndCompareOption(config_options, bar_info, "v",
- "a|{b1|b2}|{c1|c2|{d1|d2}}", &vec1, &vec2, false);
- ASSERT_EQ(vec1.size(), 3);
- ASSERT_EQ(vec1[0], "a");
- ASSERT_EQ(vec1[1], "b1|b2");
- ASSERT_EQ(vec1[2], "c1|c2|{d1|d2}");
- TestParseAndCompareOption(config_options, bar_info, "v",
- "{a1|a2}|{b1|{c1|c2}}|d1", &vec1, &vec2, true);
- ASSERT_EQ(vec1.size(), 3);
- ASSERT_EQ(vec1[0], "a1|a2");
- ASSERT_EQ(vec1[1], "b1|{c1|c2}");
- ASSERT_EQ(vec1[2], "d1");
- TestParseAndCompareOption(config_options, bar_info, "v", "{a1}", &vec1, &vec2,
- false);
- ASSERT_EQ(vec1.size(), 1);
- ASSERT_EQ(vec1[0], "a1");
- TestParseAndCompareOption(config_options, bar_info, "v", "{a1|a2}|{b1|b2}",
- &vec1, &vec2, true);
- ASSERT_EQ(vec1.size(), 2);
- ASSERT_EQ(vec1[0], "a1|a2");
- ASSERT_EQ(vec1[1], "b1|b2");
- }
- TEST_F(OptionTypeInfoTest, TestStaticType) {
- struct SimpleOptions {
- size_t size = 0;
- bool verify = true;
- };
- static std::unordered_map<std::string, OptionTypeInfo> type_map = {
- {"size", {offsetof(struct SimpleOptions, size), OptionType::kSizeT}},
- {"verify",
- {offsetof(struct SimpleOptions, verify), OptionType::kBoolean}},
- };
- ConfigOptions config_options;
- SimpleOptions opts, copy;
- opts.size = 12345;
- opts.verify = false;
- std::string str, mismatch;
- ASSERT_OK(
- OptionTypeInfo::SerializeType(config_options, type_map, &opts, &str));
- ASSERT_FALSE(OptionTypeInfo::TypesAreEqual(config_options, type_map, &opts,
- ©, &mismatch));
- ASSERT_OK(OptionTypeInfo::ParseType(config_options, str, type_map, ©));
- ASSERT_TRUE(OptionTypeInfo::TypesAreEqual(config_options, type_map, &opts,
- ©, &mismatch));
- }
- class ConfigOptionsTest : public testing::Test {};
- TEST_F(ConfigOptionsTest, EnvFromConfigOptions) {
- ConfigOptions config_options;
- DBOptions db_opts;
- Options opts;
- Env* mem_env = NewMemEnv(Env::Default());
- config_options.registry->AddLibrary("custom-env", RegisterCustomEnv,
- kCustomEnvName);
- config_options.env = mem_env;
- // First test that we can get the env as expected
- ASSERT_OK(GetDBOptionsFromString(config_options, DBOptions(), kCustomEnvProp,
- &db_opts));
- ASSERT_OK(
- GetOptionsFromString(config_options, Options(), kCustomEnvProp, &opts));
- ASSERT_NE(config_options.env, db_opts.env);
- ASSERT_EQ(opts.env, db_opts.env);
- Env* custom_env = db_opts.env;
- // Now try a "bad" env" and check that nothing changed
- config_options.ignore_unsupported_options = true;
- ASSERT_OK(
- GetDBOptionsFromString(config_options, db_opts, "env=unknown", &db_opts));
- ASSERT_OK(GetOptionsFromString(config_options, opts, "env=unknown", &opts));
- ASSERT_EQ(config_options.env, mem_env);
- ASSERT_EQ(db_opts.env, custom_env);
- ASSERT_EQ(opts.env, db_opts.env);
- // Now try a "bad" env" ignoring unknown objects
- config_options.ignore_unsupported_options = false;
- ASSERT_NOK(
- GetDBOptionsFromString(config_options, db_opts, "env=unknown", &db_opts));
- ASSERT_EQ(config_options.env, mem_env);
- ASSERT_EQ(db_opts.env, custom_env);
- ASSERT_EQ(opts.env, db_opts.env);
- delete mem_env;
- }
- TEST_F(ConfigOptionsTest, MergeOperatorFromString) {
- ConfigOptions config_options;
- std::shared_ptr<MergeOperator> merge_op;
- ASSERT_OK(MergeOperator::CreateFromString(config_options, "put", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("put"));
- ASSERT_STREQ(merge_op->Name(), "PutOperator");
- ASSERT_OK(
- MergeOperator::CreateFromString(config_options, "put_v1", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("PutOperator"));
- ASSERT_OK(
- MergeOperator::CreateFromString(config_options, "uint64add", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("uint64add"));
- ASSERT_STREQ(merge_op->Name(), "UInt64AddOperator");
- ASSERT_OK(MergeOperator::CreateFromString(config_options, "max", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("max"));
- ASSERT_STREQ(merge_op->Name(), "MaxOperator");
- ASSERT_OK(
- MergeOperator::CreateFromString(config_options, "bytesxor", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("bytesxor"));
- ASSERT_STREQ(merge_op->Name(), BytesXOROperator::kClassName());
- ASSERT_OK(
- MergeOperator::CreateFromString(config_options, "sortlist", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("sortlist"));
- ASSERT_STREQ(merge_op->Name(), SortList::kClassName());
- ASSERT_OK(MergeOperator::CreateFromString(config_options, "stringappend",
- &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("stringappend"));
- ASSERT_STREQ(merge_op->Name(), StringAppendOperator::kClassName());
- auto delimiter = merge_op->GetOptions<std::string>("Delimiter");
- ASSERT_NE(delimiter, nullptr);
- ASSERT_EQ(*delimiter, ",");
- ASSERT_OK(MergeOperator::CreateFromString(config_options, "stringappendtest",
- &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("stringappendtest"));
- ASSERT_STREQ(merge_op->Name(), StringAppendTESTOperator::kClassName());
- delimiter = merge_op->GetOptions<std::string>("Delimiter");
- ASSERT_NE(delimiter, nullptr);
- ASSERT_EQ(*delimiter, ",");
- ASSERT_OK(MergeOperator::CreateFromString(
- config_options, "id=stringappend; delimiter=||", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("stringappend"));
- ASSERT_STREQ(merge_op->Name(), StringAppendOperator::kClassName());
- delimiter = merge_op->GetOptions<std::string>("Delimiter");
- ASSERT_NE(delimiter, nullptr);
- ASSERT_EQ(*delimiter, "||");
- ASSERT_OK(MergeOperator::CreateFromString(
- config_options, "id=stringappendtest; delimiter=&&", &merge_op));
- ASSERT_NE(merge_op, nullptr);
- ASSERT_TRUE(merge_op->IsInstanceOf("stringappendtest"));
- ASSERT_STREQ(merge_op->Name(), StringAppendTESTOperator::kClassName());
- delimiter = merge_op->GetOptions<std::string>("Delimiter");
- ASSERT_NE(delimiter, nullptr);
- ASSERT_EQ(*delimiter, "&&");
- std::shared_ptr<MergeOperator> copy;
- std::string mismatch;
- std::string opts_str = merge_op->ToString(config_options);
- ASSERT_OK(MergeOperator::CreateFromString(config_options, opts_str, ©));
- ASSERT_TRUE(merge_op->AreEquivalent(config_options, copy.get(), &mismatch));
- ASSERT_NE(copy, nullptr);
- delimiter = copy->GetOptions<std::string>("Delimiter");
- ASSERT_NE(delimiter, nullptr);
- ASSERT_EQ(*delimiter, "&&");
- }
- TEST_F(ConfigOptionsTest, ConfiguringOptionsDoesNotRevertRateLimiterBandwidth) {
- // Regression test for bug where rate limiter's dynamically set bandwidth
- // could be silently reverted when configuring an options structure with an
- // existing `rate_limiter`.
- Options base_options;
- base_options.rate_limiter.reset(
- NewGenericRateLimiter(1 << 20 /* rate_bytes_per_sec */));
- Options copy_options(base_options);
- base_options.rate_limiter->SetBytesPerSecond(2 << 20);
- ASSERT_EQ(2 << 20, base_options.rate_limiter->GetBytesPerSecond());
- ASSERT_OK(GetOptionsFromString(base_options, "", ©_options));
- ASSERT_EQ(2 << 20, base_options.rate_limiter->GetBytesPerSecond());
- }
- INSTANTIATE_TEST_CASE_P(OptionsSanityCheckTest, OptionsSanityCheckTest,
- ::testing::Bool());
- } // namespace ROCKSDB_NAMESPACE
- int main(int argc, char** argv) {
- ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
- ::testing::InitGoogleTest(&argc, argv);
- #ifdef GFLAGS
- ParseCommandLineFlags(&argc, &argv, true);
- #endif // GFLAGS
- return RUN_ALL_TESTS();
- }
|