transaction_test.cc 298 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #include "utilities/transactions/transaction_test.h"
  6. #include <algorithm>
  7. #include <array>
  8. #include <functional>
  9. #include <numeric>
  10. #include <string>
  11. #include <thread>
  12. #include "db/db_impl/db_impl.h"
  13. #include "port/port.h"
  14. #include "rocksdb/attribute_groups.h"
  15. #include "rocksdb/db.h"
  16. #include "rocksdb/options.h"
  17. #include "rocksdb/perf_context.h"
  18. #include "rocksdb/utilities/secondary_index.h"
  19. #include "rocksdb/utilities/secondary_index_simple.h"
  20. #include "rocksdb/utilities/transaction.h"
  21. #include "rocksdb/utilities/transaction_db.h"
  22. #include "table/mock_table.h"
  23. #include "test_util/sync_point.h"
  24. #include "test_util/testharness.h"
  25. #include "test_util/testutil.h"
  26. #include "test_util/transaction_test_util.h"
  27. #include "util/random.h"
  28. #include "util/string_util.h"
  29. #include "utilities/merge_operators.h"
  30. #include "utilities/secondary_index/secondary_index_helper.h"
  31. #include "utilities/transactions/pessimistic_transaction_db.h"
  32. namespace ROCKSDB_NAMESPACE {
  33. constexpr std::array DBAsBaseDB_TransactionTest_Params = {
  34. std::make_tuple(false, false, WRITE_COMMITTED, kOrderedWrite),
  35. std::make_tuple(false, true, WRITE_COMMITTED, kOrderedWrite),
  36. std::make_tuple(false, false, WRITE_PREPARED, kOrderedWrite),
  37. std::make_tuple(false, true, WRITE_PREPARED, kOrderedWrite),
  38. std::make_tuple(false, true, WRITE_PREPARED, kUnorderedWrite),
  39. std::make_tuple(false, false, WRITE_UNPREPARED, kOrderedWrite),
  40. std::make_tuple(false, true, WRITE_UNPREPARED, kOrderedWrite)};
  41. INSTANTIATE_TEST_CASE_P(
  42. DBAsBaseDB, TransactionTest,
  43. ::testing::ValuesIn(WRAP_PARAM_WITH_PER_KEY_POINT_LOCK_MANAGER_PARAMS(
  44. WRAP_PARAM(bool, bool, TxnDBWritePolicy, WriteOrdering),
  45. DBAsBaseDB_TransactionTest_Params)));
  46. constexpr std::array DBAsBaseDB_TransactionStressTest_Params = {
  47. std::make_tuple(false, false, WRITE_COMMITTED, kOrderedWrite),
  48. std::make_tuple(false, true, WRITE_COMMITTED, kOrderedWrite),
  49. std::make_tuple(false, false, WRITE_PREPARED, kOrderedWrite),
  50. std::make_tuple(false, true, WRITE_PREPARED, kOrderedWrite),
  51. std::make_tuple(false, true, WRITE_PREPARED, kUnorderedWrite),
  52. std::make_tuple(false, false, WRITE_UNPREPARED, kOrderedWrite),
  53. std::make_tuple(false, true, WRITE_UNPREPARED, kOrderedWrite)};
  54. INSTANTIATE_TEST_CASE_P(
  55. DBAsBaseDB, TransactionStressTest,
  56. ::testing::ValuesIn(WRAP_PARAM_WITH_PER_KEY_POINT_LOCK_MANAGER_PARAMS(
  57. WRAP_PARAM(bool, bool, TxnDBWritePolicy, WriteOrdering),
  58. DBAsBaseDB_TransactionStressTest_Params)));
  59. constexpr std::array StackableDBAsBaseDB_TransactionTest_Params = {
  60. std::make_tuple(true, true, WRITE_COMMITTED, kOrderedWrite),
  61. std::make_tuple(true, true, WRITE_PREPARED, kOrderedWrite),
  62. std::make_tuple(true, true, WRITE_UNPREPARED, kOrderedWrite)};
  63. INSTANTIATE_TEST_CASE_P(
  64. StackableDBAsBaseDB, TransactionTest,
  65. ::testing::ValuesIn(WRAP_PARAM_WITH_PER_KEY_POINT_LOCK_MANAGER_PARAMS(
  66. WRAP_PARAM(bool, bool, TxnDBWritePolicy, WriteOrdering),
  67. StackableDBAsBaseDB_TransactionTest_Params)));
  68. // MySQLStyleTransactionTest takes far too long for valgrind to run. Only do it
  69. // in full mode (`ROCKSDB_FULL_VALGRIND_RUN` compiler flag is set).
  70. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  71. constexpr std::array MySQLStyleTransactionTest_Params = {
  72. std::make_tuple(false, false, WRITE_COMMITTED, kOrderedWrite, false),
  73. std::make_tuple(false, true, WRITE_COMMITTED, kOrderedWrite, false),
  74. std::make_tuple(false, false, WRITE_PREPARED, kOrderedWrite, false),
  75. std::make_tuple(false, false, WRITE_PREPARED, kOrderedWrite, true),
  76. std::make_tuple(false, true, WRITE_PREPARED, kOrderedWrite, false),
  77. std::make_tuple(false, true, WRITE_PREPARED, kOrderedWrite, true),
  78. std::make_tuple(false, false, WRITE_UNPREPARED, kOrderedWrite, false),
  79. std::make_tuple(false, false, WRITE_UNPREPARED, kOrderedWrite, true),
  80. std::make_tuple(false, true, WRITE_UNPREPARED, kOrderedWrite, false),
  81. std::make_tuple(false, true, WRITE_UNPREPARED, kOrderedWrite, true),
  82. std::make_tuple(false, true, WRITE_PREPARED, kUnorderedWrite, false),
  83. std::make_tuple(false, true, WRITE_PREPARED, kUnorderedWrite, true)};
  84. INSTANTIATE_TEST_CASE_P(
  85. MySQLStyleTransactionTest, MySQLStyleTransactionTest,
  86. ::testing::ValuesIn(WRAP_PARAM_WITH_PER_KEY_POINT_LOCK_MANAGER_PARAMS(
  87. WRAP_PARAM(bool, bool, TxnDBWritePolicy, WriteOrdering, bool),
  88. MySQLStyleTransactionTest_Params)));
  89. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  90. TEST_P(TransactionTest, TestUpperBoundUponDeletion) {
  91. // Reproduction from the original bug report, 11606
  92. // This test does writes without snapshot validation, and then tries to create
  93. // iterator later, which is unsupported in write unprepared.
  94. if (txn_db_options.write_policy == WRITE_UNPREPARED) {
  95. return;
  96. }
  97. WriteOptions write_options;
  98. ReadOptions read_options;
  99. Status s;
  100. Transaction* txn = db->BeginTransaction(write_options);
  101. ASSERT_TRUE(txn);
  102. // Write some keys in a txn
  103. s = txn->Put("2", "2");
  104. ASSERT_OK(s);
  105. s = txn->Put("1", "1");
  106. ASSERT_OK(s);
  107. s = txn->Delete("2");
  108. ASSERT_OK(s);
  109. read_options.iterate_upper_bound = new Slice("2", 1);
  110. Iterator* iter = txn->GetIterator(read_options);
  111. ASSERT_OK(iter->status());
  112. iter->SeekToFirst();
  113. while (iter->Valid()) {
  114. ASSERT_EQ("1", iter->key().ToString());
  115. iter->Next();
  116. }
  117. delete iter;
  118. delete txn;
  119. delete read_options.iterate_upper_bound;
  120. }
  121. TEST_P(TransactionTest, TestTxnRespectBoundsInReadOption) {
  122. if (txn_db_options.write_policy == WRITE_UNPREPARED) {
  123. return;
  124. }
  125. WriteOptions write_options;
  126. {
  127. std::unique_ptr<Transaction> txn(db->BeginTransaction(write_options));
  128. // writes that should be observed by base_iterator_ in BaseDeltaIterator
  129. ASSERT_OK(txn->Put("a", "aa"));
  130. ASSERT_OK(txn->Put("c", "cc"));
  131. ASSERT_OK(txn->Put("e", "ee"));
  132. ASSERT_OK(txn->Put("f", "ff"));
  133. ASSERT_TRUE(txn->Commit().ok());
  134. }
  135. std::unique_ptr<Transaction> txn2(db->BeginTransaction(write_options));
  136. // writes that should be observed by delta_iterator_ in BaseDeltaIterator
  137. ASSERT_OK(txn2->Put("b", "bb"));
  138. ASSERT_OK(txn2->Put("c", "cc"));
  139. ASSERT_OK(txn2->Put("f", "ff"));
  140. // delta_iterator_: b c f
  141. // base_iterator_: a c e f
  142. //
  143. // given range [c, f)
  144. // assert only {c, e} can be seen
  145. ReadOptions ro;
  146. ro.iterate_lower_bound = new Slice("c");
  147. ro.iterate_upper_bound = new Slice("f");
  148. std::unique_ptr<Iterator> iter(txn2->GetIterator(ro));
  149. iter->Seek(Slice("b"));
  150. ASSERT_EQ("c", iter->key()); // lower bound capping
  151. iter->Seek(Slice("f"));
  152. ASSERT_FALSE(iter->Valid()); // out of bound
  153. iter->SeekForPrev(Slice("f"));
  154. ASSERT_EQ("e", iter->key()); // upper bound capping
  155. iter->SeekForPrev(Slice("b"));
  156. ASSERT_FALSE(iter->Valid()); // out of bound
  157. // move to the lower bound
  158. iter->SeekToFirst();
  159. ASSERT_EQ("c", iter->key());
  160. iter->Prev();
  161. ASSERT_FALSE(iter->Valid());
  162. // move to the upper bound
  163. iter->SeekToLast();
  164. ASSERT_EQ("e", iter->key());
  165. iter->Next();
  166. ASSERT_FALSE(iter->Valid());
  167. // reversely walk to the beginning
  168. iter->SeekToLast();
  169. ASSERT_EQ("e", iter->key());
  170. iter->Prev();
  171. ASSERT_EQ("c", iter->key());
  172. iter->Prev();
  173. ASSERT_FALSE(iter->Valid());
  174. delete ro.iterate_lower_bound;
  175. delete ro.iterate_upper_bound;
  176. }
  177. TEST_P(TransactionTest, DoubleEmptyWrite) {
  178. WriteOptions write_options;
  179. write_options.sync = true;
  180. write_options.disableWAL = false;
  181. WriteBatch batch;
  182. ASSERT_OK(db->Write(write_options, &batch));
  183. ASSERT_OK(db->Write(write_options, &batch));
  184. // Also test committing empty transactions in 2PC
  185. TransactionOptions txn_options;
  186. Transaction* txn0 = db->BeginTransaction(write_options, txn_options);
  187. ASSERT_OK(txn0->SetName("xid"));
  188. ASSERT_OK(txn0->Prepare());
  189. ASSERT_OK(txn0->Commit());
  190. delete txn0;
  191. // Also test that it works during recovery
  192. txn0 = db->BeginTransaction(write_options, txn_options);
  193. ASSERT_OK(txn0->SetName("xid2"));
  194. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0a")));
  195. ASSERT_OK(txn0->Prepare());
  196. delete txn0;
  197. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  198. ASSERT_OK(ReOpenNoDelete());
  199. assert(db != nullptr);
  200. txn0 = db->GetTransactionByName("xid2");
  201. ASSERT_OK(txn0->Commit());
  202. delete txn0;
  203. }
  204. TEST_P(TransactionTest, SuccessTest) {
  205. ASSERT_OK(db->ResetStats());
  206. WriteOptions write_options;
  207. ReadOptions read_options;
  208. std::string value;
  209. ASSERT_OK(db->Put(write_options, Slice("foo"), Slice("bar")));
  210. ASSERT_OK(db->Put(write_options, Slice("foo2"), Slice("bar")));
  211. Transaction* txn = db->BeginTransaction(write_options, TransactionOptions());
  212. ASSERT_TRUE(txn);
  213. ASSERT_EQ(0, txn->GetNumPuts());
  214. ASSERT_LE(0, txn->GetID());
  215. ASSERT_OK(txn->GetForUpdate(read_options, "foo", &value));
  216. ASSERT_EQ(value, "bar");
  217. ASSERT_OK(txn->Put(Slice("foo"), Slice("bar2")));
  218. ASSERT_EQ(1, txn->GetNumPuts());
  219. ASSERT_OK(txn->GetForUpdate(read_options, "foo", &value));
  220. ASSERT_EQ(value, "bar2");
  221. ASSERT_OK(txn->Commit());
  222. ASSERT_OK(db->Get(read_options, "foo", &value));
  223. ASSERT_EQ(value, "bar2");
  224. delete txn;
  225. }
  226. // Test the basic API of the pinnable slice overload of GetForUpdate()
  227. TEST_P(TransactionTest, SuccessTestPinnable) {
  228. ASSERT_OK(db->ResetStats());
  229. WriteOptions write_options;
  230. ReadOptions read_options;
  231. PinnableSlice pinnable_val;
  232. ASSERT_OK(db->Put(write_options, Slice("foo"), Slice("bar")));
  233. ASSERT_OK(db->Put(write_options, Slice("foo2"), Slice("bar")));
  234. Transaction* txn = db->BeginTransaction(write_options, TransactionOptions());
  235. ASSERT_TRUE(txn);
  236. ASSERT_EQ(0, txn->GetNumPuts());
  237. ASSERT_LE(0, txn->GetID());
  238. ASSERT_OK(txn->GetForUpdate(read_options, "foo", &pinnable_val));
  239. ASSERT_EQ(*pinnable_val.GetSelf(), std::string("bar"));
  240. ASSERT_OK(txn->Put(Slice("foo"), Slice("bar2")));
  241. ASSERT_EQ(1, txn->GetNumPuts());
  242. ASSERT_OK(txn->GetForUpdate(read_options, "foo", &pinnable_val));
  243. ASSERT_EQ(*pinnable_val.GetSelf(), std::string("bar2"));
  244. ASSERT_OK(txn->Commit());
  245. ASSERT_OK(
  246. db->Get(read_options, db->DefaultColumnFamily(), "foo", &pinnable_val));
  247. ASSERT_EQ(*pinnable_val.GetSelf(), std::string("bar2"));
  248. delete txn;
  249. }
  250. TEST_P(TransactionTest, SwitchMemtableDuringPrepareAndCommit_WC) {
  251. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  252. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  253. ROCKSDB_GTEST_BYPASS("Test applies to write-committed only");
  254. return;
  255. }
  256. ASSERT_OK(db->Put(WriteOptions(), "key0", "value"));
  257. TransactionOptions txn_opts;
  258. txn_opts.use_only_the_last_commit_time_batch_for_recovery = true;
  259. Transaction* txn = db->BeginTransaction(WriteOptions(), txn_opts);
  260. assert(txn);
  261. SyncPoint::GetInstance()->DisableProcessing();
  262. SyncPoint::GetInstance()->ClearAllCallBacks();
  263. SyncPoint::GetInstance()->SetCallBack(
  264. "FlushJob::WriteLevel0Table", [&](void* arg) {
  265. // db mutex not held.
  266. auto* mems = static_cast<autovector<MemTable*>*>(arg);
  267. assert(mems);
  268. ASSERT_EQ(1, mems->size());
  269. auto* ctwb = txn->GetCommitTimeWriteBatch();
  270. ASSERT_OK(ctwb->Put("gtid", "123"));
  271. ASSERT_OK(txn->Commit());
  272. delete txn;
  273. });
  274. SyncPoint::GetInstance()->EnableProcessing();
  275. ASSERT_OK(txn->Put("key1", "value"));
  276. ASSERT_OK(txn->SetName("txn1"));
  277. ASSERT_OK(txn->Prepare());
  278. auto dbimpl = static_cast_with_check<DBImpl>(db->GetRootDB());
  279. ASSERT_OK(dbimpl->TEST_SwitchMemtable(nullptr));
  280. ASSERT_OK(dbimpl->TEST_FlushMemTable(
  281. /*wait=*/false, /*allow_write_stall=*/true, /*cfh=*/nullptr));
  282. ASSERT_OK(dbimpl->TEST_WaitForFlushMemTable());
  283. {
  284. std::string value;
  285. ASSERT_OK(db->Get(ReadOptions(), "key1", &value));
  286. ASSERT_EQ("value", value);
  287. }
  288. ASSERT_OK(dbimpl->SyncWAL());
  289. delete db;
  290. db = nullptr;
  291. Status s;
  292. if (use_stackable_db_ == false) {
  293. s = TransactionDB::Open(options, txn_db_options, dbname, &db);
  294. } else {
  295. s = OpenWithStackableDB();
  296. }
  297. ASSERT_OK(s);
  298. assert(db);
  299. {
  300. std::string value;
  301. ASSERT_OK(db->Get(ReadOptions(), "gtid", &value));
  302. ASSERT_EQ("123", value);
  303. ASSERT_OK(db->Get(ReadOptions(), "key1", &value));
  304. ASSERT_EQ("value", value);
  305. }
  306. SyncPoint::GetInstance()->DisableProcessing();
  307. SyncPoint::GetInstance()->ClearAllCallBacks();
  308. }
  309. // The test clarifies the contract of do_validate and assume_tracked
  310. // in GetForUpdate and Put/Merge/Delete
  311. TEST_P(TransactionTest, AssumeExclusiveTracked) {
  312. WriteOptions write_options;
  313. ReadOptions read_options;
  314. std::string value;
  315. Status s;
  316. TransactionOptions txn_options;
  317. txn_options.lock_timeout = 1;
  318. const bool EXCLUSIVE = true;
  319. const bool DO_VALIDATE = true;
  320. const bool ASSUME_LOCKED = true;
  321. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  322. ASSERT_TRUE(txn);
  323. txn->SetSnapshot();
  324. // commit a value after the snapshot is taken
  325. ASSERT_OK(db->Put(write_options, Slice("foo"), Slice("bar")));
  326. // By default write should fail to the commit after our snapshot
  327. s = txn->GetForUpdate(read_options, "foo", &value, EXCLUSIVE);
  328. ASSERT_TRUE(s.IsBusy());
  329. // But the user could direct the db to skip validating the snapshot. The read
  330. // value then should be the most recently committed
  331. ASSERT_OK(
  332. txn->GetForUpdate(read_options, "foo", &value, EXCLUSIVE, !DO_VALIDATE));
  333. ASSERT_EQ(value, "bar");
  334. // Although ValidateSnapshot is skipped the key must have still got locked
  335. s = db->Put(write_options, Slice("foo"), Slice("bar"));
  336. ASSERT_TRUE(s.IsTimedOut());
  337. // By default the write operations should fail due to the commit after the
  338. // snapshot
  339. s = txn->Put(Slice("foo"), Slice("bar1"));
  340. ASSERT_TRUE(s.IsBusy());
  341. s = txn->Put(db->DefaultColumnFamily(), Slice("foo"), Slice("bar1"),
  342. !ASSUME_LOCKED);
  343. ASSERT_TRUE(s.IsBusy());
  344. // But the user could direct the db that it already assumes exclusive lock on
  345. // the key due to the previous GetForUpdate call.
  346. ASSERT_OK(txn->Put(db->DefaultColumnFamily(), Slice("foo"), Slice("bar1"),
  347. ASSUME_LOCKED));
  348. ASSERT_OK(txn->Merge(db->DefaultColumnFamily(), Slice("foo"), Slice("bar2"),
  349. ASSUME_LOCKED));
  350. ASSERT_OK(
  351. txn->Delete(db->DefaultColumnFamily(), Slice("foo"), ASSUME_LOCKED));
  352. ASSERT_OK(txn->SingleDelete(db->DefaultColumnFamily(), Slice("foo"),
  353. ASSUME_LOCKED));
  354. ASSERT_OK(txn->Rollback());
  355. delete txn;
  356. }
  357. // This test clarifies the contract of ValidateSnapshot
  358. TEST_P(TransactionTest, ValidateSnapshotTest) {
  359. for (bool with_flush : {true}) {
  360. for (bool with_2pc : {true}) {
  361. ASSERT_OK(ReOpen());
  362. WriteOptions write_options;
  363. ReadOptions read_options;
  364. std::string value;
  365. assert(db != nullptr);
  366. Transaction* txn1 =
  367. db->BeginTransaction(write_options, TransactionOptions());
  368. ASSERT_TRUE(txn1);
  369. ASSERT_OK(txn1->Put(Slice("foo"), Slice("bar1")));
  370. if (with_2pc) {
  371. ASSERT_OK(txn1->SetName("xid1"));
  372. ASSERT_OK(txn1->Prepare());
  373. }
  374. if (with_flush) {
  375. auto db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  376. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  377. // Make sure the flushed memtable is not kept in memory
  378. int max_memtable_in_history =
  379. std::max(
  380. options.max_write_buffer_number,
  381. static_cast<int>(options.max_write_buffer_size_to_maintain) /
  382. static_cast<int>(options.write_buffer_size)) +
  383. 1;
  384. for (int i = 0; i < max_memtable_in_history; i++) {
  385. ASSERT_OK(db->Put(write_options, Slice("key"), Slice("value")));
  386. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  387. }
  388. }
  389. Transaction* txn2 =
  390. db->BeginTransaction(write_options, TransactionOptions());
  391. ASSERT_TRUE(txn2);
  392. txn2->SetSnapshot();
  393. ASSERT_OK(txn1->Commit());
  394. delete txn1;
  395. auto pes_txn2 = dynamic_cast<PessimisticTransaction*>(txn2);
  396. // Test the simple case where the key is not tracked yet
  397. auto trakced_seq = kMaxSequenceNumber;
  398. auto s = pes_txn2->ValidateSnapshot(db->DefaultColumnFamily(), "foo",
  399. &trakced_seq);
  400. ASSERT_TRUE(s.IsBusy());
  401. delete txn2;
  402. }
  403. }
  404. }
  405. TEST_P(TransactionTest, WaitingTxn) {
  406. WriteOptions write_options;
  407. ReadOptions read_options;
  408. TransactionOptions txn_options;
  409. std::string value;
  410. Status s;
  411. txn_options.lock_timeout = 1;
  412. s = db->Put(write_options, Slice("foo"), Slice("bar"));
  413. ASSERT_OK(s);
  414. /* create second cf */
  415. ColumnFamilyHandle* cfa;
  416. ColumnFamilyOptions cf_options;
  417. s = db->CreateColumnFamily(cf_options, "CFA", &cfa);
  418. ASSERT_OK(s);
  419. s = db->Put(write_options, cfa, Slice("foo"), Slice("bar"));
  420. ASSERT_OK(s);
  421. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  422. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  423. TransactionID id1 = txn1->GetID();
  424. ASSERT_TRUE(txn1);
  425. ASSERT_TRUE(txn2);
  426. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  427. "PointLockManager::AcquireWithTimeout:WaitingTxn", [&](void* /*arg*/) {
  428. std::string key;
  429. uint32_t cf_id;
  430. std::vector<TransactionID> wait = txn2->GetWaitingTxns(&cf_id, &key);
  431. ASSERT_EQ(key, "foo");
  432. ASSERT_EQ(wait.size(), 1);
  433. ASSERT_EQ(wait[0], id1);
  434. ASSERT_EQ(cf_id, 0U);
  435. });
  436. get_perf_context()->Reset();
  437. // lock key in default cf
  438. s = txn1->GetForUpdate(read_options, "foo", &value);
  439. ASSERT_OK(s);
  440. ASSERT_EQ(value, "bar");
  441. ASSERT_EQ(get_perf_context()->key_lock_wait_count, 0);
  442. // lock key in cfa
  443. s = txn1->GetForUpdate(read_options, cfa, "foo", &value);
  444. ASSERT_OK(s);
  445. ASSERT_EQ(value, "bar");
  446. ASSERT_EQ(get_perf_context()->key_lock_wait_count, 0);
  447. auto lock_data = db->GetLockStatusData();
  448. // Locked keys exist in both column family.
  449. ASSERT_EQ(lock_data.size(), 2);
  450. auto cf_iterator = lock_data.begin();
  451. // The iterator points to an unordered_multimap
  452. // thus the test can not assume any particular order.
  453. // Column family is 1 or 0 (cfa).
  454. if (cf_iterator->first != 1 && cf_iterator->first != 0) {
  455. FAIL();
  456. }
  457. // The locked key is "foo" and is locked by txn1
  458. ASSERT_EQ(cf_iterator->second.key, "foo");
  459. ASSERT_EQ(cf_iterator->second.ids.size(), 1);
  460. ASSERT_EQ(cf_iterator->second.ids[0], txn1->GetID());
  461. cf_iterator++;
  462. // Column family is 0 (default) or 1.
  463. if (cf_iterator->first != 1 && cf_iterator->first != 0) {
  464. FAIL();
  465. }
  466. // The locked key is "foo" and is locked by txn1
  467. ASSERT_EQ(cf_iterator->second.key, "foo");
  468. ASSERT_EQ(cf_iterator->second.ids.size(), 1);
  469. ASSERT_EQ(cf_iterator->second.ids[0], txn1->GetID());
  470. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  471. s = txn2->GetForUpdate(read_options, "foo", &value);
  472. ASSERT_TRUE(s.IsTimedOut());
  473. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  474. ASSERT_EQ(get_perf_context()->key_lock_wait_count, 1);
  475. ASSERT_GE(get_perf_context()->key_lock_wait_time, 0);
  476. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  477. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  478. // We expect GetWaitingTxns still returns the waiting values as it would
  479. // normally before timeout
  480. std::string key;
  481. uint32_t cf_id;
  482. std::vector<TransactionID> wait = txn2->GetWaitingTxns(&cf_id, &key);
  483. ASSERT_EQ(key, "foo");
  484. ASSERT_EQ(wait.size(), 1);
  485. ASSERT_EQ(wait[0], id1);
  486. ASSERT_EQ(cf_id, 0U);
  487. delete cfa;
  488. delete txn1;
  489. delete txn2;
  490. }
  491. TEST_P(TransactionTest, SharedLocks) {
  492. WriteOptions write_options;
  493. ReadOptions read_options;
  494. TransactionOptions txn_options;
  495. Status s;
  496. txn_options.lock_timeout = 1;
  497. s = db->Put(write_options, Slice("foo"), Slice("bar"));
  498. ASSERT_OK(s);
  499. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  500. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  501. Transaction* txn3 = db->BeginTransaction(write_options, txn_options);
  502. ASSERT_TRUE(txn1);
  503. ASSERT_TRUE(txn2);
  504. ASSERT_TRUE(txn3);
  505. // Test shared access between txns
  506. s = txn1->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  507. false /* exclusive */);
  508. ASSERT_OK(s);
  509. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  510. false /* exclusive */);
  511. ASSERT_OK(s);
  512. s = txn3->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  513. false /* exclusive */);
  514. ASSERT_OK(s);
  515. auto lock_data = db->GetLockStatusData();
  516. ASSERT_EQ(lock_data.size(), 1);
  517. auto cf_iterator = lock_data.begin();
  518. ASSERT_EQ(cf_iterator->second.key, "foo");
  519. // We compare whether the set of txns locking this key is the same. To do
  520. // this, we need to sort both vectors so that the comparison is done
  521. // correctly.
  522. std::vector<TransactionID> expected_txns = {txn1->GetID(), txn2->GetID(),
  523. txn3->GetID()};
  524. std::vector<TransactionID> lock_txns = cf_iterator->second.ids;
  525. ASSERT_EQ(expected_txns, lock_txns);
  526. ASSERT_FALSE(cf_iterator->second.exclusive);
  527. ASSERT_OK(txn1->Rollback());
  528. ASSERT_OK(txn2->Rollback());
  529. ASSERT_OK(txn3->Rollback());
  530. // Test txn1 and txn2 sharing a lock and txn3 trying to obtain it.
  531. s = txn1->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  532. false /* exclusive */);
  533. ASSERT_OK(s);
  534. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  535. false /* exclusive */);
  536. ASSERT_OK(s);
  537. s = txn3->GetForUpdate(read_options, "foo", (std::string*)nullptr);
  538. ASSERT_TRUE(s.IsTimedOut());
  539. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  540. txn1->UndoGetForUpdate("foo");
  541. s = txn3->GetForUpdate(read_options, "foo", (std::string*)nullptr);
  542. ASSERT_TRUE(s.IsTimedOut());
  543. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  544. txn2->UndoGetForUpdate("foo");
  545. s = txn3->GetForUpdate(read_options, "foo", (std::string*)nullptr);
  546. ASSERT_OK(s);
  547. ASSERT_OK(txn1->Rollback());
  548. ASSERT_OK(txn2->Rollback());
  549. ASSERT_OK(txn3->Rollback());
  550. // Test txn1 and txn2 sharing a lock and txn2 trying to upgrade lock.
  551. s = txn1->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  552. false /* exclusive */);
  553. ASSERT_OK(s);
  554. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  555. false /* exclusive */);
  556. ASSERT_OK(s);
  557. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr);
  558. ASSERT_TRUE(s.IsTimedOut());
  559. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  560. txn1->UndoGetForUpdate("foo");
  561. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr);
  562. ASSERT_OK(s);
  563. ASSERT_OK(txn1->Rollback());
  564. ASSERT_OK(txn2->Rollback());
  565. // Test txn1 trying to downgrade its lock.
  566. s = txn1->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  567. true /* exclusive */);
  568. ASSERT_OK(s);
  569. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  570. false /* exclusive */);
  571. ASSERT_TRUE(s.IsTimedOut());
  572. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  573. // Should still fail after "downgrading".
  574. s = txn1->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  575. false /* exclusive */);
  576. ASSERT_OK(s);
  577. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  578. false /* exclusive */);
  579. ASSERT_TRUE(s.IsTimedOut());
  580. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  581. ASSERT_OK(txn1->Rollback());
  582. ASSERT_OK(txn2->Rollback());
  583. // Test txn1 holding an exclusive lock and txn2 trying to obtain shared
  584. // access.
  585. s = txn1->GetForUpdate(read_options, "foo", (std::string*)nullptr);
  586. ASSERT_OK(s);
  587. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  588. false /* exclusive */);
  589. ASSERT_TRUE(s.IsTimedOut());
  590. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  591. txn1->UndoGetForUpdate("foo");
  592. s = txn2->GetForUpdate(read_options, "foo", (std::string*)nullptr,
  593. false /* exclusive */);
  594. ASSERT_OK(s);
  595. delete txn1;
  596. delete txn2;
  597. delete txn3;
  598. }
  599. TEST_P(TransactionTest, DeadlockCycleShared) {
  600. WriteOptions write_options;
  601. ReadOptions read_options;
  602. TransactionOptions txn_options;
  603. txn_options.lock_timeout = 1000000;
  604. txn_options.deadlock_detect = true;
  605. // Set up a wait for chain like this:
  606. //
  607. // Tn -> T(n*2)
  608. // Tn -> T(n*2 + 1)
  609. //
  610. // So we have:
  611. // T1 -> T2 -> T4 ...
  612. // | |> T5 ...
  613. // |> T3 -> T6 ...
  614. // |> T7 ...
  615. // up to T31, then T[16 - 31] -> T1.
  616. // Note that Tn holds lock on floor(n / 2).
  617. std::vector<Transaction*> txns(31);
  618. for (uint32_t i = 0; i < 31; i++) {
  619. txns[i] = db->BeginTransaction(write_options, txn_options);
  620. ASSERT_TRUE(txns[i]);
  621. auto s =
  622. txns[i]->GetForUpdate(read_options, std::to_string((i + 1) / 2),
  623. (std::string*)nullptr, false /* exclusive */);
  624. ASSERT_OK(s);
  625. }
  626. std::atomic<uint32_t> checkpoints(0);
  627. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  628. "PointLockManager::AcquireWithTimeout:WaitingTxn",
  629. [&](void* /*arg*/) { checkpoints.fetch_add(1); });
  630. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  631. // We want the leaf transactions to block and hold everyone back.
  632. std::vector<port::Thread> threads;
  633. for (uint32_t i = 0; i < 15; i++) {
  634. std::function<void()> blocking_thread = [&, i] {
  635. auto s =
  636. txns[i]->GetForUpdate(read_options, std::to_string(i + 1),
  637. (std::string*)nullptr, true /* exclusive */);
  638. ASSERT_OK(s);
  639. ASSERT_OK(txns[i]->Rollback());
  640. delete txns[i];
  641. };
  642. threads.emplace_back(blocking_thread);
  643. }
  644. // Wait until all threads are waiting on each other.
  645. while (checkpoints.load() != 15) {
  646. /* sleep override */
  647. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  648. }
  649. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  650. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  651. // Complete the cycle T[16 - 31] -> T1
  652. for (uint32_t i = 15; i < 31; i++) {
  653. auto s = txns[i]->GetForUpdate(read_options, "0", (std::string*)nullptr,
  654. true /* exclusive */);
  655. ASSERT_TRUE(s.IsDeadlock());
  656. // Calculate next buffer len, plateau at 5 when 5 records are inserted.
  657. const uint32_t curr_dlock_buffer_len_ =
  658. (i - 14 > kInitialMaxDeadlocks) ? kInitialMaxDeadlocks : (i - 14);
  659. auto dlock_buffer = db->GetDeadlockInfoBuffer();
  660. ASSERT_EQ(dlock_buffer.size(), curr_dlock_buffer_len_);
  661. auto dlock_entry = dlock_buffer[0].path;
  662. ASSERT_EQ(dlock_entry.size(), kInitialMaxDeadlocks);
  663. int64_t pre_deadlock_time = dlock_buffer[0].deadlock_time;
  664. int64_t cur_deadlock_time = 0;
  665. for (auto const& dl_path_rec : dlock_buffer) {
  666. cur_deadlock_time = dl_path_rec.deadlock_time;
  667. ASSERT_NE(cur_deadlock_time, 0);
  668. ASSERT_TRUE(cur_deadlock_time <= pre_deadlock_time);
  669. pre_deadlock_time = cur_deadlock_time;
  670. }
  671. int64_t curr_waiting_key = 0;
  672. // Offset of each txn id from the root of the shared dlock tree's txn id.
  673. int64_t offset_root = dlock_entry[0].m_txn_id - 1;
  674. // Offset of the final entry in the dlock path from the root's txn id.
  675. TransactionID leaf_id =
  676. dlock_entry[dlock_entry.size() - 1].m_txn_id - offset_root;
  677. for (auto it = dlock_entry.rbegin(); it != dlock_entry.rend(); ++it) {
  678. auto dl_node = *it;
  679. ASSERT_EQ(dl_node.m_txn_id, offset_root + leaf_id);
  680. ASSERT_EQ(dl_node.m_cf_id, 0U);
  681. ASSERT_EQ(dl_node.m_waiting_key, std::to_string(curr_waiting_key));
  682. ASSERT_EQ(dl_node.m_exclusive, true);
  683. if (curr_waiting_key == 0) {
  684. curr_waiting_key = leaf_id;
  685. }
  686. curr_waiting_key /= 2;
  687. leaf_id /= 2;
  688. }
  689. }
  690. // Rollback the leaf transaction.
  691. for (uint32_t i = 15; i < 31; i++) {
  692. ASSERT_OK(txns[i]->Rollback());
  693. delete txns[i];
  694. }
  695. for (auto& t : threads) {
  696. t.join();
  697. }
  698. // Downsize the buffer and verify the 3 latest deadlocks are preserved.
  699. auto dlock_buffer_before_resize = db->GetDeadlockInfoBuffer();
  700. db->SetDeadlockInfoBufferSize(3);
  701. auto dlock_buffer_after_resize = db->GetDeadlockInfoBuffer();
  702. ASSERT_EQ(dlock_buffer_after_resize.size(), 3);
  703. for (uint32_t i = 0; i < dlock_buffer_after_resize.size(); i++) {
  704. for (uint32_t j = 0; j < dlock_buffer_after_resize[i].path.size(); j++) {
  705. ASSERT_EQ(dlock_buffer_after_resize[i].path[j].m_txn_id,
  706. dlock_buffer_before_resize[i].path[j].m_txn_id);
  707. }
  708. }
  709. // Upsize the buffer and verify the 3 latest dealocks are preserved.
  710. dlock_buffer_before_resize = db->GetDeadlockInfoBuffer();
  711. db->SetDeadlockInfoBufferSize(5);
  712. dlock_buffer_after_resize = db->GetDeadlockInfoBuffer();
  713. ASSERT_EQ(dlock_buffer_after_resize.size(), 3);
  714. for (uint32_t i = 0; i < dlock_buffer_before_resize.size(); i++) {
  715. for (uint32_t j = 0; j < dlock_buffer_before_resize[i].path.size(); j++) {
  716. ASSERT_EQ(dlock_buffer_after_resize[i].path[j].m_txn_id,
  717. dlock_buffer_before_resize[i].path[j].m_txn_id);
  718. }
  719. }
  720. // Downsize to 0 and verify the size is consistent.
  721. dlock_buffer_before_resize = db->GetDeadlockInfoBuffer();
  722. db->SetDeadlockInfoBufferSize(0);
  723. dlock_buffer_after_resize = db->GetDeadlockInfoBuffer();
  724. ASSERT_EQ(dlock_buffer_after_resize.size(), 0);
  725. // Upsize from 0 to verify the size is persistent.
  726. dlock_buffer_before_resize = db->GetDeadlockInfoBuffer();
  727. db->SetDeadlockInfoBufferSize(3);
  728. dlock_buffer_after_resize = db->GetDeadlockInfoBuffer();
  729. ASSERT_EQ(dlock_buffer_after_resize.size(), 0);
  730. // Contrived case of shared lock of cycle size 2 to verify that a shared
  731. // lock causing a deadlock is correctly reported as "shared" in the buffer.
  732. std::vector<Transaction*> txns_shared(2);
  733. // Create a cycle of size 2.
  734. for (uint32_t i = 0; i < 2; i++) {
  735. txns_shared[i] = db->BeginTransaction(write_options, txn_options);
  736. ASSERT_TRUE(txns_shared[i]);
  737. auto s = txns_shared[i]->GetForUpdate(read_options, std::to_string(i),
  738. (std::string*)nullptr);
  739. ASSERT_OK(s);
  740. }
  741. std::atomic<uint32_t> checkpoints_shared(0);
  742. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  743. "PointLockManager::AcquireWithTimeout:WaitingTxn",
  744. [&](void* /*arg*/) { checkpoints_shared.fetch_add(1); });
  745. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  746. std::vector<port::Thread> threads_shared;
  747. for (uint32_t i = 0; i < 1; i++) {
  748. std::function<void()> blocking_thread = [&, i] {
  749. auto s = txns_shared[i]->GetForUpdate(read_options, std::to_string(i + 1),
  750. (std::string*)nullptr);
  751. ASSERT_OK(s);
  752. ASSERT_OK(txns_shared[i]->Rollback());
  753. delete txns_shared[i];
  754. };
  755. threads_shared.emplace_back(blocking_thread);
  756. }
  757. // Wait until all threads are waiting on each other.
  758. while (checkpoints_shared.load() != 1) {
  759. /* sleep override */
  760. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  761. }
  762. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  763. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  764. // Complete the cycle T2 -> T1 with a shared lock.
  765. auto s = txns_shared[1]->GetForUpdate(read_options, "0",
  766. (std::string*)nullptr, false);
  767. ASSERT_TRUE(s.IsDeadlock());
  768. auto dlock_buffer = db->GetDeadlockInfoBuffer();
  769. // Verify the size of the buffer and the single path.
  770. ASSERT_EQ(dlock_buffer.size(), 1);
  771. ASSERT_EQ(dlock_buffer[0].path.size(), 2);
  772. // Verify the exclusivity field of the transactions in the deadlock path.
  773. ASSERT_TRUE(dlock_buffer[0].path[0].m_exclusive);
  774. ASSERT_FALSE(dlock_buffer[0].path[1].m_exclusive);
  775. ASSERT_OK(txns_shared[1]->Rollback());
  776. delete txns_shared[1];
  777. for (auto& t : threads_shared) {
  778. t.join();
  779. }
  780. }
  781. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  782. TEST_P(TransactionStressTest, DeadlockCycle) {
  783. WriteOptions write_options;
  784. ReadOptions read_options;
  785. TransactionOptions txn_options;
  786. // offset by 2 from the max depth to test edge case
  787. const uint32_t kMaxCycleLength = 52;
  788. txn_options.lock_timeout = 1000000;
  789. txn_options.deadlock_detect = true;
  790. for (uint32_t len = 2; len < kMaxCycleLength; len++) {
  791. // Set up a long wait for chain like this:
  792. //
  793. // T1 -> T2 -> T3 -> ... -> Tlen
  794. std::vector<Transaction*> txns(len);
  795. for (uint32_t i = 0; i < len; i++) {
  796. txns[i] = db->BeginTransaction(write_options, txn_options);
  797. ASSERT_TRUE(txns[i]);
  798. auto s = txns[i]->GetForUpdate(read_options, std::to_string(i),
  799. (std::string*)nullptr);
  800. ASSERT_OK(s);
  801. }
  802. std::atomic<uint32_t> checkpoints(0);
  803. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  804. "PointLockManager::AcquireWithTimeout:WaitingTxn",
  805. [&](void* /*arg*/) { checkpoints.fetch_add(1); });
  806. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  807. // We want the last transaction in the chain to block and hold everyone
  808. // back.
  809. std::vector<port::Thread> threads;
  810. for (uint32_t i = 0; i + 1 < len; i++) {
  811. std::function<void()> blocking_thread = [&, i] {
  812. auto s = txns[i]->GetForUpdate(read_options, std::to_string(i + 1),
  813. (std::string*)nullptr);
  814. ASSERT_OK(s);
  815. ASSERT_OK(txns[i]->Rollback());
  816. delete txns[i];
  817. };
  818. threads.emplace_back(blocking_thread);
  819. }
  820. // Wait until all threads are waiting on each other.
  821. while (checkpoints.load() != len - 1) {
  822. /* sleep override */
  823. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  824. }
  825. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  826. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  827. // Complete the cycle Tlen -> T1
  828. auto s =
  829. txns[len - 1]->GetForUpdate(read_options, "0", (std::string*)nullptr);
  830. ASSERT_TRUE(s.IsDeadlock());
  831. const uint32_t dlock_buffer_size_ = (len - 1 > 5) ? 5 : (len - 1);
  832. uint32_t curr_waiting_key = 0;
  833. TransactionID curr_txn_id = txns[0]->GetID();
  834. auto dlock_buffer = db->GetDeadlockInfoBuffer();
  835. ASSERT_EQ(dlock_buffer.size(), dlock_buffer_size_);
  836. uint32_t check_len = len;
  837. bool check_limit_flag = false;
  838. // Special case for a deadlock path that exceeds the maximum depth.
  839. if (len > 50) {
  840. check_len = 0;
  841. check_limit_flag = true;
  842. }
  843. auto dlock_entry = dlock_buffer[0].path;
  844. ASSERT_EQ(dlock_entry.size(), check_len);
  845. ASSERT_EQ(dlock_buffer[0].limit_exceeded, check_limit_flag);
  846. int64_t pre_deadlock_time = dlock_buffer[0].deadlock_time;
  847. int64_t cur_deadlock_time = 0;
  848. for (auto const& dl_path_rec : dlock_buffer) {
  849. cur_deadlock_time = dl_path_rec.deadlock_time;
  850. ASSERT_NE(cur_deadlock_time, 0);
  851. ASSERT_TRUE(cur_deadlock_time <= pre_deadlock_time);
  852. pre_deadlock_time = cur_deadlock_time;
  853. }
  854. // Iterates backwards over path verifying decreasing txn_ids.
  855. for (auto it = dlock_entry.rbegin(); it != dlock_entry.rend(); ++it) {
  856. auto dl_node = *it;
  857. ASSERT_EQ(dl_node.m_txn_id, len + curr_txn_id - 1);
  858. ASSERT_EQ(dl_node.m_cf_id, 0u);
  859. ASSERT_EQ(dl_node.m_waiting_key, std::to_string(curr_waiting_key));
  860. ASSERT_EQ(dl_node.m_exclusive, true);
  861. curr_txn_id--;
  862. if (curr_waiting_key == 0) {
  863. curr_waiting_key = len;
  864. }
  865. curr_waiting_key--;
  866. }
  867. // Rollback the last transaction.
  868. ASSERT_OK(txns[len - 1]->Rollback());
  869. delete txns[len - 1];
  870. for (auto& t : threads) {
  871. t.join();
  872. }
  873. }
  874. }
  875. TEST_P(TransactionStressTest, DeadlockStress) {
  876. const uint32_t NUM_TXN_THREADS = 10;
  877. const uint32_t NUM_KEYS = 100;
  878. const uint32_t NUM_ITERS = 1000;
  879. WriteOptions write_options;
  880. ReadOptions read_options;
  881. TransactionOptions txn_options;
  882. txn_options.lock_timeout = 1000000;
  883. txn_options.deadlock_detect = true;
  884. std::vector<std::string> keys;
  885. for (uint32_t i = 0; i < NUM_KEYS; i++) {
  886. ASSERT_OK(db->Put(write_options, Slice(std::to_string(i)), Slice("")));
  887. keys.push_back(std::to_string(i));
  888. }
  889. size_t tid = std::hash<std::thread::id>()(std::this_thread::get_id());
  890. Random rnd(static_cast<uint32_t>(tid));
  891. std::function<void(uint32_t)> stress_thread = [&](uint32_t seed) {
  892. std::default_random_engine g(seed);
  893. Transaction* txn;
  894. for (uint32_t i = 0; i < NUM_ITERS; i++) {
  895. txn = db->BeginTransaction(write_options, txn_options);
  896. auto random_keys = keys;
  897. std::shuffle(random_keys.begin(), random_keys.end(), g);
  898. // Lock keys in random order.
  899. for (const auto& k : random_keys) {
  900. // Lock mostly for shared access, but exclusive 1/4 of the time.
  901. auto s = txn->GetForUpdate(read_options, k, (std::string*)nullptr,
  902. txn->GetID() % 4 == 0);
  903. if (!s.ok()) {
  904. ASSERT_TRUE(s.IsDeadlock());
  905. ASSERT_OK(txn->Rollback());
  906. break;
  907. }
  908. }
  909. delete txn;
  910. }
  911. };
  912. std::vector<port::Thread> threads;
  913. for (uint32_t i = 0; i < NUM_TXN_THREADS; i++) {
  914. threads.emplace_back(stress_thread, rnd.Next());
  915. }
  916. for (auto& t : threads) {
  917. t.join();
  918. }
  919. }
  920. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  921. TEST_P(TransactionTest, CommitTimeBatchFailTest) {
  922. WriteOptions write_options;
  923. TransactionOptions txn_options;
  924. std::string value;
  925. Status s;
  926. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  927. ASSERT_TRUE(txn1);
  928. ASSERT_OK(txn1->GetCommitTimeWriteBatch()->Put("cat", "dog"));
  929. s = txn1->Put("foo", "bar");
  930. ASSERT_OK(s);
  931. // fails due to non-empty commit-time batch
  932. s = txn1->Commit();
  933. ASSERT_EQ(s, Status::InvalidArgument());
  934. delete txn1;
  935. }
  936. TEST_P(TransactionTest, LogMarkLeakTest) {
  937. TransactionOptions txn_options;
  938. WriteOptions write_options;
  939. options.write_buffer_size = 1024;
  940. ASSERT_OK(ReOpenNoDelete());
  941. assert(db != nullptr);
  942. Random rnd(47);
  943. std::vector<Transaction*> txns;
  944. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  945. // At the beginning there should be no log containing prepare data
  946. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  947. for (size_t i = 0; i < 100; i++) {
  948. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  949. ASSERT_OK(txn->SetName("xid" + std::to_string(i)));
  950. ASSERT_OK(txn->Put(Slice("foo" + std::to_string(i)), Slice("bar")));
  951. ASSERT_OK(txn->Prepare());
  952. ASSERT_GT(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  953. if (rnd.OneIn(5)) {
  954. txns.push_back(txn);
  955. } else {
  956. ASSERT_OK(txn->Commit());
  957. delete txn;
  958. }
  959. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  960. }
  961. for (auto txn : txns) {
  962. ASSERT_OK(txn->Commit());
  963. delete txn;
  964. }
  965. // At the end there should be no log left containing prepare data
  966. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  967. // Make sure that the underlying data structures are properly truncated and
  968. // cause not leak
  969. ASSERT_EQ(db_impl->TEST_PreparedSectionCompletedSize(), 0);
  970. ASSERT_EQ(db_impl->TEST_LogsWithPrepSize(), 0);
  971. }
  972. TEST_P(TransactionTest, SimpleTwoPhaseTransactionTest) {
  973. for (bool cwb4recovery : {true, false}) {
  974. ASSERT_OK(ReOpen());
  975. WriteOptions write_options;
  976. ReadOptions read_options;
  977. TransactionOptions txn_options;
  978. txn_options.use_only_the_last_commit_time_batch_for_recovery = cwb4recovery;
  979. std::string value;
  980. Status s;
  981. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  982. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  983. s = txn->SetName("xid");
  984. ASSERT_OK(s);
  985. ASSERT_EQ(db->GetTransactionByName("xid"), txn);
  986. // transaction put
  987. s = txn->Put(Slice("foo"), Slice("bar"));
  988. ASSERT_OK(s);
  989. ASSERT_EQ(1, txn->GetNumPuts());
  990. // regular db put
  991. s = db->Put(write_options, Slice("foo2"), Slice("bar2"));
  992. ASSERT_OK(s);
  993. ASSERT_EQ(1, txn->GetNumPuts());
  994. // regular db read
  995. ASSERT_OK(db->Get(read_options, "foo2", &value));
  996. ASSERT_EQ(value, "bar2");
  997. // commit time put
  998. if (cwb4recovery) {
  999. ASSERT_OK(
  1000. txn->GetCommitTimeWriteBatch()->Put(Slice("gtid"), Slice("dogs")));
  1001. ASSERT_OK(
  1002. txn->GetCommitTimeWriteBatch()->Put(Slice("gtid2"), Slice("cats")));
  1003. }
  1004. // nothing has been prepped yet
  1005. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  1006. s = txn->Prepare();
  1007. ASSERT_OK(s);
  1008. // data not im mem yet
  1009. s = db->Get(read_options, Slice("foo"), &value);
  1010. ASSERT_TRUE(s.IsNotFound());
  1011. s = db->Get(read_options, Slice("gtid"), &value);
  1012. ASSERT_TRUE(s.IsNotFound());
  1013. // find trans in list of prepared transactions
  1014. std::vector<Transaction*> prepared_trans;
  1015. db->GetAllPreparedTransactions(&prepared_trans);
  1016. ASSERT_EQ(prepared_trans.size(), 1);
  1017. ASSERT_EQ(prepared_trans.front()->GetName(), "xid");
  1018. auto log_containing_prep =
  1019. db_impl->TEST_FindMinLogContainingOutstandingPrep();
  1020. ASSERT_GT(log_containing_prep, 0);
  1021. // make commit
  1022. s = txn->Commit();
  1023. ASSERT_OK(s);
  1024. // value is now available
  1025. s = db->Get(read_options, "foo", &value);
  1026. ASSERT_OK(s);
  1027. ASSERT_EQ(value, "bar");
  1028. // we already committed
  1029. s = txn->Commit();
  1030. ASSERT_EQ(s, Status::InvalidArgument());
  1031. // no longer is prepared results
  1032. db->GetAllPreparedTransactions(&prepared_trans);
  1033. ASSERT_EQ(prepared_trans.size(), 0);
  1034. ASSERT_EQ(db->GetTransactionByName("xid"), nullptr);
  1035. // heap should not care about prepared section anymore
  1036. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  1037. switch (txn_db_options.write_policy) {
  1038. case WRITE_COMMITTED:
  1039. // but now our memtable should be referencing the prep section
  1040. ASSERT_GE(log_containing_prep, db_impl->MinLogNumberToKeep());
  1041. ASSERT_EQ(log_containing_prep,
  1042. db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1043. break;
  1044. case WRITE_PREPARED:
  1045. case WRITE_UNPREPARED:
  1046. // In these modes memtable do not ref the prep sections
  1047. ASSERT_EQ(0, db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1048. break;
  1049. default:
  1050. assert(false);
  1051. }
  1052. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  1053. // After flush the recoverable state must be visible
  1054. if (cwb4recovery) {
  1055. s = db->Get(read_options, "gtid", &value);
  1056. ASSERT_OK(s);
  1057. ASSERT_EQ(value, "dogs");
  1058. s = db->Get(read_options, "gtid2", &value);
  1059. ASSERT_OK(s);
  1060. ASSERT_EQ(value, "cats");
  1061. }
  1062. // after memtable flush we can now relese the log
  1063. ASSERT_GT(db_impl->MinLogNumberToKeep(), log_containing_prep);
  1064. ASSERT_EQ(0, db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1065. delete txn;
  1066. if (cwb4recovery) {
  1067. // kill and reopen to trigger recovery
  1068. s = ReOpenNoDelete();
  1069. ASSERT_OK(s);
  1070. assert(db != nullptr);
  1071. s = db->Get(read_options, "gtid", &value);
  1072. ASSERT_OK(s);
  1073. ASSERT_EQ(value, "dogs");
  1074. s = db->Get(read_options, "gtid2", &value);
  1075. ASSERT_OK(s);
  1076. ASSERT_EQ(value, "cats");
  1077. }
  1078. }
  1079. }
  1080. TEST_P(TransactionTest, TwoPhaseNameTest) {
  1081. Status s;
  1082. WriteOptions write_options;
  1083. TransactionOptions txn_options;
  1084. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  1085. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  1086. Transaction* txn3 = db->BeginTransaction(write_options, txn_options);
  1087. ASSERT_TRUE(txn3);
  1088. delete txn3;
  1089. // cant prepare txn without name
  1090. s = txn1->Prepare();
  1091. ASSERT_EQ(s, Status::InvalidArgument());
  1092. // name too short
  1093. s = txn1->SetName("");
  1094. ASSERT_EQ(s, Status::InvalidArgument());
  1095. // name too long
  1096. s = txn1->SetName(std::string(513, 'x'));
  1097. ASSERT_EQ(s, Status::InvalidArgument());
  1098. // valid set name
  1099. s = txn1->SetName("name1");
  1100. ASSERT_OK(s);
  1101. // cant have duplicate name
  1102. s = txn2->SetName("name1");
  1103. ASSERT_EQ(s, Status::InvalidArgument());
  1104. // shouldn't be able to prepare
  1105. s = txn2->Prepare();
  1106. ASSERT_EQ(s, Status::InvalidArgument());
  1107. // valid name set
  1108. s = txn2->SetName("name2");
  1109. ASSERT_OK(s);
  1110. // cant reset name
  1111. s = txn2->SetName("name3");
  1112. ASSERT_EQ(s, Status::InvalidArgument());
  1113. ASSERT_EQ(txn1->GetName(), "name1");
  1114. ASSERT_EQ(txn2->GetName(), "name2");
  1115. s = txn1->Prepare();
  1116. ASSERT_OK(s);
  1117. // can't rename after prepare
  1118. s = txn1->SetName("name4");
  1119. ASSERT_EQ(s, Status::InvalidArgument());
  1120. ASSERT_OK(txn1->Rollback());
  1121. ASSERT_OK(txn2->Rollback());
  1122. delete txn1;
  1123. delete txn2;
  1124. }
  1125. TEST_P(TransactionTest, TwoPhaseEmptyWriteTest) {
  1126. for (bool cwb4recovery : {true, false}) {
  1127. for (bool test_with_empty_wal : {true, false}) {
  1128. if (!cwb4recovery && test_with_empty_wal) {
  1129. continue;
  1130. }
  1131. ASSERT_OK(ReOpen());
  1132. Status s;
  1133. std::string value;
  1134. WriteOptions write_options;
  1135. ReadOptions read_options;
  1136. TransactionOptions txn_options;
  1137. txn_options.use_only_the_last_commit_time_batch_for_recovery =
  1138. cwb4recovery;
  1139. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  1140. ASSERT_TRUE(txn1);
  1141. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  1142. ASSERT_TRUE(txn2);
  1143. s = txn1->SetName("joe");
  1144. ASSERT_OK(s);
  1145. s = txn2->SetName("bob");
  1146. ASSERT_OK(s);
  1147. s = txn1->Prepare();
  1148. ASSERT_OK(s);
  1149. s = txn1->Commit();
  1150. ASSERT_OK(s);
  1151. delete txn1;
  1152. if (cwb4recovery) {
  1153. ASSERT_OK(
  1154. txn2->GetCommitTimeWriteBatch()->Put(Slice("foo"), Slice("bar")));
  1155. }
  1156. s = txn2->Prepare();
  1157. ASSERT_OK(s);
  1158. s = txn2->Commit();
  1159. ASSERT_OK(s);
  1160. delete txn2;
  1161. if (cwb4recovery) {
  1162. if (test_with_empty_wal) {
  1163. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1164. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  1165. // After flush the state must be visible
  1166. s = db->Get(read_options, "foo", &value);
  1167. ASSERT_OK(s);
  1168. ASSERT_EQ(value, "bar");
  1169. }
  1170. ASSERT_OK(db->FlushWAL(true));
  1171. // kill and reopen to trigger recovery
  1172. s = ReOpenNoDelete();
  1173. ASSERT_OK(s);
  1174. assert(db != nullptr);
  1175. s = db->Get(read_options, "foo", &value);
  1176. ASSERT_OK(s);
  1177. ASSERT_EQ(value, "bar");
  1178. }
  1179. }
  1180. }
  1181. }
  1182. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1183. TEST_P(TransactionStressTest, TwoPhaseExpirationTest) {
  1184. Status s;
  1185. WriteOptions write_options;
  1186. TransactionOptions txn_options;
  1187. txn_options.expiration = 500; // 500ms
  1188. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  1189. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  1190. ASSERT_TRUE(txn1);
  1191. ASSERT_TRUE(txn1);
  1192. s = txn1->SetName("joe");
  1193. ASSERT_OK(s);
  1194. s = txn2->SetName("bob");
  1195. ASSERT_OK(s);
  1196. s = txn1->Prepare();
  1197. ASSERT_OK(s);
  1198. /* sleep override */
  1199. std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  1200. s = txn1->Commit();
  1201. ASSERT_OK(s);
  1202. s = txn2->Prepare();
  1203. ASSERT_EQ(s, Status::Expired());
  1204. delete txn1;
  1205. delete txn2;
  1206. }
  1207. TEST_P(TransactionTest, TwoPhaseRollbackTest) {
  1208. WriteOptions write_options;
  1209. ReadOptions read_options;
  1210. TransactionOptions txn_options;
  1211. std::string value;
  1212. Status s;
  1213. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1214. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  1215. s = txn->SetName("xid");
  1216. ASSERT_OK(s);
  1217. // transaction put
  1218. s = txn->Put(Slice("tfoo"), Slice("tbar"));
  1219. ASSERT_OK(s);
  1220. // value is readable form txn
  1221. s = txn->Get(read_options, Slice("tfoo"), &value);
  1222. ASSERT_OK(s);
  1223. ASSERT_EQ(value, "tbar");
  1224. // issue rollback
  1225. s = txn->Rollback();
  1226. ASSERT_OK(s);
  1227. // value is nolonger readable
  1228. s = txn->Get(read_options, Slice("tfoo"), &value);
  1229. ASSERT_TRUE(s.IsNotFound());
  1230. ASSERT_EQ(txn->GetNumPuts(), 0);
  1231. // put new txn values
  1232. s = txn->Put(Slice("tfoo2"), Slice("tbar2"));
  1233. ASSERT_OK(s);
  1234. // new value is readable from txn
  1235. s = txn->Get(read_options, Slice("tfoo2"), &value);
  1236. ASSERT_OK(s);
  1237. ASSERT_EQ(value, "tbar2");
  1238. s = txn->Prepare();
  1239. ASSERT_OK(s);
  1240. // flush to next wal
  1241. s = db->Put(write_options, Slice("foo"), Slice("bar"));
  1242. ASSERT_OK(s);
  1243. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  1244. // issue rollback (marker written to WAL)
  1245. s = txn->Rollback();
  1246. ASSERT_OK(s);
  1247. // value is nolonger readable
  1248. s = txn->Get(read_options, Slice("tfoo2"), &value);
  1249. ASSERT_TRUE(s.IsNotFound());
  1250. ASSERT_EQ(txn->GetNumPuts(), 0);
  1251. // make commit
  1252. s = txn->Commit();
  1253. ASSERT_EQ(s, Status::InvalidArgument());
  1254. // try rollback again
  1255. s = txn->Rollback();
  1256. ASSERT_EQ(s, Status::InvalidArgument());
  1257. delete txn;
  1258. }
  1259. TEST_P(TransactionTest, PersistentTwoPhaseTransactionTest) {
  1260. WriteOptions write_options;
  1261. write_options.sync = true;
  1262. write_options.disableWAL = false;
  1263. ReadOptions read_options;
  1264. TransactionOptions txn_options;
  1265. std::string value;
  1266. Status s;
  1267. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1268. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  1269. s = txn->SetName("xid");
  1270. ASSERT_OK(s);
  1271. ASSERT_EQ(db->GetTransactionByName("xid"), txn);
  1272. // transaction put
  1273. s = txn->Put(Slice("foo"), Slice("bar"));
  1274. ASSERT_OK(s);
  1275. ASSERT_EQ(1, txn->GetNumPuts());
  1276. // txn read
  1277. s = txn->Get(read_options, "foo", &value);
  1278. ASSERT_OK(s);
  1279. ASSERT_EQ(value, "bar");
  1280. // regular db put
  1281. s = db->Put(write_options, Slice("foo2"), Slice("bar2"));
  1282. ASSERT_OK(s);
  1283. ASSERT_EQ(1, txn->GetNumPuts());
  1284. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  1285. // regular db read
  1286. ASSERT_OK(db->Get(read_options, "foo2", &value));
  1287. ASSERT_EQ(value, "bar2");
  1288. // nothing has been prepped yet
  1289. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  1290. // prepare
  1291. s = txn->Prepare();
  1292. ASSERT_OK(s);
  1293. // still not available to db
  1294. s = db->Get(read_options, Slice("foo"), &value);
  1295. ASSERT_TRUE(s.IsNotFound());
  1296. ASSERT_OK(db->FlushWAL(false));
  1297. delete txn;
  1298. // kill and reopen
  1299. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  1300. s = ReOpenNoDelete();
  1301. ASSERT_OK(s);
  1302. assert(db != nullptr);
  1303. db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1304. // find trans in list of prepared transactions
  1305. std::vector<Transaction*> prepared_trans;
  1306. db->GetAllPreparedTransactions(&prepared_trans);
  1307. ASSERT_EQ(prepared_trans.size(), 1);
  1308. txn = prepared_trans.front();
  1309. ASSERT_TRUE(txn);
  1310. ASSERT_EQ(txn->GetName(), "xid");
  1311. ASSERT_EQ(db->GetTransactionByName("xid"), txn);
  1312. // log has been marked
  1313. auto log_containing_prep =
  1314. db_impl->TEST_FindMinLogContainingOutstandingPrep();
  1315. ASSERT_GT(log_containing_prep, 0);
  1316. // value is readable from txn
  1317. s = txn->Get(read_options, "foo", &value);
  1318. ASSERT_OK(s);
  1319. ASSERT_EQ(value, "bar");
  1320. // make commit
  1321. s = txn->Commit();
  1322. ASSERT_OK(s);
  1323. // value is now available
  1324. ASSERT_OK(db->Get(read_options, "foo", &value));
  1325. ASSERT_EQ(value, "bar");
  1326. // we already committed
  1327. s = txn->Commit();
  1328. ASSERT_EQ(s, Status::InvalidArgument());
  1329. // no longer is prepared results
  1330. prepared_trans.clear();
  1331. db->GetAllPreparedTransactions(&prepared_trans);
  1332. ASSERT_EQ(prepared_trans.size(), 0);
  1333. // transaction should no longer be visible
  1334. ASSERT_EQ(db->GetTransactionByName("xid"), nullptr);
  1335. // heap should not care about prepared section anymore
  1336. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  1337. switch (txn_db_options.write_policy) {
  1338. case WRITE_COMMITTED:
  1339. // but now our memtable should be referencing the prep section
  1340. ASSERT_EQ(log_containing_prep,
  1341. db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1342. ASSERT_GE(log_containing_prep, db_impl->MinLogNumberToKeep());
  1343. break;
  1344. case WRITE_PREPARED:
  1345. case WRITE_UNPREPARED:
  1346. // In these modes memtable do not ref the prep sections
  1347. ASSERT_EQ(0, db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1348. break;
  1349. default:
  1350. assert(false);
  1351. }
  1352. // Add a dummy record to memtable before a flush. Otherwise, the
  1353. // memtable will be empty and flush will be skipped.
  1354. s = db->Put(write_options, Slice("foo3"), Slice("bar3"));
  1355. ASSERT_OK(s);
  1356. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  1357. // after memtable flush we can now release the log
  1358. ASSERT_GT(db_impl->MinLogNumberToKeep(), log_containing_prep);
  1359. ASSERT_EQ(0, db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1360. delete txn;
  1361. // deleting transaction should unregister transaction
  1362. ASSERT_EQ(db->GetTransactionByName("xid"), nullptr);
  1363. }
  1364. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1365. // TODO this test needs to be updated with serial commits
  1366. TEST_P(TransactionTest, DISABLED_TwoPhaseMultiThreadTest) {
  1367. // mix transaction writes and regular writes
  1368. const uint32_t NUM_TXN_THREADS = 50;
  1369. std::atomic<uint32_t> txn_thread_num(0);
  1370. std::function<void()> txn_write_thread = [&]() {
  1371. uint32_t id = txn_thread_num.fetch_add(1);
  1372. WriteOptions write_options;
  1373. write_options.sync = true;
  1374. write_options.disableWAL = false;
  1375. TransactionOptions txn_options;
  1376. txn_options.lock_timeout = 1000000;
  1377. if (id % 2 == 0) {
  1378. txn_options.expiration = 1000000;
  1379. }
  1380. TransactionName name("xid_" + std::string(1, 'A' + static_cast<char>(id)));
  1381. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  1382. ASSERT_OK(txn->SetName(name));
  1383. for (int i = 0; i < 10; i++) {
  1384. std::string key(name + "_" + std::string(1, static_cast<char>('A' + i)));
  1385. ASSERT_OK(txn->Put(key, "val"));
  1386. }
  1387. ASSERT_OK(txn->Prepare());
  1388. ASSERT_OK(txn->Commit());
  1389. delete txn;
  1390. };
  1391. // assure that all thread are in the same write group
  1392. std::atomic<uint32_t> t_wait_on_prepare(0);
  1393. std::atomic<uint32_t> t_wait_on_commit(0);
  1394. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  1395. "WriteThread::JoinBatchGroup:Wait", [&](void* arg) {
  1396. auto* writer = static_cast<WriteThread::Writer*>(arg);
  1397. if (writer->ShouldWriteToWAL()) {
  1398. t_wait_on_prepare.fetch_add(1);
  1399. // wait for friends
  1400. while (t_wait_on_prepare.load() < NUM_TXN_THREADS) {
  1401. env->SleepForMicroseconds(10);
  1402. }
  1403. } else if (writer->ShouldWriteToMemtable()) {
  1404. t_wait_on_commit.fetch_add(1);
  1405. // wait for friends
  1406. while (t_wait_on_commit.load() < NUM_TXN_THREADS) {
  1407. env->SleepForMicroseconds(10);
  1408. }
  1409. } else {
  1410. FAIL();
  1411. }
  1412. });
  1413. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  1414. // do all the writes
  1415. std::vector<port::Thread> threads;
  1416. for (uint32_t i = 0; i < NUM_TXN_THREADS; i++) {
  1417. threads.emplace_back(txn_write_thread);
  1418. }
  1419. for (auto& t : threads) {
  1420. t.join();
  1421. }
  1422. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  1423. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
  1424. ReadOptions read_options;
  1425. std::string value;
  1426. Status s;
  1427. for (uint32_t t = 0; t < NUM_TXN_THREADS; t++) {
  1428. TransactionName name("xid_" + std::string(1, 'A' + static_cast<char>(t)));
  1429. for (int i = 0; i < 10; i++) {
  1430. std::string key(name + "_" + std::string(1, static_cast<char>('A' + i)));
  1431. s = db->Get(read_options, key, &value);
  1432. ASSERT_OK(s);
  1433. ASSERT_EQ(value, "val");
  1434. }
  1435. }
  1436. }
  1437. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1438. TEST_P(TransactionStressTest, TwoPhaseLongPrepareTest) {
  1439. WriteOptions write_options;
  1440. write_options.sync = true;
  1441. write_options.disableWAL = false;
  1442. ReadOptions read_options;
  1443. TransactionOptions txn_options;
  1444. std::string value;
  1445. Status s;
  1446. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  1447. s = txn->SetName("bob");
  1448. ASSERT_OK(s);
  1449. // transaction put
  1450. s = txn->Put(Slice("foo"), Slice("bar"));
  1451. ASSERT_OK(s);
  1452. // prepare
  1453. s = txn->Prepare();
  1454. ASSERT_OK(s);
  1455. delete txn;
  1456. for (int i = 0; i < 1000; i++) {
  1457. std::string key(i, 'k');
  1458. std::string val(1000, 'v');
  1459. assert(db != nullptr);
  1460. s = db->Put(write_options, key, val);
  1461. ASSERT_OK(s);
  1462. if (i % 29 == 0) {
  1463. // crash
  1464. fault_fs->SetFilesystemActive(false);
  1465. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  1466. ASSERT_OK(ReOpenNoDelete());
  1467. } else if (i % 37 == 0) {
  1468. // close
  1469. ASSERT_OK(ReOpenNoDelete());
  1470. }
  1471. }
  1472. // commit old txn
  1473. txn = db->GetTransactionByName("bob");
  1474. ASSERT_TRUE(txn);
  1475. s = txn->Commit();
  1476. ASSERT_OK(s);
  1477. // verify data txn data
  1478. s = db->Get(read_options, "foo", &value);
  1479. ASSERT_EQ(s, Status::OK());
  1480. ASSERT_EQ(value, "bar");
  1481. // verify non txn data
  1482. for (int i = 0; i < 1000; i++) {
  1483. std::string key(i, 'k');
  1484. std::string val(1000, 'v');
  1485. s = db->Get(read_options, key, &value);
  1486. ASSERT_EQ(s, Status::OK());
  1487. ASSERT_EQ(value, val);
  1488. }
  1489. delete txn;
  1490. }
  1491. TEST_P(TransactionTest, TwoPhaseSequenceTest) {
  1492. WriteOptions write_options;
  1493. write_options.sync = true;
  1494. write_options.disableWAL = false;
  1495. ReadOptions read_options;
  1496. TransactionOptions txn_options;
  1497. std::string value;
  1498. Status s;
  1499. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  1500. s = txn->SetName("xid");
  1501. ASSERT_OK(s);
  1502. // transaction put
  1503. s = txn->Put(Slice("foo"), Slice("bar"));
  1504. ASSERT_OK(s);
  1505. s = txn->Put(Slice("foo2"), Slice("bar2"));
  1506. ASSERT_OK(s);
  1507. s = txn->Put(Slice("foo3"), Slice("bar3"));
  1508. ASSERT_OK(s);
  1509. s = txn->Put(Slice("foo4"), Slice("bar4"));
  1510. ASSERT_OK(s);
  1511. // prepare
  1512. s = txn->Prepare();
  1513. ASSERT_OK(s);
  1514. // make commit
  1515. s = txn->Commit();
  1516. ASSERT_OK(s);
  1517. delete txn;
  1518. // kill and reopen
  1519. fault_fs->SetFilesystemActive(false);
  1520. ASSERT_OK(ReOpenNoDelete());
  1521. assert(db != nullptr);
  1522. // value is now available
  1523. s = db->Get(read_options, "foo4", &value);
  1524. ASSERT_EQ(s, Status::OK());
  1525. ASSERT_EQ(value, "bar4");
  1526. }
  1527. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  1528. TEST_P(TransactionTest, TwoPhaseDoubleRecoveryTest) {
  1529. WriteOptions write_options;
  1530. write_options.sync = true;
  1531. write_options.disableWAL = false;
  1532. ReadOptions read_options;
  1533. TransactionOptions txn_options;
  1534. std::string value;
  1535. Status s;
  1536. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  1537. s = txn->SetName("a");
  1538. ASSERT_OK(s);
  1539. // transaction put
  1540. s = txn->Put(Slice("foo"), Slice("bar"));
  1541. ASSERT_OK(s);
  1542. // prepare
  1543. s = txn->Prepare();
  1544. ASSERT_OK(s);
  1545. delete txn;
  1546. // kill and reopen
  1547. fault_fs->SetFilesystemActive(false);
  1548. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  1549. ASSERT_OK(ReOpenNoDelete());
  1550. // commit old txn
  1551. assert(db != nullptr); // Make clang analyze happy.
  1552. txn = db->GetTransactionByName("a");
  1553. assert(txn != nullptr);
  1554. s = txn->Commit();
  1555. ASSERT_OK(s);
  1556. s = db->Get(read_options, "foo", &value);
  1557. ASSERT_EQ(s, Status::OK());
  1558. ASSERT_EQ(value, "bar");
  1559. delete txn;
  1560. txn = db->BeginTransaction(write_options, txn_options);
  1561. s = txn->SetName("b");
  1562. ASSERT_OK(s);
  1563. s = txn->Put(Slice("foo2"), Slice("bar2"));
  1564. ASSERT_OK(s);
  1565. s = txn->Prepare();
  1566. ASSERT_OK(s);
  1567. s = txn->Commit();
  1568. ASSERT_OK(s);
  1569. delete txn;
  1570. // kill and reopen
  1571. fault_fs->SetFilesystemActive(false);
  1572. ASSERT_OK(ReOpenNoDelete());
  1573. assert(db != nullptr);
  1574. // value is now available
  1575. s = db->Get(read_options, "foo", &value);
  1576. ASSERT_EQ(s, Status::OK());
  1577. ASSERT_EQ(value, "bar");
  1578. s = db->Get(read_options, "foo2", &value);
  1579. ASSERT_EQ(s, Status::OK());
  1580. ASSERT_EQ(value, "bar2");
  1581. }
  1582. TEST_P(TransactionTest, TwoPhaseLogRollingTest) {
  1583. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1584. Status s;
  1585. std::string v;
  1586. ColumnFamilyHandle *cfa, *cfb;
  1587. // Create 2 new column families
  1588. ColumnFamilyOptions cf_options;
  1589. s = db->CreateColumnFamily(cf_options, "CFA", &cfa);
  1590. ASSERT_OK(s);
  1591. s = db->CreateColumnFamily(cf_options, "CFB", &cfb);
  1592. ASSERT_OK(s);
  1593. WriteOptions wopts;
  1594. wopts.disableWAL = false;
  1595. wopts.sync = true;
  1596. TransactionOptions topts1;
  1597. Transaction* txn1 = db->BeginTransaction(wopts, topts1);
  1598. s = txn1->SetName("xid1");
  1599. ASSERT_OK(s);
  1600. TransactionOptions topts2;
  1601. Transaction* txn2 = db->BeginTransaction(wopts, topts2);
  1602. s = txn2->SetName("xid2");
  1603. ASSERT_OK(s);
  1604. // transaction put in two column families
  1605. s = txn1->Put(cfa, "ka1", "va1");
  1606. ASSERT_OK(s);
  1607. // transaction put in two column families
  1608. s = txn2->Put(cfa, "ka2", "va2");
  1609. ASSERT_OK(s);
  1610. s = txn2->Put(cfb, "kb2", "vb2");
  1611. ASSERT_OK(s);
  1612. // write prep section to wal
  1613. s = txn1->Prepare();
  1614. ASSERT_OK(s);
  1615. // our log should be in the heap
  1616. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(),
  1617. txn1->GetLogNumber());
  1618. ASSERT_EQ(db_impl->TEST_LogfileNumber(), txn1->GetLastLogNumber());
  1619. // flush default cf to crate new log
  1620. s = db->Put(wopts, "foo", "bar");
  1621. ASSERT_OK(s);
  1622. s = db_impl->TEST_FlushMemTable(true);
  1623. ASSERT_OK(s);
  1624. // make sure we are on a new log
  1625. ASSERT_GT(db_impl->TEST_LogfileNumber(), txn1->GetLastLogNumber());
  1626. // put txn2 prep section in this log
  1627. s = txn2->Prepare();
  1628. ASSERT_OK(s);
  1629. ASSERT_EQ(db_impl->TEST_LogfileNumber(), txn2->GetLastLogNumber());
  1630. // heap should still see first log
  1631. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(),
  1632. txn1->GetLogNumber());
  1633. // commit txn1
  1634. s = txn1->Commit();
  1635. ASSERT_OK(s);
  1636. // heap should now show txn2s log
  1637. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(),
  1638. txn2->GetLogNumber());
  1639. switch (txn_db_options.write_policy) {
  1640. case WRITE_COMMITTED:
  1641. // we should see txn1s log refernced by the memtables
  1642. ASSERT_EQ(txn1->GetLogNumber(),
  1643. db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1644. break;
  1645. case WRITE_PREPARED:
  1646. case WRITE_UNPREPARED:
  1647. // In these modes memtable do not ref the prep sections
  1648. ASSERT_EQ(0, db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1649. break;
  1650. default:
  1651. assert(false);
  1652. }
  1653. // flush default cf to crate new log
  1654. s = db->Put(wopts, "foo", "bar2");
  1655. ASSERT_OK(s);
  1656. s = db_impl->TEST_FlushMemTable(true);
  1657. ASSERT_OK(s);
  1658. // make sure we are on a new log
  1659. ASSERT_GT(db_impl->TEST_LogfileNumber(), txn2->GetLastLogNumber());
  1660. // commit txn2
  1661. s = txn2->Commit();
  1662. ASSERT_OK(s);
  1663. // heap should not show any logs
  1664. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  1665. switch (txn_db_options.write_policy) {
  1666. case WRITE_COMMITTED:
  1667. // should show the first txn log
  1668. ASSERT_EQ(txn1->GetLogNumber(),
  1669. db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1670. break;
  1671. case WRITE_PREPARED:
  1672. case WRITE_UNPREPARED:
  1673. // In these modes memtable do not ref the prep sections
  1674. ASSERT_EQ(0, db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1675. break;
  1676. default:
  1677. assert(false);
  1678. }
  1679. // flush only cfa memtable
  1680. s = db_impl->TEST_FlushMemTable(true, false, cfa);
  1681. ASSERT_OK(s);
  1682. switch (txn_db_options.write_policy) {
  1683. case WRITE_COMMITTED:
  1684. // should show the first txn log
  1685. ASSERT_EQ(txn2->GetLogNumber(),
  1686. db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1687. break;
  1688. case WRITE_PREPARED:
  1689. case WRITE_UNPREPARED:
  1690. // In these modes memtable do not ref the prep sections
  1691. ASSERT_EQ(0, db_impl->TEST_FindMinPrepLogReferencedByMemTable());
  1692. break;
  1693. default:
  1694. assert(false);
  1695. }
  1696. // flush only cfb memtable
  1697. s = db_impl->TEST_FlushMemTable(true, false, cfb);
  1698. ASSERT_OK(s);
  1699. // should show not dependency on logs
  1700. ASSERT_EQ(db_impl->TEST_FindMinPrepLogReferencedByMemTable(), 0);
  1701. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(), 0);
  1702. delete txn1;
  1703. delete txn2;
  1704. delete cfa;
  1705. delete cfb;
  1706. }
  1707. TEST_P(TransactionTest, TwoPhaseLogRollingTest2) {
  1708. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1709. Status s;
  1710. ColumnFamilyHandle *cfa, *cfb;
  1711. ColumnFamilyOptions cf_options;
  1712. s = db->CreateColumnFamily(cf_options, "CFA", &cfa);
  1713. ASSERT_OK(s);
  1714. s = db->CreateColumnFamily(cf_options, "CFB", &cfb);
  1715. ASSERT_OK(s);
  1716. WriteOptions wopts;
  1717. wopts.disableWAL = false;
  1718. wopts.sync = true;
  1719. auto cfh_a = static_cast_with_check<ColumnFamilyHandleImpl>(cfa);
  1720. auto cfh_b = static_cast_with_check<ColumnFamilyHandleImpl>(cfb);
  1721. TransactionOptions topts1;
  1722. Transaction* txn1 = db->BeginTransaction(wopts, topts1);
  1723. s = txn1->SetName("xid1");
  1724. ASSERT_OK(s);
  1725. s = txn1->Put(cfa, "boys", "girls1");
  1726. ASSERT_OK(s);
  1727. Transaction* txn2 = db->BeginTransaction(wopts, topts1);
  1728. s = txn2->SetName("xid2");
  1729. ASSERT_OK(s);
  1730. s = txn2->Put(cfb, "up", "down1");
  1731. ASSERT_OK(s);
  1732. // prepre transaction in LOG A
  1733. s = txn1->Prepare();
  1734. ASSERT_OK(s);
  1735. // prepre transaction in LOG A
  1736. s = txn2->Prepare();
  1737. ASSERT_OK(s);
  1738. // regular put so that mem table can actually be flushed for log rolling
  1739. s = db->Put(wopts, "cats", "dogs1");
  1740. ASSERT_OK(s);
  1741. auto prepare_log_no = txn1->GetLastLogNumber();
  1742. // roll to LOG B
  1743. s = db_impl->TEST_FlushMemTable(true);
  1744. ASSERT_OK(s);
  1745. // now we pause background work so that
  1746. // imm()s are not flushed before we can check their status
  1747. s = db_impl->PauseBackgroundWork();
  1748. ASSERT_OK(s);
  1749. ASSERT_GT(db_impl->TEST_LogfileNumber(), prepare_log_no);
  1750. switch (txn_db_options.write_policy) {
  1751. case WRITE_COMMITTED:
  1752. // This cf is empty and should ref the latest log
  1753. ASSERT_GT(cfh_a->cfd()->GetLogNumber(), prepare_log_no);
  1754. ASSERT_EQ(cfh_a->cfd()->GetLogNumber(), db_impl->TEST_LogfileNumber());
  1755. break;
  1756. case WRITE_PREPARED:
  1757. case WRITE_UNPREPARED:
  1758. // This cf is not flushed yet and should ref the log that has its data
  1759. ASSERT_EQ(cfh_a->cfd()->GetLogNumber(), prepare_log_no);
  1760. break;
  1761. default:
  1762. assert(false);
  1763. }
  1764. ASSERT_EQ(db_impl->TEST_FindMinLogContainingOutstandingPrep(),
  1765. txn1->GetLogNumber());
  1766. ASSERT_EQ(db_impl->TEST_FindMinPrepLogReferencedByMemTable(), 0);
  1767. // commit in LOG B
  1768. s = txn1->Commit();
  1769. ASSERT_OK(s);
  1770. switch (txn_db_options.write_policy) {
  1771. case WRITE_COMMITTED:
  1772. ASSERT_EQ(db_impl->TEST_FindMinPrepLogReferencedByMemTable(),
  1773. prepare_log_no);
  1774. break;
  1775. case WRITE_PREPARED:
  1776. case WRITE_UNPREPARED:
  1777. // In these modes memtable do not ref the prep sections
  1778. ASSERT_EQ(db_impl->TEST_FindMinPrepLogReferencedByMemTable(), 0);
  1779. break;
  1780. default:
  1781. assert(false);
  1782. }
  1783. ASSERT_TRUE(!db_impl->TEST_UnableToReleaseOldestLog());
  1784. // request a flush for all column families such that the earliest
  1785. // alive log file can be killed
  1786. ASSERT_OK(db_impl->TEST_SwitchWAL());
  1787. // log cannot be flushed because txn2 has not been commited
  1788. ASSERT_TRUE(!db_impl->TEST_IsLogGettingFlushed());
  1789. ASSERT_TRUE(db_impl->TEST_UnableToReleaseOldestLog());
  1790. // assert that cfa has a flush requested
  1791. ASSERT_TRUE(cfh_a->cfd()->imm()->HasFlushRequested());
  1792. switch (txn_db_options.write_policy) {
  1793. case WRITE_COMMITTED:
  1794. // cfb should not be flushed becuse it has no data from LOG A
  1795. ASSERT_TRUE(!cfh_b->cfd()->imm()->HasFlushRequested());
  1796. break;
  1797. case WRITE_PREPARED:
  1798. case WRITE_UNPREPARED:
  1799. // cfb should be flushed becuse it has prepared data from LOG A
  1800. ASSERT_TRUE(cfh_b->cfd()->imm()->HasFlushRequested());
  1801. break;
  1802. default:
  1803. assert(false);
  1804. }
  1805. // cfb now has data from LOG A
  1806. s = txn2->Commit();
  1807. ASSERT_OK(s);
  1808. ASSERT_OK(db_impl->TEST_SwitchWAL());
  1809. ASSERT_TRUE(!db_impl->TEST_UnableToReleaseOldestLog());
  1810. // we should see that cfb now has a flush requested
  1811. ASSERT_TRUE(cfh_b->cfd()->imm()->HasFlushRequested());
  1812. // all data in LOG A resides in a memtable that has been
  1813. // requested for a flush
  1814. ASSERT_TRUE(db_impl->TEST_IsLogGettingFlushed());
  1815. delete txn1;
  1816. delete txn2;
  1817. delete cfa;
  1818. delete cfb;
  1819. }
  1820. TEST_P(TransactionTest, TwoPhaseLogMultiMemtableFlush) {
  1821. // Test that min log number to keep is tracked correctly when
  1822. // multiple memtables are flushed together.
  1823. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1824. // So that two immutable memtable won't stall writes.
  1825. ASSERT_OK(db->SetOptions({{"max_write_buffer_number", "4"}}));
  1826. // Pause flush.
  1827. ASSERT_OK(db->PauseBackgroundWork());
  1828. WriteOptions wopts;
  1829. wopts.disableWAL = false;
  1830. wopts.sync = true;
  1831. TransactionOptions topts;
  1832. Transaction* txn1 = db->BeginTransaction(wopts, topts);
  1833. ASSERT_OK(txn1->Put("key1", "val1"));
  1834. ASSERT_OK(txn1->SetName("xid1"));
  1835. ASSERT_OK(txn1->Prepare());
  1836. ASSERT_OK(txn1->Commit());
  1837. delete txn1;
  1838. ASSERT_OK(db_impl->TEST_SwitchMemtable());
  1839. Transaction* txn2 = db->BeginTransaction(wopts, topts);
  1840. ASSERT_OK(txn2->Put("key2", "val2"));
  1841. ASSERT_OK(txn2->SetName("xid2"));
  1842. ASSERT_OK(txn2->Prepare());
  1843. ASSERT_OK(txn2->Commit());
  1844. delete txn2;
  1845. ASSERT_OK(db_impl->TEST_SwitchMemtable());
  1846. ASSERT_OK(db->ContinueBackgroundWork());
  1847. ASSERT_OK(db->Flush({}));
  1848. uint64_t cur_wal_num = db_impl->TEST_GetCurrentLogNumber();
  1849. // All non-active WALs should be obsolete.
  1850. ASSERT_EQ(cur_wal_num, db_impl->MinLogNumberToKeep());
  1851. }
  1852. /*
  1853. * 1) use prepare to keep first log around to determine starting sequence
  1854. * during recovery.
  1855. * 2) insert many values, skipping wal, to increase seqid.
  1856. * 3) insert final value into wal
  1857. * 4) recover and see that final value was properly recovered - not
  1858. * hidden behind improperly summed sequence ids
  1859. */
  1860. TEST_P(TransactionTest, TwoPhaseOutOfOrderDelete) {
  1861. // WAL recycling incompatible with disableWAL (below)
  1862. options.recycle_log_file_num = 0;
  1863. ASSERT_OK(ReOpenNoDelete());
  1864. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  1865. WriteOptions wal_on, wal_off;
  1866. wal_on.sync = true;
  1867. wal_on.disableWAL = false;
  1868. wal_off.disableWAL = true;
  1869. ReadOptions read_options;
  1870. TransactionOptions txn_options;
  1871. std::string value;
  1872. Status s;
  1873. Transaction* txn1 = db->BeginTransaction(wal_on, txn_options);
  1874. s = txn1->SetName("1");
  1875. ASSERT_OK(s);
  1876. s = db->Put(wal_on, "first", "first");
  1877. ASSERT_OK(s);
  1878. s = txn1->Put(Slice("dummy"), Slice("dummy"));
  1879. ASSERT_OK(s);
  1880. s = txn1->Prepare();
  1881. ASSERT_OK(s);
  1882. s = db->Put(wal_off, "cats", "dogs1");
  1883. ASSERT_OK(s);
  1884. s = db->Put(wal_off, "cats", "dogs2");
  1885. ASSERT_OK(s);
  1886. s = db->Put(wal_off, "cats", "dogs3");
  1887. ASSERT_OK(s);
  1888. s = db_impl->TEST_FlushMemTable(true);
  1889. ASSERT_OK(s);
  1890. s = db->Put(wal_on, "cats", "dogs4");
  1891. ASSERT_OK(s);
  1892. ASSERT_OK(db->FlushWAL(false));
  1893. // kill and reopen
  1894. fault_fs->SetFilesystemActive(false);
  1895. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  1896. ASSERT_OK(ReOpenNoDelete());
  1897. assert(db != nullptr);
  1898. s = db->Get(read_options, "first", &value);
  1899. ASSERT_OK(s);
  1900. ASSERT_EQ(value, "first");
  1901. s = db->Get(read_options, "cats", &value);
  1902. ASSERT_OK(s);
  1903. ASSERT_EQ(value, "dogs4");
  1904. }
  1905. TEST_P(TransactionTest, FirstWriteTest) {
  1906. WriteOptions write_options;
  1907. // Test conflict checking against the very first write to a db.
  1908. // The transaction's snapshot will have seq 1 and the following write
  1909. // will have sequence 1.
  1910. Status s = db->Put(write_options, "A", "a");
  1911. Transaction* txn = db->BeginTransaction(write_options);
  1912. txn->SetSnapshot();
  1913. ASSERT_OK(s);
  1914. s = txn->Put("A", "b");
  1915. ASSERT_OK(s);
  1916. delete txn;
  1917. }
  1918. TEST_P(TransactionTest, FirstWriteTest2) {
  1919. WriteOptions write_options;
  1920. Transaction* txn = db->BeginTransaction(write_options);
  1921. txn->SetSnapshot();
  1922. // Test conflict checking against the very first write to a db.
  1923. // The transaction's snapshot is a seq 0 while the following write
  1924. // will have sequence 1.
  1925. Status s = db->Put(write_options, "A", "a");
  1926. ASSERT_OK(s);
  1927. s = txn->Put("A", "b");
  1928. ASSERT_TRUE(s.IsBusy());
  1929. delete txn;
  1930. }
  1931. TEST_P(TransactionTest, WriteOptionsTest) {
  1932. WriteOptions write_options;
  1933. write_options.sync = true;
  1934. write_options.disableWAL = true;
  1935. Transaction* txn = db->BeginTransaction(write_options);
  1936. ASSERT_TRUE(txn);
  1937. ASSERT_TRUE(txn->GetWriteOptions()->sync);
  1938. write_options.sync = false;
  1939. txn->SetWriteOptions(write_options);
  1940. ASSERT_FALSE(txn->GetWriteOptions()->sync);
  1941. ASSERT_TRUE(txn->GetWriteOptions()->disableWAL);
  1942. delete txn;
  1943. }
  1944. TEST_P(TransactionTest, WriteConflictTest) {
  1945. WriteOptions write_options;
  1946. ReadOptions read_options;
  1947. std::string value;
  1948. Status s;
  1949. ASSERT_OK(db->Put(write_options, "foo", "A"));
  1950. ASSERT_OK(db->Put(write_options, "foo2", "B"));
  1951. Transaction* txn = db->BeginTransaction(write_options);
  1952. ASSERT_TRUE(txn);
  1953. s = txn->Put("foo", "A2");
  1954. ASSERT_OK(s);
  1955. s = txn->Put("foo2", "B2");
  1956. ASSERT_OK(s);
  1957. // This Put outside of a transaction will conflict with the previous write
  1958. s = db->Put(write_options, "foo", "xxx");
  1959. ASSERT_TRUE(s.IsTimedOut());
  1960. s = db->Get(read_options, "foo", &value);
  1961. ASSERT_EQ(value, "A");
  1962. s = txn->Commit();
  1963. ASSERT_OK(s);
  1964. ASSERT_OK(db->Get(read_options, "foo", &value));
  1965. ASSERT_EQ(value, "A2");
  1966. ASSERT_OK(db->Get(read_options, "foo2", &value));
  1967. ASSERT_EQ(value, "B2");
  1968. delete txn;
  1969. }
  1970. TEST_P(TransactionTest, WriteConflictTest2) {
  1971. WriteOptions write_options;
  1972. ReadOptions read_options;
  1973. TransactionOptions txn_options;
  1974. std::string value;
  1975. Status s;
  1976. ASSERT_OK(db->Put(write_options, "foo", "bar"));
  1977. txn_options.set_snapshot = true;
  1978. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  1979. ASSERT_TRUE(txn);
  1980. // This Put outside of a transaction will conflict with a later write
  1981. s = db->Put(write_options, "foo", "barz");
  1982. ASSERT_OK(s);
  1983. s = txn->Put("foo2", "X");
  1984. ASSERT_OK(s);
  1985. s = txn->Put("foo",
  1986. "bar2"); // Conflicts with write done after snapshot taken
  1987. ASSERT_TRUE(s.IsBusy());
  1988. s = txn->Put("foo3", "Y");
  1989. ASSERT_OK(s);
  1990. s = db->Get(read_options, "foo", &value);
  1991. ASSERT_EQ(value, "barz");
  1992. ASSERT_EQ(2, txn->GetNumKeys());
  1993. s = txn->Commit();
  1994. ASSERT_OK(s); // Txn should commit, but only write foo2 and foo3
  1995. // Verify that transaction wrote foo2 and foo3 but not foo
  1996. ASSERT_OK(db->Get(read_options, "foo", &value));
  1997. ASSERT_EQ(value, "barz");
  1998. ASSERT_OK(db->Get(read_options, "foo2", &value));
  1999. ASSERT_EQ(value, "X");
  2000. ASSERT_OK(db->Get(read_options, "foo3", &value));
  2001. ASSERT_EQ(value, "Y");
  2002. delete txn;
  2003. }
  2004. TEST_P(TransactionTest, ReadConflictTest) {
  2005. WriteOptions write_options;
  2006. ReadOptions read_options, snapshot_read_options;
  2007. TransactionOptions txn_options;
  2008. std::string value;
  2009. Status s;
  2010. ASSERT_OK(db->Put(write_options, "foo", "bar"));
  2011. ASSERT_OK(db->Put(write_options, "foo2", "bar"));
  2012. txn_options.set_snapshot = true;
  2013. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  2014. ASSERT_TRUE(txn);
  2015. txn->SetSnapshot();
  2016. snapshot_read_options.snapshot = txn->GetSnapshot();
  2017. ASSERT_OK(txn->GetForUpdate(snapshot_read_options, "foo", &value));
  2018. ASSERT_EQ(value, "bar");
  2019. // This Put outside of a transaction will conflict with the previous read
  2020. s = db->Put(write_options, "foo", "barz");
  2021. ASSERT_TRUE(s.IsTimedOut());
  2022. s = db->Get(read_options, "foo", &value);
  2023. ASSERT_EQ(value, "bar");
  2024. s = txn->Get(read_options, "foo", &value);
  2025. ASSERT_EQ(value, "bar");
  2026. s = txn->Commit();
  2027. ASSERT_OK(s);
  2028. delete txn;
  2029. }
  2030. TEST_P(TransactionTest, TxnOnlyTest) {
  2031. // Test to make sure transactions work when there are no other writes in an
  2032. // empty db.
  2033. WriteOptions write_options;
  2034. ReadOptions read_options;
  2035. std::string value;
  2036. Status s;
  2037. Transaction* txn = db->BeginTransaction(write_options);
  2038. ASSERT_TRUE(txn);
  2039. s = txn->Put("x", "y");
  2040. ASSERT_OK(s);
  2041. s = txn->Commit();
  2042. ASSERT_OK(s);
  2043. delete txn;
  2044. }
  2045. TEST_P(TransactionTest, FlushTest) {
  2046. WriteOptions write_options;
  2047. ReadOptions read_options, snapshot_read_options;
  2048. std::string value;
  2049. Status s;
  2050. ASSERT_OK(db->Put(write_options, Slice("foo"), Slice("bar")));
  2051. ASSERT_OK(db->Put(write_options, Slice("foo2"), Slice("bar")));
  2052. Transaction* txn = db->BeginTransaction(write_options);
  2053. ASSERT_TRUE(txn);
  2054. snapshot_read_options.snapshot = txn->GetSnapshot();
  2055. ASSERT_OK(txn->GetForUpdate(snapshot_read_options, "foo", &value));
  2056. ASSERT_EQ(value, "bar");
  2057. s = txn->Put(Slice("foo"), Slice("bar2"));
  2058. ASSERT_OK(s);
  2059. ASSERT_OK(txn->GetForUpdate(snapshot_read_options, "foo", &value));
  2060. ASSERT_EQ(value, "bar2");
  2061. // Put a random key so we have a memtable to flush
  2062. s = db->Put(write_options, "dummy", "dummy");
  2063. ASSERT_OK(s);
  2064. // force a memtable flush
  2065. FlushOptions flush_ops;
  2066. ASSERT_OK(db->Flush(flush_ops));
  2067. s = txn->Commit();
  2068. // txn should commit since the flushed table is still in MemtableList History
  2069. ASSERT_OK(s);
  2070. ASSERT_OK(db->Get(read_options, "foo", &value));
  2071. ASSERT_EQ(value, "bar2");
  2072. delete txn;
  2073. }
  2074. TEST_P(TransactionTest, FlushTest2) {
  2075. const size_t num_tests = 3;
  2076. for (size_t n = 0; n < num_tests; n++) {
  2077. // Test different table factories
  2078. switch (n) {
  2079. case 0:
  2080. break;
  2081. case 1:
  2082. options.table_factory.reset(new mock::MockTableFactory());
  2083. break;
  2084. case 2: {
  2085. PlainTableOptions pt_opts;
  2086. pt_opts.hash_table_ratio = 0;
  2087. options.table_factory.reset(NewPlainTableFactory(pt_opts));
  2088. break;
  2089. }
  2090. }
  2091. Status s = ReOpen();
  2092. ASSERT_OK(s);
  2093. assert(db != nullptr);
  2094. WriteOptions write_options;
  2095. ReadOptions read_options, snapshot_read_options;
  2096. TransactionOptions txn_options;
  2097. std::string value;
  2098. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  2099. ASSERT_OK(db->Put(write_options, Slice("foo"), Slice("bar")));
  2100. ASSERT_OK(db->Put(write_options, Slice("foo2"), Slice("bar2")));
  2101. ASSERT_OK(db->Put(write_options, Slice("foo3"), Slice("bar3")));
  2102. txn_options.set_snapshot = true;
  2103. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  2104. ASSERT_TRUE(txn);
  2105. snapshot_read_options.snapshot = txn->GetSnapshot();
  2106. ASSERT_OK(txn->GetForUpdate(snapshot_read_options, "foo", &value));
  2107. ASSERT_EQ(value, "bar");
  2108. s = txn->Put(Slice("foo"), Slice("bar2"));
  2109. ASSERT_OK(s);
  2110. ASSERT_OK(txn->GetForUpdate(snapshot_read_options, "foo", &value));
  2111. ASSERT_EQ(value, "bar2");
  2112. // verify foo is locked by txn
  2113. s = db->Delete(write_options, "foo");
  2114. ASSERT_TRUE(s.IsTimedOut());
  2115. s = db->Put(write_options, "Z", "z");
  2116. ASSERT_OK(s);
  2117. s = db->Put(write_options, "dummy", "dummy");
  2118. ASSERT_OK(s);
  2119. s = db->Put(write_options, "S", "s");
  2120. ASSERT_OK(s);
  2121. s = db->SingleDelete(write_options, "S");
  2122. ASSERT_OK(s);
  2123. s = txn->Delete("S");
  2124. // Should fail after encountering a write to S in memtable
  2125. ASSERT_TRUE(s.IsBusy());
  2126. // force a memtable flush
  2127. s = db_impl->TEST_FlushMemTable(true);
  2128. ASSERT_OK(s);
  2129. // Put a random key so we have a MemTable to flush
  2130. s = db->Put(write_options, "dummy", "dummy2");
  2131. ASSERT_OK(s);
  2132. // force a memtable flush
  2133. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  2134. s = db->Put(write_options, "dummy", "dummy3");
  2135. ASSERT_OK(s);
  2136. // force a memtable flush
  2137. // Since our test db has max_write_buffer_number=2, this flush will cause
  2138. // the first memtable to get purged from the MemtableList history.
  2139. ASSERT_OK(db_impl->TEST_FlushMemTable(true));
  2140. s = txn->Put("X", "Y");
  2141. // Should succeed after verifying there is no write to X in SST file
  2142. ASSERT_OK(s);
  2143. s = txn->Put("Z", "zz");
  2144. // Should fail after encountering a write to Z in SST file
  2145. ASSERT_TRUE(s.IsBusy());
  2146. s = txn->GetForUpdate(read_options, "foo2", &value);
  2147. // should succeed since key was written before txn started
  2148. ASSERT_OK(s);
  2149. // verify foo2 is locked by txn
  2150. s = db->Delete(write_options, "foo2");
  2151. ASSERT_TRUE(s.IsTimedOut());
  2152. s = txn->Delete("S");
  2153. // Should fail after encountering a write to S in SST file
  2154. ASSERT_TRUE(s.IsBusy());
  2155. // Write a bunch of keys to db to force a compaction
  2156. Random rnd(47);
  2157. for (int i = 0; i < 1000; i++) {
  2158. s = db->Put(write_options, std::to_string(i),
  2159. test::CompressibleString(&rnd, 0.8, 100, &value));
  2160. ASSERT_OK(s);
  2161. }
  2162. s = txn->Put("X", "yy");
  2163. // Should succeed after verifying there is no write to X in SST file
  2164. ASSERT_OK(s);
  2165. s = txn->Put("Z", "zzz");
  2166. // Should fail after encountering a write to Z in SST file
  2167. ASSERT_TRUE(s.IsBusy());
  2168. s = txn->Delete("S");
  2169. // Should fail after encountering a write to S in SST file
  2170. ASSERT_TRUE(s.IsBusy());
  2171. s = txn->GetForUpdate(read_options, "foo3", &value);
  2172. // should succeed since key was written before txn started
  2173. ASSERT_OK(s);
  2174. // verify foo3 is locked by txn
  2175. s = db->Delete(write_options, "foo3");
  2176. ASSERT_TRUE(s.IsTimedOut());
  2177. ASSERT_OK(db_impl->TEST_WaitForCompact());
  2178. s = txn->Commit();
  2179. ASSERT_OK(s);
  2180. // Transaction should only write the keys that succeeded.
  2181. s = db->Get(read_options, "foo", &value);
  2182. ASSERT_EQ(value, "bar2");
  2183. s = db->Get(read_options, "X", &value);
  2184. ASSERT_OK(s);
  2185. ASSERT_EQ("yy", value);
  2186. s = db->Get(read_options, "Z", &value);
  2187. ASSERT_OK(s);
  2188. ASSERT_EQ("z", value);
  2189. delete txn;
  2190. }
  2191. }
  2192. TEST_P(TransactionTest, WaitForCompactAbortOnPause) {
  2193. Status s = ReOpen();
  2194. ASSERT_OK(s);
  2195. assert(db != nullptr);
  2196. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  2197. // Pause the background jobs.
  2198. ASSERT_OK(db_impl->PauseBackgroundWork());
  2199. WaitForCompactOptions waitForCompactOptions = WaitForCompactOptions();
  2200. waitForCompactOptions.abort_on_pause = true;
  2201. s = db->WaitForCompact(waitForCompactOptions);
  2202. ASSERT_NOK(s);
  2203. ASSERT_FALSE(s.IsNotSupported());
  2204. ASSERT_TRUE(s.IsAborted());
  2205. }
  2206. TEST_P(TransactionTest, NoSnapshotTest) {
  2207. WriteOptions write_options;
  2208. ReadOptions read_options;
  2209. std::string value;
  2210. Status s;
  2211. ASSERT_OK(db->Put(write_options, "AAA", "bar"));
  2212. Transaction* txn = db->BeginTransaction(write_options);
  2213. ASSERT_TRUE(txn);
  2214. // Modify key after transaction start
  2215. ASSERT_OK(db->Put(write_options, "AAA", "bar1"));
  2216. // Read and write without a snap
  2217. ASSERT_OK(txn->GetForUpdate(read_options, "AAA", &value));
  2218. ASSERT_EQ(value, "bar1");
  2219. s = txn->Put("AAA", "bar2");
  2220. ASSERT_OK(s);
  2221. // Should commit since read/write was done after data changed
  2222. s = txn->Commit();
  2223. ASSERT_OK(s);
  2224. ASSERT_OK(txn->GetForUpdate(read_options, "AAA", &value));
  2225. ASSERT_EQ(value, "bar2");
  2226. delete txn;
  2227. }
  2228. TEST_P(TransactionTest, MultipleSnapshotTest) {
  2229. WriteOptions write_options;
  2230. ReadOptions read_options, snapshot_read_options;
  2231. std::string value;
  2232. Status s;
  2233. ASSERT_OK(db->Put(write_options, "AAA", "bar"));
  2234. ASSERT_OK(db->Put(write_options, "BBB", "bar"));
  2235. ASSERT_OK(db->Put(write_options, "CCC", "bar"));
  2236. Transaction* txn = db->BeginTransaction(write_options);
  2237. ASSERT_TRUE(txn);
  2238. ASSERT_OK(db->Put(write_options, "AAA", "bar1"));
  2239. // Read and write without a snapshot
  2240. ASSERT_OK(txn->GetForUpdate(read_options, "AAA", &value));
  2241. ASSERT_EQ(value, "bar1");
  2242. s = txn->Put("AAA", "bar2");
  2243. ASSERT_OK(s);
  2244. // Modify BBB before snapshot is taken
  2245. ASSERT_OK(db->Put(write_options, "BBB", "bar1"));
  2246. txn->SetSnapshot();
  2247. snapshot_read_options.snapshot = txn->GetSnapshot();
  2248. // Read and write with snapshot
  2249. ASSERT_OK(txn->GetForUpdate(snapshot_read_options, "BBB", &value));
  2250. ASSERT_EQ(value, "bar1");
  2251. s = txn->Put("BBB", "bar2");
  2252. ASSERT_OK(s);
  2253. ASSERT_OK(db->Put(write_options, "CCC", "bar1"));
  2254. // Set a new snapshot
  2255. txn->SetSnapshot();
  2256. snapshot_read_options.snapshot = txn->GetSnapshot();
  2257. // Read and write with snapshot
  2258. ASSERT_OK(txn->GetForUpdate(snapshot_read_options, "CCC", &value));
  2259. ASSERT_EQ(value, "bar1");
  2260. s = txn->Put("CCC", "bar2");
  2261. ASSERT_OK(s);
  2262. s = txn->GetForUpdate(read_options, "AAA", &value);
  2263. ASSERT_OK(s);
  2264. ASSERT_EQ(value, "bar2");
  2265. s = txn->GetForUpdate(read_options, "BBB", &value);
  2266. ASSERT_OK(s);
  2267. ASSERT_EQ(value, "bar2");
  2268. s = txn->GetForUpdate(read_options, "CCC", &value);
  2269. ASSERT_OK(s);
  2270. ASSERT_EQ(value, "bar2");
  2271. s = db->Get(read_options, "AAA", &value);
  2272. ASSERT_OK(s);
  2273. ASSERT_EQ(value, "bar1");
  2274. s = db->Get(read_options, "BBB", &value);
  2275. ASSERT_OK(s);
  2276. ASSERT_EQ(value, "bar1");
  2277. s = db->Get(read_options, "CCC", &value);
  2278. ASSERT_OK(s);
  2279. ASSERT_EQ(value, "bar1");
  2280. s = txn->Commit();
  2281. ASSERT_OK(s);
  2282. s = db->Get(read_options, "AAA", &value);
  2283. ASSERT_OK(s);
  2284. ASSERT_EQ(value, "bar2");
  2285. s = db->Get(read_options, "BBB", &value);
  2286. ASSERT_OK(s);
  2287. ASSERT_EQ(value, "bar2");
  2288. s = db->Get(read_options, "CCC", &value);
  2289. ASSERT_OK(s);
  2290. ASSERT_EQ(value, "bar2");
  2291. // verify that we track multiple writes to the same key at different snapshots
  2292. delete txn;
  2293. txn = db->BeginTransaction(write_options);
  2294. // Potentially conflicting writes
  2295. ASSERT_OK(db->Put(write_options, "ZZZ", "zzz"));
  2296. ASSERT_OK(db->Put(write_options, "XXX", "xxx"));
  2297. txn->SetSnapshot();
  2298. TransactionOptions txn_options;
  2299. txn_options.set_snapshot = true;
  2300. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  2301. txn2->SetSnapshot();
  2302. // This should not conflict in txn since the snapshot is later than the
  2303. // previous write (spoiler alert: it will later conflict with txn2).
  2304. s = txn->Put("ZZZ", "zzzz");
  2305. ASSERT_OK(s);
  2306. s = txn->Commit();
  2307. ASSERT_OK(s);
  2308. delete txn;
  2309. // This will conflict since the snapshot is earlier than another write to ZZZ
  2310. s = txn2->Put("ZZZ", "xxxxx");
  2311. ASSERT_TRUE(s.IsBusy());
  2312. s = txn2->Commit();
  2313. ASSERT_OK(s);
  2314. s = db->Get(read_options, "ZZZ", &value);
  2315. ASSERT_OK(s);
  2316. ASSERT_EQ(value, "zzzz");
  2317. delete txn2;
  2318. }
  2319. TEST_P(TransactionTest, ColumnFamiliesTest) {
  2320. WriteOptions write_options;
  2321. ReadOptions read_options, snapshot_read_options;
  2322. TransactionOptions txn_options;
  2323. std::string value;
  2324. Status s;
  2325. ColumnFamilyHandle *cfa, *cfb;
  2326. ColumnFamilyOptions cf_options;
  2327. // Create 2 new column families
  2328. s = db->CreateColumnFamily(cf_options, "CFA", &cfa);
  2329. ASSERT_OK(s);
  2330. s = db->CreateColumnFamily(cf_options, "CFB", &cfb);
  2331. ASSERT_OK(s);
  2332. delete cfa;
  2333. delete cfb;
  2334. delete db;
  2335. db = nullptr;
  2336. // open DB with three column families
  2337. std::vector<ColumnFamilyDescriptor> column_families;
  2338. // have to open default column family
  2339. column_families.emplace_back(kDefaultColumnFamilyName, ColumnFamilyOptions());
  2340. // open the new column families
  2341. column_families.emplace_back("CFA", ColumnFamilyOptions());
  2342. column_families.emplace_back("CFB", ColumnFamilyOptions());
  2343. std::vector<ColumnFamilyHandle*> handles;
  2344. ASSERT_OK(ReOpenNoDelete(column_families, &handles));
  2345. assert(db != nullptr);
  2346. Transaction* txn = db->BeginTransaction(write_options);
  2347. ASSERT_TRUE(txn);
  2348. txn->SetSnapshot();
  2349. snapshot_read_options.snapshot = txn->GetSnapshot();
  2350. txn_options.set_snapshot = true;
  2351. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  2352. ASSERT_TRUE(txn2);
  2353. // Write some data to the db
  2354. WriteBatch batch;
  2355. ASSERT_OK(batch.Put("foo", "foo"));
  2356. ASSERT_OK(batch.Put(handles[1], "AAA", "bar"));
  2357. ASSERT_OK(batch.Put(handles[1], "AAAZZZ", "bar"));
  2358. s = db->Write(write_options, &batch);
  2359. ASSERT_OK(s);
  2360. ASSERT_OK(db->Delete(write_options, handles[1], "AAAZZZ"));
  2361. // These keys do not conflict with existing writes since they're in
  2362. // different column families
  2363. s = txn->Delete("AAA");
  2364. ASSERT_OK(s);
  2365. s = txn->GetForUpdate(snapshot_read_options, handles[1], "foo", &value);
  2366. ASSERT_TRUE(s.IsNotFound());
  2367. Slice key_slice("AAAZZZ");
  2368. Slice value_slices[2] = {Slice("bar"), Slice("bar")};
  2369. s = txn->Put(handles[2], SliceParts(&key_slice, 1),
  2370. SliceParts(value_slices, 2));
  2371. ASSERT_OK(s);
  2372. ASSERT_EQ(3, txn->GetNumKeys());
  2373. s = txn->Commit();
  2374. ASSERT_OK(s);
  2375. s = db->Get(read_options, "AAA", &value);
  2376. ASSERT_TRUE(s.IsNotFound());
  2377. s = db->Get(read_options, handles[2], "AAAZZZ", &value);
  2378. ASSERT_EQ(value, "barbar");
  2379. Slice key_slices[3] = {Slice("AAA"), Slice("ZZ"), Slice("Z")};
  2380. Slice value_slice("barbarbar");
  2381. s = txn2->Delete(handles[2], "XXX");
  2382. ASSERT_OK(s);
  2383. s = txn2->Delete(handles[1], "XXX");
  2384. ASSERT_OK(s);
  2385. // This write will cause a conflict with the earlier batch write
  2386. s = txn2->Put(handles[1], SliceParts(key_slices, 3),
  2387. SliceParts(&value_slice, 1));
  2388. ASSERT_TRUE(s.IsBusy());
  2389. s = txn2->Commit();
  2390. ASSERT_OK(s);
  2391. // In the above the latest change to AAAZZZ in handles[1] is delete.
  2392. s = db->Get(read_options, handles[1], "AAAZZZ", &value);
  2393. ASSERT_TRUE(s.IsNotFound());
  2394. delete txn;
  2395. delete txn2;
  2396. txn = db->BeginTransaction(write_options, txn_options);
  2397. snapshot_read_options.snapshot = txn->GetSnapshot();
  2398. txn2 = db->BeginTransaction(write_options, txn_options);
  2399. ASSERT_TRUE(txn);
  2400. std::vector<ColumnFamilyHandle*> multiget_cfh = {handles[1], handles[2],
  2401. handles[0], handles[2]};
  2402. std::vector<Slice> multiget_keys = {"AAA", "AAAZZZ", "foo", "foo"};
  2403. std::vector<std::string> values(4);
  2404. std::vector<Status> results = txn->MultiGetForUpdate(
  2405. snapshot_read_options, multiget_cfh, multiget_keys, &values);
  2406. ASSERT_OK(results[0]);
  2407. ASSERT_OK(results[1]);
  2408. ASSERT_OK(results[2]);
  2409. ASSERT_TRUE(results[3].IsNotFound());
  2410. ASSERT_EQ(values[0], "bar");
  2411. ASSERT_EQ(values[1], "barbar");
  2412. ASSERT_EQ(values[2], "foo");
  2413. s = txn->SingleDelete(handles[2], "ZZZ");
  2414. ASSERT_OK(s);
  2415. s = txn->Put(handles[2], "ZZZ", "YYY");
  2416. ASSERT_OK(s);
  2417. s = txn->Put(handles[2], "ZZZ", "YYYY");
  2418. ASSERT_OK(s);
  2419. s = txn->Delete(handles[2], "ZZZ");
  2420. ASSERT_OK(s);
  2421. s = txn->Put(handles[2], "AAAZZZ", "barbarbar");
  2422. ASSERT_OK(s);
  2423. ASSERT_EQ(5, txn->GetNumKeys());
  2424. // Txn should commit
  2425. s = txn->Commit();
  2426. ASSERT_OK(s);
  2427. s = db->Get(read_options, handles[2], "ZZZ", &value);
  2428. ASSERT_TRUE(s.IsNotFound());
  2429. // Put a key which will conflict with the next txn using the previous snapshot
  2430. ASSERT_OK(db->Put(write_options, handles[2], "foo", "000"));
  2431. results = txn2->MultiGetForUpdate(snapshot_read_options, multiget_cfh,
  2432. multiget_keys, &values);
  2433. // All results should fail since there was a conflict
  2434. ASSERT_TRUE(results[0].IsBusy());
  2435. ASSERT_TRUE(results[1].IsBusy());
  2436. ASSERT_TRUE(results[2].IsBusy());
  2437. ASSERT_TRUE(results[3].IsBusy());
  2438. s = db->Get(read_options, handles[2], "foo", &value);
  2439. ASSERT_EQ(value, "000");
  2440. s = txn2->Commit();
  2441. ASSERT_OK(s);
  2442. s = db->DropColumnFamily(handles[1]);
  2443. ASSERT_OK(s);
  2444. s = db->DropColumnFamily(handles[2]);
  2445. ASSERT_OK(s);
  2446. delete txn;
  2447. delete txn2;
  2448. for (auto handle : handles) {
  2449. delete handle;
  2450. }
  2451. }
  2452. TEST_P(TransactionTest, WriteImportedColumnFamilyTest) {
  2453. WriteOptions write_options;
  2454. ReadOptions read_options;
  2455. ColumnFamilyOptions cf_options;
  2456. ImportColumnFamilyOptions import_options;
  2457. ExportImportFilesMetaData* metadata_ptr = nullptr;
  2458. ColumnFamilyHandle* import_cf = nullptr;
  2459. ColumnFamilyHandle* export_cf = nullptr;
  2460. std::string export_files_dir = test::PerThreadDBPath(env.get(), "cf_export");
  2461. std::string value;
  2462. Status s;
  2463. {
  2464. // Create a column family to export
  2465. s = db->CreateColumnFamily(cf_options, "CF_EXPORT", &export_cf);
  2466. ASSERT_OK(s);
  2467. // Write some data to the db
  2468. WriteBatch batch;
  2469. ASSERT_OK(batch.Put(export_cf, "K1", "V1"));
  2470. ASSERT_OK(batch.Put(export_cf, "K2", "V2"));
  2471. s = db->Write(write_options, &batch);
  2472. ASSERT_OK(s);
  2473. Checkpoint* checkpoint = nullptr;
  2474. s = Checkpoint::Create(db, &checkpoint);
  2475. ASSERT_OK(s);
  2476. s = checkpoint->ExportColumnFamily(export_cf, export_files_dir,
  2477. &metadata_ptr);
  2478. ASSERT_OK(s);
  2479. ASSERT_NE(metadata_ptr, nullptr);
  2480. delete checkpoint;
  2481. s = db->DropColumnFamily(export_cf);
  2482. ASSERT_OK(s);
  2483. delete export_cf;
  2484. }
  2485. {
  2486. // Create a new column family with import
  2487. s = db->CreateColumnFamilyWithImport(
  2488. cf_options, "CF_IMPORT", import_options, *metadata_ptr, &import_cf);
  2489. ASSERT_OK(s);
  2490. s = db->Get(read_options, import_cf, "K1", &value);
  2491. ASSERT_OK(s);
  2492. ASSERT_EQ(value, "V1");
  2493. s = db->Get(read_options, import_cf, "K2", &value);
  2494. ASSERT_OK(s);
  2495. ASSERT_EQ(value, "V2");
  2496. // Wirte a new key-value pair
  2497. Transaction* txn = db->BeginTransaction(write_options);
  2498. ASSERT_TRUE(txn);
  2499. s = txn->Put(import_cf, "K3", "V3");
  2500. ASSERT_OK(s);
  2501. s = txn->Commit();
  2502. ASSERT_OK(s);
  2503. delete txn;
  2504. s = db->Get(read_options, import_cf, "K3", &value);
  2505. ASSERT_OK(s);
  2506. ASSERT_EQ(value, "V3");
  2507. s = db->DropColumnFamily(import_cf);
  2508. ASSERT_OK(s);
  2509. delete import_cf;
  2510. }
  2511. delete metadata_ptr;
  2512. EXPECT_OK(DestroyDir(env.get(), export_files_dir));
  2513. }
  2514. TEST_P(TransactionTest, MultiGetBatchedTest) {
  2515. WriteOptions write_options;
  2516. ReadOptions read_options, snapshot_read_options;
  2517. TransactionOptions txn_options;
  2518. std::string value;
  2519. Status s;
  2520. ColumnFamilyHandle* cf;
  2521. ColumnFamilyOptions cf_options;
  2522. // Create a new column families
  2523. s = db->CreateColumnFamily(cf_options, "CF", &cf);
  2524. ASSERT_OK(s);
  2525. delete cf;
  2526. delete db;
  2527. db = nullptr;
  2528. // open DB with three column families
  2529. std::vector<ColumnFamilyDescriptor> column_families;
  2530. // have to open default column family
  2531. column_families.emplace_back(kDefaultColumnFamilyName, ColumnFamilyOptions());
  2532. // open the new column families
  2533. cf_options.merge_operator = MergeOperators::CreateStringAppendOperator();
  2534. column_families.emplace_back("CF", cf_options);
  2535. std::vector<ColumnFamilyHandle*> handles;
  2536. options.merge_operator = MergeOperators::CreateStringAppendOperator();
  2537. ASSERT_OK(ReOpenNoDelete(column_families, &handles));
  2538. assert(db != nullptr);
  2539. // Write some data to the db
  2540. WriteBatch batch;
  2541. ASSERT_OK(batch.Put(handles[1], "aaa", "val1"));
  2542. ASSERT_OK(batch.Put(handles[1], "bbb", "val2"));
  2543. ASSERT_OK(batch.Put(handles[1], "ccc", "val3"));
  2544. ASSERT_OK(batch.Put(handles[1], "ddd", "foo"));
  2545. ASSERT_OK(batch.Put(handles[1], "eee", "val5"));
  2546. ASSERT_OK(batch.Put(handles[1], "fff", "val6"));
  2547. ASSERT_OK(batch.Merge(handles[1], "ggg", "foo"));
  2548. s = db->Write(write_options, &batch);
  2549. ASSERT_OK(s);
  2550. Transaction* txn = db->BeginTransaction(write_options);
  2551. ASSERT_TRUE(txn);
  2552. txn->SetSnapshot();
  2553. snapshot_read_options.snapshot = txn->GetSnapshot();
  2554. txn_options.set_snapshot = true;
  2555. // Write some data to the db
  2556. s = txn->Delete(handles[1], "bbb");
  2557. ASSERT_OK(s);
  2558. s = txn->Put(handles[1], "ccc", "val3_new");
  2559. ASSERT_OK(s);
  2560. s = txn->Merge(handles[1], "ddd", "bar");
  2561. ASSERT_OK(s);
  2562. std::vector<Slice> keys = {"aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg"};
  2563. std::vector<PinnableSlice> values(keys.size());
  2564. std::vector<Status> statuses(keys.size());
  2565. txn->MultiGet(snapshot_read_options, handles[1], keys.size(), keys.data(),
  2566. values.data(), statuses.data());
  2567. ASSERT_TRUE(statuses[0].ok());
  2568. ASSERT_EQ(values[0], "val1");
  2569. ASSERT_TRUE(statuses[1].IsNotFound());
  2570. ASSERT_TRUE(statuses[2].ok());
  2571. ASSERT_EQ(values[2], "val3_new");
  2572. ASSERT_TRUE(statuses[3].ok());
  2573. ASSERT_EQ(values[3], "foo,bar");
  2574. ASSERT_TRUE(statuses[4].ok());
  2575. ASSERT_EQ(values[4], "val5");
  2576. ASSERT_TRUE(statuses[5].ok());
  2577. ASSERT_EQ(values[5], "val6");
  2578. ASSERT_TRUE(statuses[6].ok());
  2579. ASSERT_EQ(values[6], "foo");
  2580. delete txn;
  2581. for (auto handle : handles) {
  2582. delete handle;
  2583. }
  2584. }
  2585. // This test calls WriteBatchWithIndex::MultiGetFromBatchAndDB with a large
  2586. // number of keys, i.e greater than MultiGetContext::MAX_BATCH_SIZE, which is
  2587. // is 32. This forces autovector allocations in the MultiGet code paths
  2588. // to use std::vector in addition to stack allocations. The MultiGet keys
  2589. // includes Merges, which are handled specially in MultiGetFromBatchAndDB by
  2590. // allocating an autovector of MergeContexts
  2591. TEST_P(TransactionTest, MultiGetLargeBatchedTest) {
  2592. WriteOptions write_options;
  2593. ReadOptions read_options, snapshot_read_options;
  2594. std::string value;
  2595. Status s;
  2596. ColumnFamilyHandle* cf;
  2597. ColumnFamilyOptions cf_options;
  2598. std::vector<std::string> key_str;
  2599. for (int i = 0; i < 100; ++i) {
  2600. key_str.emplace_back(std::to_string(i));
  2601. }
  2602. // Create a new column families
  2603. s = db->CreateColumnFamily(cf_options, "CF", &cf);
  2604. ASSERT_OK(s);
  2605. delete cf;
  2606. delete db;
  2607. db = nullptr;
  2608. // open DB with three column families
  2609. std::vector<ColumnFamilyDescriptor> column_families;
  2610. // have to open default column family
  2611. column_families.emplace_back(kDefaultColumnFamilyName, ColumnFamilyOptions());
  2612. // open the new column families
  2613. cf_options.merge_operator = MergeOperators::CreateStringAppendOperator();
  2614. column_families.emplace_back("CF", cf_options);
  2615. std::vector<ColumnFamilyHandle*> handles;
  2616. options.merge_operator = MergeOperators::CreateStringAppendOperator();
  2617. ASSERT_OK(ReOpenNoDelete(column_families, &handles));
  2618. assert(db != nullptr);
  2619. // Write some data to the db
  2620. WriteBatch batch;
  2621. for (int i = 0; i < 3 * MultiGetContext::MAX_BATCH_SIZE; ++i) {
  2622. std::string val = "val" + std::to_string(i);
  2623. ASSERT_OK(batch.Put(handles[1], key_str[i], val));
  2624. }
  2625. s = db->Write(write_options, &batch);
  2626. ASSERT_OK(s);
  2627. WriteBatchWithIndex wb;
  2628. // Write some data to the db
  2629. s = wb.Delete(handles[1], std::to_string(1));
  2630. ASSERT_OK(s);
  2631. s = wb.Put(handles[1], std::to_string(2), "new_val" + std::to_string(2));
  2632. ASSERT_OK(s);
  2633. // Write a lot of merges so when we call MultiGetFromBatchAndDB later on,
  2634. // it is forced to use std::vector in ROCKSDB_NAMESPACE::autovector to
  2635. // allocate MergeContexts. The number of merges needs to be >
  2636. // MultiGetContext::MAX_BATCH_SIZE
  2637. for (int i = 8; i < MultiGetContext::MAX_BATCH_SIZE + 24; ++i) {
  2638. s = wb.Merge(handles[1], std::to_string(i), "merge");
  2639. ASSERT_OK(s);
  2640. }
  2641. // MultiGet a lot of keys in order to force std::vector reallocations
  2642. std::vector<Slice> keys;
  2643. for (int i = 0; i < MultiGetContext::MAX_BATCH_SIZE + 32; ++i) {
  2644. keys.emplace_back(key_str[i]);
  2645. }
  2646. std::vector<PinnableSlice> values(keys.size());
  2647. std::vector<Status> statuses(keys.size());
  2648. wb.MultiGetFromBatchAndDB(db, snapshot_read_options, handles[1], keys.size(),
  2649. keys.data(), values.data(), statuses.data(), false);
  2650. for (size_t i = 0; i < keys.size(); ++i) {
  2651. if (i == 1) {
  2652. ASSERT_TRUE(statuses[1].IsNotFound());
  2653. } else if (i == 2) {
  2654. ASSERT_TRUE(statuses[2].ok());
  2655. ASSERT_EQ(values[2], "new_val" + std::to_string(2));
  2656. } else if (i >= 8 && i < 56) {
  2657. ASSERT_TRUE(statuses[i].ok());
  2658. ASSERT_EQ(values[i], "val" + std::to_string(i) + ",merge");
  2659. } else {
  2660. ASSERT_TRUE(statuses[i].ok());
  2661. if (values[i] != "val" + std::to_string(i)) {
  2662. ASSERT_EQ(values[i], "val" + std::to_string(i));
  2663. }
  2664. }
  2665. }
  2666. for (auto handle : handles) {
  2667. delete handle;
  2668. }
  2669. }
  2670. TEST_P(TransactionTest, MultiGetSnapshot) {
  2671. WriteOptions write_options;
  2672. TransactionOptions transaction_options;
  2673. Transaction* txn1 = db->BeginTransaction(write_options, transaction_options);
  2674. Slice key = "foo";
  2675. Status s = txn1->Put(key, "bar");
  2676. ASSERT_OK(s);
  2677. s = txn1->SetName("test");
  2678. ASSERT_OK(s);
  2679. s = txn1->Prepare();
  2680. ASSERT_OK(s);
  2681. // Get snapshot between prepare and commit
  2682. // Un-committed data should be invisible to other transactions
  2683. const Snapshot* s1 = db->GetSnapshot();
  2684. s = txn1->Commit();
  2685. ASSERT_OK(s);
  2686. delete txn1;
  2687. Transaction* txn2 = db->BeginTransaction(write_options, transaction_options);
  2688. ReadOptions read_options;
  2689. read_options.snapshot = s1;
  2690. std::vector<Slice> keys;
  2691. std::vector<PinnableSlice> values(1);
  2692. std::vector<Status> statuses(1);
  2693. keys.push_back(key);
  2694. auto cfd = db->DefaultColumnFamily();
  2695. txn2->MultiGet(read_options, cfd, 1, keys.data(), values.data(),
  2696. statuses.data());
  2697. ASSERT_TRUE(statuses[0].IsNotFound());
  2698. delete txn2;
  2699. db->ReleaseSnapshot(s1);
  2700. }
  2701. TEST_P(TransactionTest, ColumnFamiliesTest2) {
  2702. WriteOptions write_options;
  2703. ReadOptions read_options, snapshot_read_options;
  2704. std::string value;
  2705. Status s;
  2706. ColumnFamilyHandle *one, *two;
  2707. ColumnFamilyOptions cf_options;
  2708. // Create 2 new column families
  2709. s = db->CreateColumnFamily(cf_options, "ONE", &one);
  2710. ASSERT_OK(s);
  2711. s = db->CreateColumnFamily(cf_options, "TWO", &two);
  2712. ASSERT_OK(s);
  2713. Transaction* txn1 = db->BeginTransaction(write_options);
  2714. ASSERT_TRUE(txn1);
  2715. Transaction* txn2 = db->BeginTransaction(write_options);
  2716. ASSERT_TRUE(txn2);
  2717. s = txn1->Put(one, "X", "1");
  2718. ASSERT_OK(s);
  2719. s = txn1->Put(two, "X", "2");
  2720. ASSERT_OK(s);
  2721. s = txn1->Put("X", "0");
  2722. ASSERT_OK(s);
  2723. s = txn2->Put(one, "X", "11");
  2724. ASSERT_TRUE(s.IsTimedOut());
  2725. s = txn1->Commit();
  2726. ASSERT_OK(s);
  2727. // Drop first column family
  2728. s = db->DropColumnFamily(one);
  2729. ASSERT_OK(s);
  2730. // Should fail since column family was dropped.
  2731. s = txn2->Commit();
  2732. ASSERT_OK(s);
  2733. delete txn1;
  2734. txn1 = db->BeginTransaction(write_options);
  2735. ASSERT_TRUE(txn1);
  2736. // Should fail since column family was dropped
  2737. s = txn1->Put(one, "X", "111");
  2738. ASSERT_TRUE(s.IsInvalidArgument());
  2739. s = txn1->Put(two, "X", "222");
  2740. ASSERT_OK(s);
  2741. s = txn1->Put("X", "000");
  2742. ASSERT_OK(s);
  2743. s = txn1->Commit();
  2744. ASSERT_OK(s);
  2745. s = db->Get(read_options, two, "X", &value);
  2746. ASSERT_OK(s);
  2747. ASSERT_EQ("222", value);
  2748. s = db->Get(read_options, "X", &value);
  2749. ASSERT_OK(s);
  2750. ASSERT_EQ("000", value);
  2751. s = db->DropColumnFamily(two);
  2752. ASSERT_OK(s);
  2753. delete txn1;
  2754. delete txn2;
  2755. delete one;
  2756. delete two;
  2757. }
  2758. TEST_P(TransactionTest, EmptyTest) {
  2759. WriteOptions write_options;
  2760. ReadOptions read_options;
  2761. std::string value;
  2762. Status s;
  2763. s = db->Put(write_options, "aaa", "aaa");
  2764. ASSERT_OK(s);
  2765. Transaction* txn = db->BeginTransaction(write_options);
  2766. s = txn->Commit();
  2767. ASSERT_OK(s);
  2768. delete txn;
  2769. txn = db->BeginTransaction(write_options);
  2770. ASSERT_OK(txn->Rollback());
  2771. delete txn;
  2772. txn = db->BeginTransaction(write_options);
  2773. s = txn->GetForUpdate(read_options, "aaa", &value);
  2774. ASSERT_EQ(value, "aaa");
  2775. s = txn->Commit();
  2776. ASSERT_OK(s);
  2777. delete txn;
  2778. txn = db->BeginTransaction(write_options);
  2779. txn->SetSnapshot();
  2780. s = txn->GetForUpdate(read_options, "aaa", &value);
  2781. ASSERT_EQ(value, "aaa");
  2782. // Conflicts with previous GetForUpdate
  2783. s = db->Put(write_options, "aaa", "xxx");
  2784. ASSERT_TRUE(s.IsTimedOut());
  2785. // transaction expired!
  2786. s = txn->Commit();
  2787. ASSERT_OK(s);
  2788. delete txn;
  2789. }
  2790. TEST_P(TransactionTest, PredicateManyPreceders) {
  2791. WriteOptions write_options;
  2792. ReadOptions read_options1, read_options2;
  2793. TransactionOptions txn_options;
  2794. std::string value;
  2795. Status s;
  2796. txn_options.set_snapshot = true;
  2797. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  2798. read_options1.snapshot = txn1->GetSnapshot();
  2799. Transaction* txn2 = db->BeginTransaction(write_options);
  2800. txn2->SetSnapshot();
  2801. read_options2.snapshot = txn2->GetSnapshot();
  2802. std::vector<Slice> multiget_keys = {"1", "2", "3"};
  2803. std::vector<std::string> multiget_values;
  2804. std::vector<Status> results =
  2805. txn1->MultiGetForUpdate(read_options1, multiget_keys, &multiget_values);
  2806. ASSERT_EQ(results.size(), 3);
  2807. ASSERT_TRUE(results[0].IsNotFound());
  2808. ASSERT_TRUE(results[1].IsNotFound());
  2809. ASSERT_TRUE(results[2].IsNotFound());
  2810. s = txn2->Put("2", "x"); // Conflict's with txn1's MultiGetForUpdate
  2811. ASSERT_TRUE(s.IsTimedOut());
  2812. ASSERT_OK(txn2->Rollback());
  2813. multiget_values.clear();
  2814. results =
  2815. txn1->MultiGetForUpdate(read_options1, multiget_keys, &multiget_values);
  2816. ASSERT_EQ(results.size(), 3);
  2817. ASSERT_TRUE(results[0].IsNotFound());
  2818. ASSERT_TRUE(results[1].IsNotFound());
  2819. ASSERT_TRUE(results[2].IsNotFound());
  2820. s = txn1->Commit();
  2821. ASSERT_OK(s);
  2822. delete txn1;
  2823. delete txn2;
  2824. txn1 = db->BeginTransaction(write_options, txn_options);
  2825. read_options1.snapshot = txn1->GetSnapshot();
  2826. txn2 = db->BeginTransaction(write_options, txn_options);
  2827. read_options2.snapshot = txn2->GetSnapshot();
  2828. s = txn1->Put("4", "x");
  2829. ASSERT_OK(s);
  2830. s = txn2->Delete("4"); // conflict
  2831. ASSERT_TRUE(s.IsTimedOut());
  2832. s = txn1->Commit();
  2833. ASSERT_OK(s);
  2834. s = txn2->GetForUpdate(read_options2, "4", &value);
  2835. ASSERT_TRUE(s.IsBusy());
  2836. ASSERT_OK(txn2->Rollback());
  2837. delete txn1;
  2838. delete txn2;
  2839. }
  2840. TEST_P(TransactionTest, LostUpdate) {
  2841. WriteOptions write_options;
  2842. ReadOptions read_options, read_options1, read_options2;
  2843. TransactionOptions txn_options;
  2844. std::string value;
  2845. Status s;
  2846. // Test 2 transactions writing to the same key in multiple orders and
  2847. // with/without snapshots
  2848. Transaction* txn1 = db->BeginTransaction(write_options);
  2849. Transaction* txn2 = db->BeginTransaction(write_options);
  2850. s = txn1->Put("1", "1");
  2851. ASSERT_OK(s);
  2852. s = txn2->Put("1", "2"); // conflict
  2853. ASSERT_TRUE(s.IsTimedOut());
  2854. s = txn2->Commit();
  2855. ASSERT_OK(s);
  2856. s = txn1->Commit();
  2857. ASSERT_OK(s);
  2858. s = db->Get(read_options, "1", &value);
  2859. ASSERT_OK(s);
  2860. ASSERT_EQ("1", value);
  2861. delete txn1;
  2862. delete txn2;
  2863. txn_options.set_snapshot = true;
  2864. txn1 = db->BeginTransaction(write_options, txn_options);
  2865. read_options1.snapshot = txn1->GetSnapshot();
  2866. txn2 = db->BeginTransaction(write_options, txn_options);
  2867. read_options2.snapshot = txn2->GetSnapshot();
  2868. s = txn1->Put("1", "3");
  2869. ASSERT_OK(s);
  2870. s = txn2->Put("1", "4"); // conflict
  2871. ASSERT_TRUE(s.IsTimedOut());
  2872. s = txn1->Commit();
  2873. ASSERT_OK(s);
  2874. s = txn2->Commit();
  2875. ASSERT_OK(s);
  2876. s = db->Get(read_options, "1", &value);
  2877. ASSERT_OK(s);
  2878. ASSERT_EQ("3", value);
  2879. delete txn1;
  2880. delete txn2;
  2881. txn1 = db->BeginTransaction(write_options, txn_options);
  2882. read_options1.snapshot = txn1->GetSnapshot();
  2883. txn2 = db->BeginTransaction(write_options, txn_options);
  2884. read_options2.snapshot = txn2->GetSnapshot();
  2885. s = txn1->Put("1", "5");
  2886. ASSERT_OK(s);
  2887. s = txn1->Commit();
  2888. ASSERT_OK(s);
  2889. s = txn2->Put("1", "6");
  2890. ASSERT_TRUE(s.IsBusy());
  2891. s = txn2->Commit();
  2892. ASSERT_OK(s);
  2893. s = db->Get(read_options, "1", &value);
  2894. ASSERT_OK(s);
  2895. ASSERT_EQ("5", value);
  2896. delete txn1;
  2897. delete txn2;
  2898. txn1 = db->BeginTransaction(write_options, txn_options);
  2899. read_options1.snapshot = txn1->GetSnapshot();
  2900. txn2 = db->BeginTransaction(write_options, txn_options);
  2901. read_options2.snapshot = txn2->GetSnapshot();
  2902. s = txn1->Put("1", "7");
  2903. ASSERT_OK(s);
  2904. s = txn1->Commit();
  2905. ASSERT_OK(s);
  2906. txn2->SetSnapshot();
  2907. s = txn2->Put("1", "8");
  2908. ASSERT_OK(s);
  2909. s = txn2->Commit();
  2910. ASSERT_OK(s);
  2911. s = db->Get(read_options, "1", &value);
  2912. ASSERT_OK(s);
  2913. ASSERT_EQ("8", value);
  2914. delete txn1;
  2915. delete txn2;
  2916. txn1 = db->BeginTransaction(write_options);
  2917. txn2 = db->BeginTransaction(write_options);
  2918. s = txn1->Put("1", "9");
  2919. ASSERT_OK(s);
  2920. s = txn1->Commit();
  2921. ASSERT_OK(s);
  2922. s = txn2->Put("1", "10");
  2923. ASSERT_OK(s);
  2924. s = txn2->Commit();
  2925. ASSERT_OK(s);
  2926. delete txn1;
  2927. delete txn2;
  2928. s = db->Get(read_options, "1", &value);
  2929. ASSERT_OK(s);
  2930. ASSERT_EQ(value, "10");
  2931. }
  2932. TEST_P(TransactionTest, UntrackedWrites) {
  2933. if (txn_db_options.write_policy == WRITE_UNPREPARED) {
  2934. // TODO(lth): For WriteUnprepared, validate that untracked writes are
  2935. // not supported.
  2936. return;
  2937. }
  2938. WriteOptions write_options;
  2939. ReadOptions read_options;
  2940. std::string value;
  2941. Status s;
  2942. // Verify transaction rollback works for untracked keys.
  2943. Transaction* txn = db->BeginTransaction(write_options);
  2944. txn->SetSnapshot();
  2945. s = txn->PutUntracked("untracked", "0");
  2946. ASSERT_OK(s);
  2947. ASSERT_OK(txn->Rollback());
  2948. s = db->Get(read_options, "untracked", &value);
  2949. ASSERT_TRUE(s.IsNotFound());
  2950. delete txn;
  2951. txn = db->BeginTransaction(write_options);
  2952. txn->SetSnapshot();
  2953. s = db->Put(write_options, "untracked", "x");
  2954. ASSERT_OK(s);
  2955. // Untracked writes should succeed even though key was written after snapshot
  2956. s = txn->PutUntracked("untracked", "1");
  2957. ASSERT_OK(s);
  2958. s = txn->PutEntityUntracked(db->DefaultColumnFamily(), "untracked",
  2959. {{"hello", "world"}});
  2960. ASSERT_OK(s);
  2961. s = txn->MergeUntracked("untracked", "2");
  2962. ASSERT_OK(s);
  2963. s = txn->DeleteUntracked("untracked");
  2964. ASSERT_OK(s);
  2965. // Conflict
  2966. s = txn->Put("untracked", "3");
  2967. ASSERT_TRUE(s.IsBusy());
  2968. s = txn->PutEntity(db->DefaultColumnFamily(), "untracked", {{"foo", "bar"}});
  2969. ASSERT_TRUE(s.IsBusy());
  2970. s = txn->Commit();
  2971. ASSERT_OK(s);
  2972. s = db->Get(read_options, "untracked", &value);
  2973. ASSERT_TRUE(s.IsNotFound());
  2974. delete txn;
  2975. }
  2976. TEST_P(TransactionTest, ExpiredTransaction) {
  2977. WriteOptions write_options;
  2978. ReadOptions read_options;
  2979. TransactionOptions txn_options;
  2980. std::string value;
  2981. Status s;
  2982. // Set txn expiration timeout to 0 microseconds (expires instantly)
  2983. txn_options.expiration = 0;
  2984. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  2985. s = txn1->Put("X", "1");
  2986. ASSERT_OK(s);
  2987. s = txn1->Put("Y", "1");
  2988. ASSERT_OK(s);
  2989. Transaction* txn2 = db->BeginTransaction(write_options);
  2990. // txn2 should be able to write to X since txn1 has expired
  2991. s = txn2->Put("X", "2");
  2992. ASSERT_OK(s);
  2993. s = txn2->Commit();
  2994. ASSERT_OK(s);
  2995. s = db->Get(read_options, "X", &value);
  2996. ASSERT_OK(s);
  2997. ASSERT_EQ("2", value);
  2998. s = txn1->Put("Z", "1");
  2999. ASSERT_OK(s);
  3000. // txn1 should fail to commit since it is expired
  3001. s = txn1->Commit();
  3002. ASSERT_TRUE(s.IsExpired());
  3003. s = db->Get(read_options, "Y", &value);
  3004. ASSERT_TRUE(s.IsNotFound());
  3005. s = db->Get(read_options, "Z", &value);
  3006. ASSERT_TRUE(s.IsNotFound());
  3007. delete txn1;
  3008. delete txn2;
  3009. }
  3010. TEST_P(TransactionTest, ReinitializeTest) {
  3011. WriteOptions write_options;
  3012. ReadOptions read_options;
  3013. TransactionOptions txn_options;
  3014. std::string value;
  3015. Status s;
  3016. // Set txn expiration timeout to 0 microseconds (expires instantly)
  3017. txn_options.expiration = 0;
  3018. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  3019. // Reinitialize transaction to no long expire
  3020. txn_options.expiration = -1;
  3021. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3022. s = txn1->Put("Z", "z");
  3023. ASSERT_OK(s);
  3024. // Should commit since not expired
  3025. s = txn1->Commit();
  3026. ASSERT_OK(s);
  3027. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3028. s = txn1->Put("Z", "zz");
  3029. ASSERT_OK(s);
  3030. // Reinitilize txn1 and verify that Z gets unlocked
  3031. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3032. Transaction* txn2 = db->BeginTransaction(write_options, txn_options, nullptr);
  3033. s = txn2->Put("Z", "zzz");
  3034. ASSERT_OK(s);
  3035. s = txn2->Commit();
  3036. ASSERT_OK(s);
  3037. delete txn2;
  3038. s = db->Get(read_options, "Z", &value);
  3039. ASSERT_OK(s);
  3040. ASSERT_EQ(value, "zzz");
  3041. // Verify snapshots get reinitialized correctly
  3042. txn1->SetSnapshot();
  3043. s = txn1->Put("Z", "zzzz");
  3044. ASSERT_OK(s);
  3045. s = txn1->Commit();
  3046. ASSERT_OK(s);
  3047. s = db->Get(read_options, "Z", &value);
  3048. ASSERT_OK(s);
  3049. ASSERT_EQ(value, "zzzz");
  3050. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3051. const Snapshot* snapshot = txn1->GetSnapshot();
  3052. ASSERT_FALSE(snapshot);
  3053. txn_options.set_snapshot = true;
  3054. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3055. snapshot = txn1->GetSnapshot();
  3056. ASSERT_TRUE(snapshot);
  3057. s = txn1->Put("Z", "a");
  3058. ASSERT_OK(s);
  3059. ASSERT_OK(txn1->Rollback());
  3060. s = txn1->Put("Y", "y");
  3061. ASSERT_OK(s);
  3062. txn_options.set_snapshot = false;
  3063. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3064. snapshot = txn1->GetSnapshot();
  3065. ASSERT_FALSE(snapshot);
  3066. s = txn1->Put("X", "x");
  3067. ASSERT_OK(s);
  3068. s = txn1->Commit();
  3069. ASSERT_OK(s);
  3070. s = db->Get(read_options, "Z", &value);
  3071. ASSERT_OK(s);
  3072. ASSERT_EQ(value, "zzzz");
  3073. s = db->Get(read_options, "Y", &value);
  3074. ASSERT_TRUE(s.IsNotFound());
  3075. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3076. s = txn1->SetName("name");
  3077. ASSERT_OK(s);
  3078. s = txn1->Prepare();
  3079. ASSERT_OK(s);
  3080. s = txn1->Commit();
  3081. ASSERT_OK(s);
  3082. txn1 = db->BeginTransaction(write_options, txn_options, txn1);
  3083. s = txn1->SetName("name");
  3084. ASSERT_OK(s);
  3085. delete txn1;
  3086. }
  3087. TEST_P(TransactionTest, Rollback) {
  3088. WriteOptions write_options;
  3089. ReadOptions read_options;
  3090. TransactionOptions txn_options;
  3091. std::string value;
  3092. Status s;
  3093. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  3094. ASSERT_OK(s);
  3095. s = txn1->Put("X", "1");
  3096. ASSERT_OK(s);
  3097. Transaction* txn2 = db->BeginTransaction(write_options);
  3098. // txn2 should not be able to write to X since txn1 has it locked
  3099. s = txn2->Put("X", "2");
  3100. ASSERT_TRUE(s.IsTimedOut());
  3101. ASSERT_OK(txn1->Rollback());
  3102. delete txn1;
  3103. // txn2 should now be able to write to X
  3104. s = txn2->Put("X", "3");
  3105. ASSERT_OK(s);
  3106. s = txn2->Commit();
  3107. ASSERT_OK(s);
  3108. s = db->Get(read_options, "X", &value);
  3109. ASSERT_OK(s);
  3110. ASSERT_EQ("3", value);
  3111. delete txn2;
  3112. }
  3113. TEST_P(TransactionTest, LockLimitTest) {
  3114. WriteOptions write_options;
  3115. ReadOptions read_options, snapshot_read_options;
  3116. TransactionOptions txn_options;
  3117. std::string value;
  3118. Status s;
  3119. delete db;
  3120. db = nullptr;
  3121. // Open DB with a lock limit of 3
  3122. txn_db_options.max_num_locks = 3;
  3123. ASSERT_OK(ReOpen());
  3124. assert(db != nullptr);
  3125. ASSERT_OK(s);
  3126. // Create a txn and verify we can only lock up to 3 keys
  3127. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  3128. ASSERT_TRUE(txn);
  3129. s = txn->Put("X", "x");
  3130. ASSERT_OK(s);
  3131. s = txn->Put("Y", "y");
  3132. ASSERT_OK(s);
  3133. s = txn->Put("Z", "z");
  3134. ASSERT_OK(s);
  3135. // lock limit reached
  3136. s = txn->Put("W", "w");
  3137. ASSERT_TRUE(s.IsLockLimit());
  3138. // re-locking same key shouldn't put us over the limit
  3139. s = txn->Put("X", "xx");
  3140. ASSERT_OK(s);
  3141. s = txn->GetForUpdate(read_options, "W", &value);
  3142. ASSERT_TRUE(s.IsLockLimit());
  3143. s = txn->GetForUpdate(read_options, "V", &value);
  3144. ASSERT_TRUE(s.IsLockLimit());
  3145. // re-locking same key shouldn't put us over the limit
  3146. s = txn->GetForUpdate(read_options, "Y", &value);
  3147. ASSERT_OK(s);
  3148. ASSERT_EQ("y", value);
  3149. s = txn->Get(read_options, "W", &value);
  3150. ASSERT_TRUE(s.IsNotFound());
  3151. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  3152. ASSERT_TRUE(txn2);
  3153. // "X" currently locked
  3154. s = txn2->Put("X", "x");
  3155. ASSERT_TRUE(s.IsTimedOut());
  3156. // lock limit reached
  3157. s = txn2->Put("M", "m");
  3158. ASSERT_TRUE(s.IsLockLimit());
  3159. s = txn->Commit();
  3160. ASSERT_OK(s);
  3161. s = db->Get(read_options, "X", &value);
  3162. ASSERT_OK(s);
  3163. ASSERT_EQ("xx", value);
  3164. s = db->Get(read_options, "W", &value);
  3165. ASSERT_TRUE(s.IsNotFound());
  3166. // Committing txn should release its locks and allow txn2 to proceed
  3167. s = txn2->Put("X", "x2");
  3168. ASSERT_OK(s);
  3169. s = txn2->Delete("X");
  3170. ASSERT_OK(s);
  3171. s = txn2->Put("M", "m");
  3172. ASSERT_OK(s);
  3173. s = txn2->Put("Z", "z2");
  3174. ASSERT_OK(s);
  3175. // lock limit reached
  3176. s = txn2->Delete("Y");
  3177. ASSERT_TRUE(s.IsLockLimit());
  3178. s = txn2->Commit();
  3179. ASSERT_OK(s);
  3180. s = db->Get(read_options, "Z", &value);
  3181. ASSERT_OK(s);
  3182. ASSERT_EQ("z2", value);
  3183. s = db->Get(read_options, "Y", &value);
  3184. ASSERT_OK(s);
  3185. ASSERT_EQ("y", value);
  3186. s = db->Get(read_options, "X", &value);
  3187. ASSERT_TRUE(s.IsNotFound());
  3188. delete txn;
  3189. delete txn2;
  3190. }
  3191. TEST_P(TransactionTest, LockLimitWithTimeoutHangTest) {
  3192. // Tests a bug where transaction can infinite-loop during lock acquiry.
  3193. // This happens when lock limit is reached and user specifies a positive
  3194. // timeout which is reached before the transaction start waiting for it.
  3195. WriteOptions write_options;
  3196. TransactionOptions txn_options;
  3197. txn_db_options.max_num_locks = 3;
  3198. txn_db_options.transaction_lock_timeout = 10; // 10ms
  3199. ASSERT_OK(ReOpen());
  3200. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  3201. ASSERT_TRUE(txn);
  3202. ASSERT_OK(txn->Put("X", "x"));
  3203. ASSERT_OK(txn->Put("Y", "y"));
  3204. ASSERT_OK(txn->Put("Z", "z"));
  3205. TransactionOptions txn2_options;
  3206. txn2_options.lock_timeout = 1; // 1ms short timeout
  3207. Transaction* txn2 = db->BeginTransaction(write_options, txn2_options);
  3208. SyncPoint::GetInstance()->SetCallBack(
  3209. "PointLockManager::AcquireWithTimeout:WaitingTxn", [&](void*) {
  3210. // Sleep for 2ms, so timeout is already passed for txn2 before waiting.
  3211. // txn2 should fail instead of waiting forever.
  3212. env->SleepForMicroseconds(2 * 1000);
  3213. });
  3214. SyncPoint::GetInstance()->EnableProcessing();
  3215. // This lock attempt should fail and return
  3216. ASSERT_TRUE(txn2->Put("W", "w").IsLockLimit());
  3217. SyncPoint::GetInstance()->DisableProcessing();
  3218. delete txn;
  3219. delete txn2;
  3220. }
  3221. TEST_P(TransactionTest, IteratorTest) {
  3222. // This test does writes without snapshot validation, and then tries to create
  3223. // iterator later, which is unsupported in write unprepared.
  3224. if (txn_db_options.write_policy == WRITE_UNPREPARED) {
  3225. return;
  3226. }
  3227. WriteOptions write_options;
  3228. ReadOptions read_options, snapshot_read_options;
  3229. std::string value;
  3230. Status s;
  3231. // Write some keys to the db
  3232. s = db->Put(write_options, "A", "a");
  3233. ASSERT_OK(s);
  3234. s = db->Put(write_options, "G", "g");
  3235. ASSERT_OK(s);
  3236. s = db->Put(write_options, "F", "f");
  3237. ASSERT_OK(s);
  3238. s = db->Put(write_options, "C", "c");
  3239. ASSERT_OK(s);
  3240. s = db->Put(write_options, "D", "d");
  3241. ASSERT_OK(s);
  3242. Transaction* txn = db->BeginTransaction(write_options);
  3243. ASSERT_TRUE(txn);
  3244. // Write some keys in a txn
  3245. s = txn->Put("B", "b");
  3246. ASSERT_OK(s);
  3247. s = txn->Put("H", "h");
  3248. ASSERT_OK(s);
  3249. s = txn->Delete("D");
  3250. ASSERT_OK(s);
  3251. s = txn->Put("E", "e");
  3252. ASSERT_OK(s);
  3253. txn->SetSnapshot();
  3254. const Snapshot* snapshot = txn->GetSnapshot();
  3255. // Write some keys to the db after the snapshot
  3256. s = db->Put(write_options, "BB", "xx");
  3257. ASSERT_OK(s);
  3258. s = db->Put(write_options, "C", "xx");
  3259. ASSERT_OK(s);
  3260. read_options.snapshot = snapshot;
  3261. Iterator* iter = txn->GetIterator(read_options);
  3262. ASSERT_OK(iter->status());
  3263. iter->SeekToFirst();
  3264. // Read all keys via iter and lock them all
  3265. std::string results[] = {"a", "b", "c", "e", "f", "g", "h"};
  3266. for (int i = 0; i < 7; i++) {
  3267. ASSERT_OK(iter->status());
  3268. ASSERT_TRUE(iter->Valid());
  3269. ASSERT_EQ(results[i], iter->value().ToString());
  3270. s = txn->GetForUpdate(read_options, iter->key(), (std::string*)nullptr);
  3271. if (i == 2) {
  3272. // "C" was modified after txn's snapshot
  3273. ASSERT_TRUE(s.IsBusy());
  3274. } else {
  3275. ASSERT_OK(s);
  3276. }
  3277. iter->Next();
  3278. }
  3279. ASSERT_FALSE(iter->Valid());
  3280. iter->Seek("G");
  3281. ASSERT_OK(iter->status());
  3282. ASSERT_TRUE(iter->Valid());
  3283. ASSERT_EQ("g", iter->value().ToString());
  3284. iter->Prev();
  3285. ASSERT_OK(iter->status());
  3286. ASSERT_TRUE(iter->Valid());
  3287. ASSERT_EQ("f", iter->value().ToString());
  3288. iter->Seek("D");
  3289. ASSERT_OK(iter->status());
  3290. ASSERT_TRUE(iter->Valid());
  3291. ASSERT_EQ("e", iter->value().ToString());
  3292. iter->Seek("C");
  3293. ASSERT_OK(iter->status());
  3294. ASSERT_TRUE(iter->Valid());
  3295. ASSERT_EQ("c", iter->value().ToString());
  3296. iter->Next();
  3297. ASSERT_OK(iter->status());
  3298. ASSERT_TRUE(iter->Valid());
  3299. ASSERT_EQ("e", iter->value().ToString());
  3300. iter->Seek("");
  3301. ASSERT_OK(iter->status());
  3302. ASSERT_TRUE(iter->Valid());
  3303. ASSERT_EQ("a", iter->value().ToString());
  3304. iter->Seek("X");
  3305. ASSERT_OK(iter->status());
  3306. ASSERT_FALSE(iter->Valid());
  3307. iter->SeekToLast();
  3308. ASSERT_OK(iter->status());
  3309. ASSERT_TRUE(iter->Valid());
  3310. ASSERT_EQ("h", iter->value().ToString());
  3311. s = txn->Commit();
  3312. ASSERT_OK(s);
  3313. delete iter;
  3314. delete txn;
  3315. }
  3316. TEST_P(TransactionTest, DisableIndexingTest) {
  3317. // Skip this test for write unprepared. It does not solely rely on WBWI for
  3318. // read your own writes, so depending on whether batches are flushed or not,
  3319. // only some writes will be visible.
  3320. //
  3321. // Also, write unprepared does not support creating iterators if there has
  3322. // been txn->Put() without snapshot validation.
  3323. if (txn_db_options.write_policy == WRITE_UNPREPARED) {
  3324. return;
  3325. }
  3326. WriteOptions write_options;
  3327. ReadOptions read_options;
  3328. std::string value;
  3329. Status s;
  3330. Transaction* txn = db->BeginTransaction(write_options);
  3331. ASSERT_TRUE(txn);
  3332. s = txn->Put("A", "a");
  3333. ASSERT_OK(s);
  3334. s = txn->Get(read_options, "A", &value);
  3335. ASSERT_OK(s);
  3336. ASSERT_EQ("a", value);
  3337. txn->DisableIndexing();
  3338. s = txn->Put("B", "b");
  3339. ASSERT_OK(s);
  3340. s = txn->Get(read_options, "B", &value);
  3341. ASSERT_TRUE(s.IsNotFound());
  3342. Iterator* iter = txn->GetIterator(read_options);
  3343. ASSERT_OK(iter->status());
  3344. iter->Seek("B");
  3345. ASSERT_OK(iter->status());
  3346. ASSERT_FALSE(iter->Valid());
  3347. s = txn->Delete("A");
  3348. s = txn->Get(read_options, "A", &value);
  3349. ASSERT_OK(s);
  3350. ASSERT_EQ("a", value);
  3351. txn->EnableIndexing();
  3352. s = txn->Put("B", "bb");
  3353. ASSERT_OK(s);
  3354. iter->Seek("B");
  3355. ASSERT_OK(iter->status());
  3356. ASSERT_TRUE(iter->Valid());
  3357. ASSERT_EQ("bb", iter->value().ToString());
  3358. s = txn->Get(read_options, "B", &value);
  3359. ASSERT_OK(s);
  3360. ASSERT_EQ("bb", value);
  3361. s = txn->Put("A", "aa");
  3362. ASSERT_OK(s);
  3363. s = txn->Get(read_options, "A", &value);
  3364. ASSERT_OK(s);
  3365. ASSERT_EQ("aa", value);
  3366. delete iter;
  3367. delete txn;
  3368. }
  3369. TEST_P(TransactionTest, SavepointTest) {
  3370. WriteOptions write_options;
  3371. ReadOptions read_options, snapshot_read_options;
  3372. std::string value;
  3373. Status s;
  3374. Transaction* txn = db->BeginTransaction(write_options);
  3375. ASSERT_TRUE(txn);
  3376. ASSERT_EQ(0, txn->GetNumPuts());
  3377. s = txn->RollbackToSavePoint();
  3378. ASSERT_TRUE(s.IsNotFound());
  3379. txn->SetSavePoint(); // 1
  3380. ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to beginning of txn
  3381. s = txn->RollbackToSavePoint();
  3382. ASSERT_TRUE(s.IsNotFound());
  3383. s = txn->Put("B", "b");
  3384. ASSERT_OK(s);
  3385. ASSERT_EQ(1, txn->GetNumPuts());
  3386. ASSERT_EQ(0, txn->GetNumDeletes());
  3387. s = txn->Commit();
  3388. ASSERT_OK(s);
  3389. s = db->Get(read_options, "B", &value);
  3390. ASSERT_OK(s);
  3391. ASSERT_EQ("b", value);
  3392. delete txn;
  3393. txn = db->BeginTransaction(write_options);
  3394. ASSERT_TRUE(txn);
  3395. s = txn->Put("A", "a");
  3396. ASSERT_OK(s);
  3397. s = txn->Put("B", "bb");
  3398. ASSERT_OK(s);
  3399. s = txn->Put("C", "c");
  3400. ASSERT_OK(s);
  3401. txn->SetSavePoint(); // 2
  3402. s = txn->Delete("B");
  3403. ASSERT_OK(s);
  3404. s = txn->Put("C", "cc");
  3405. ASSERT_OK(s);
  3406. s = txn->Put("D", "d");
  3407. ASSERT_OK(s);
  3408. ASSERT_EQ(5, txn->GetNumPuts());
  3409. ASSERT_EQ(1, txn->GetNumDeletes());
  3410. ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to 2
  3411. ASSERT_EQ(3, txn->GetNumPuts());
  3412. ASSERT_EQ(0, txn->GetNumDeletes());
  3413. s = txn->Get(read_options, "A", &value);
  3414. ASSERT_OK(s);
  3415. ASSERT_EQ("a", value);
  3416. s = txn->Get(read_options, "B", &value);
  3417. ASSERT_OK(s);
  3418. ASSERT_EQ("bb", value);
  3419. s = txn->Get(read_options, "C", &value);
  3420. ASSERT_OK(s);
  3421. ASSERT_EQ("c", value);
  3422. s = txn->Get(read_options, "D", &value);
  3423. ASSERT_TRUE(s.IsNotFound());
  3424. s = txn->Put("A", "a");
  3425. ASSERT_OK(s);
  3426. s = txn->Put("E", "e");
  3427. ASSERT_OK(s);
  3428. ASSERT_EQ(5, txn->GetNumPuts());
  3429. ASSERT_EQ(0, txn->GetNumDeletes());
  3430. // Rollback to beginning of txn
  3431. s = txn->RollbackToSavePoint();
  3432. ASSERT_TRUE(s.IsNotFound());
  3433. ASSERT_OK(txn->Rollback());
  3434. ASSERT_EQ(0, txn->GetNumPuts());
  3435. ASSERT_EQ(0, txn->GetNumDeletes());
  3436. s = txn->Get(read_options, "A", &value);
  3437. ASSERT_TRUE(s.IsNotFound());
  3438. s = txn->Get(read_options, "B", &value);
  3439. ASSERT_OK(s);
  3440. ASSERT_EQ("b", value);
  3441. s = txn->Get(read_options, "D", &value);
  3442. ASSERT_TRUE(s.IsNotFound());
  3443. s = txn->Get(read_options, "D", &value);
  3444. ASSERT_TRUE(s.IsNotFound());
  3445. s = txn->Get(read_options, "E", &value);
  3446. ASSERT_TRUE(s.IsNotFound());
  3447. s = txn->Put("A", "aa");
  3448. ASSERT_OK(s);
  3449. s = txn->Put("F", "f");
  3450. ASSERT_OK(s);
  3451. ASSERT_EQ(2, txn->GetNumPuts());
  3452. ASSERT_EQ(0, txn->GetNumDeletes());
  3453. txn->SetSavePoint(); // 3
  3454. txn->SetSavePoint(); // 4
  3455. s = txn->Put("G", "g");
  3456. ASSERT_OK(s);
  3457. s = txn->SingleDelete("F");
  3458. ASSERT_OK(s);
  3459. s = txn->Delete("B");
  3460. ASSERT_OK(s);
  3461. s = txn->Get(read_options, "A", &value);
  3462. ASSERT_OK(s);
  3463. ASSERT_EQ("aa", value);
  3464. s = txn->Get(read_options, "F", &value);
  3465. // According to db.h, doing a SingleDelete on a key that has been
  3466. // overwritten will have undefinied behavior. So it is unclear what the
  3467. // result of fetching "F" should be. The current implementation will
  3468. // return NotFound in this case.
  3469. ASSERT_TRUE(s.IsNotFound());
  3470. s = txn->Get(read_options, "B", &value);
  3471. ASSERT_TRUE(s.IsNotFound());
  3472. ASSERT_EQ(3, txn->GetNumPuts());
  3473. ASSERT_EQ(2, txn->GetNumDeletes());
  3474. ASSERT_OK(txn->RollbackToSavePoint()); // Rollback to 3
  3475. ASSERT_EQ(2, txn->GetNumPuts());
  3476. ASSERT_EQ(0, txn->GetNumDeletes());
  3477. s = txn->Get(read_options, "F", &value);
  3478. ASSERT_OK(s);
  3479. ASSERT_EQ("f", value);
  3480. s = txn->Get(read_options, "G", &value);
  3481. ASSERT_TRUE(s.IsNotFound());
  3482. s = txn->Commit();
  3483. ASSERT_OK(s);
  3484. s = db->Get(read_options, "F", &value);
  3485. ASSERT_OK(s);
  3486. ASSERT_EQ("f", value);
  3487. s = db->Get(read_options, "G", &value);
  3488. ASSERT_TRUE(s.IsNotFound());
  3489. s = db->Get(read_options, "A", &value);
  3490. ASSERT_OK(s);
  3491. ASSERT_EQ("aa", value);
  3492. s = db->Get(read_options, "B", &value);
  3493. ASSERT_OK(s);
  3494. ASSERT_EQ("b", value);
  3495. s = db->Get(read_options, "C", &value);
  3496. ASSERT_TRUE(s.IsNotFound());
  3497. s = db->Get(read_options, "D", &value);
  3498. ASSERT_TRUE(s.IsNotFound());
  3499. s = db->Get(read_options, "E", &value);
  3500. ASSERT_TRUE(s.IsNotFound());
  3501. delete txn;
  3502. }
  3503. TEST_P(TransactionTest, SavepointTest2) {
  3504. WriteOptions write_options;
  3505. ReadOptions read_options;
  3506. TransactionOptions txn_options;
  3507. Status s;
  3508. txn_options.lock_timeout = 1; // 1 ms
  3509. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  3510. ASSERT_TRUE(txn1);
  3511. s = txn1->Put("A", "");
  3512. ASSERT_OK(s);
  3513. txn1->SetSavePoint(); // 1
  3514. s = txn1->Put("A", "a");
  3515. ASSERT_OK(s);
  3516. s = txn1->Put("C", "c");
  3517. ASSERT_OK(s);
  3518. txn1->SetSavePoint(); // 2
  3519. s = txn1->Put("A", "a");
  3520. ASSERT_OK(s);
  3521. s = txn1->Put("B", "b");
  3522. ASSERT_OK(s);
  3523. ASSERT_OK(txn1->RollbackToSavePoint()); // Rollback to 2
  3524. // Verify that "A" and "C" is still locked while "B" is not
  3525. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  3526. ASSERT_TRUE(txn2);
  3527. s = txn2->Put("A", "a2");
  3528. ASSERT_TRUE(s.IsTimedOut());
  3529. s = txn2->Put("C", "c2");
  3530. ASSERT_TRUE(s.IsTimedOut());
  3531. s = txn2->Put("B", "b2");
  3532. ASSERT_OK(s);
  3533. s = txn1->Put("A", "aa");
  3534. ASSERT_OK(s);
  3535. s = txn1->Put("B", "bb");
  3536. ASSERT_TRUE(s.IsTimedOut());
  3537. s = txn2->Commit();
  3538. ASSERT_OK(s);
  3539. delete txn2;
  3540. s = txn1->Put("A", "aaa");
  3541. ASSERT_OK(s);
  3542. s = txn1->Put("B", "bbb");
  3543. ASSERT_OK(s);
  3544. s = txn1->Put("C", "ccc");
  3545. ASSERT_OK(s);
  3546. txn1->SetSavePoint(); // 3
  3547. ASSERT_OK(txn1->RollbackToSavePoint()); // Rollback to 3
  3548. // Verify that "A", "B", "C" are still locked
  3549. txn2 = db->BeginTransaction(write_options, txn_options);
  3550. ASSERT_TRUE(txn2);
  3551. s = txn2->Put("A", "a2");
  3552. ASSERT_TRUE(s.IsTimedOut());
  3553. s = txn2->Put("B", "b2");
  3554. ASSERT_TRUE(s.IsTimedOut());
  3555. s = txn2->Put("C", "c2");
  3556. ASSERT_TRUE(s.IsTimedOut());
  3557. ASSERT_OK(txn1->RollbackToSavePoint()); // Rollback to 1
  3558. // Verify that only "A" is locked
  3559. s = txn2->Put("A", "a3");
  3560. ASSERT_TRUE(s.IsTimedOut());
  3561. s = txn2->Put("B", "b3");
  3562. ASSERT_OK(s);
  3563. s = txn2->Put("C", "c3po");
  3564. ASSERT_OK(s);
  3565. s = txn1->Commit();
  3566. ASSERT_OK(s);
  3567. delete txn1;
  3568. // Verify "A" "C" "B" are no longer locked
  3569. s = txn2->Put("A", "a4");
  3570. ASSERT_OK(s);
  3571. s = txn2->Put("B", "b4");
  3572. ASSERT_OK(s);
  3573. s = txn2->Put("C", "c4");
  3574. ASSERT_OK(s);
  3575. s = txn2->Commit();
  3576. ASSERT_OK(s);
  3577. delete txn2;
  3578. }
  3579. TEST_P(TransactionTest, SavepointTest3) {
  3580. WriteOptions write_options;
  3581. ReadOptions read_options;
  3582. TransactionOptions txn_options;
  3583. Status s;
  3584. txn_options.lock_timeout = 1; // 1 ms
  3585. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  3586. ASSERT_TRUE(txn1);
  3587. s = txn1->PopSavePoint(); // No SavePoint present
  3588. ASSERT_TRUE(s.IsNotFound());
  3589. s = txn1->Put("A", "");
  3590. ASSERT_OK(s);
  3591. s = txn1->PopSavePoint(); // Still no SavePoint present
  3592. ASSERT_TRUE(s.IsNotFound());
  3593. txn1->SetSavePoint(); // 1
  3594. s = txn1->Put("A", "a");
  3595. ASSERT_OK(s);
  3596. s = txn1->PopSavePoint(); // Remove 1
  3597. ASSERT_TRUE(txn1->RollbackToSavePoint().IsNotFound());
  3598. // Verify that "A" is still locked
  3599. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  3600. ASSERT_TRUE(txn2);
  3601. s = txn2->Put("A", "a2");
  3602. ASSERT_TRUE(s.IsTimedOut());
  3603. delete txn2;
  3604. txn1->SetSavePoint(); // 2
  3605. s = txn1->Put("B", "b");
  3606. ASSERT_OK(s);
  3607. txn1->SetSavePoint(); // 3
  3608. s = txn1->Put("B", "b2");
  3609. ASSERT_OK(s);
  3610. ASSERT_OK(txn1->RollbackToSavePoint()); // Roll back to 2
  3611. s = txn1->PopSavePoint();
  3612. ASSERT_OK(s);
  3613. s = txn1->PopSavePoint();
  3614. ASSERT_TRUE(s.IsNotFound());
  3615. s = txn1->Commit();
  3616. ASSERT_OK(s);
  3617. delete txn1;
  3618. std::string value;
  3619. // tnx1 should have modified "A" to "a"
  3620. s = db->Get(read_options, "A", &value);
  3621. ASSERT_OK(s);
  3622. ASSERT_EQ("a", value);
  3623. // tnx1 should have set "B" to just "b"
  3624. s = db->Get(read_options, "B", &value);
  3625. ASSERT_OK(s);
  3626. ASSERT_EQ("b", value);
  3627. s = db->Get(read_options, "C", &value);
  3628. ASSERT_TRUE(s.IsNotFound());
  3629. }
  3630. TEST_P(TransactionTest, SavepointTest4) {
  3631. WriteOptions write_options;
  3632. ReadOptions read_options;
  3633. TransactionOptions txn_options;
  3634. Status s;
  3635. txn_options.lock_timeout = 1; // 1 ms
  3636. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  3637. ASSERT_TRUE(txn1);
  3638. txn1->SetSavePoint(); // 1
  3639. s = txn1->Put("A", "a");
  3640. ASSERT_OK(s);
  3641. txn1->SetSavePoint(); // 2
  3642. s = txn1->Put("B", "b");
  3643. ASSERT_OK(s);
  3644. s = txn1->PopSavePoint(); // Remove 2
  3645. ASSERT_OK(s);
  3646. // Verify that A/B still exists.
  3647. std::string value;
  3648. ASSERT_OK(txn1->Get(read_options, "A", &value));
  3649. ASSERT_EQ("a", value);
  3650. ASSERT_OK(txn1->Get(read_options, "B", &value));
  3651. ASSERT_EQ("b", value);
  3652. ASSERT_OK(txn1->RollbackToSavePoint()); // Rollback to 1
  3653. // Verify that everything was rolled back.
  3654. s = txn1->Get(read_options, "A", &value);
  3655. ASSERT_TRUE(s.IsNotFound());
  3656. s = txn1->Get(read_options, "B", &value);
  3657. ASSERT_TRUE(s.IsNotFound());
  3658. // Nothing should be locked
  3659. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  3660. ASSERT_TRUE(txn2);
  3661. s = txn2->Put("A", "");
  3662. ASSERT_OK(s);
  3663. s = txn2->Put("B", "");
  3664. ASSERT_OK(s);
  3665. delete txn2;
  3666. delete txn1;
  3667. }
  3668. TEST_P(TransactionTest, UndoGetForUpdateTest) {
  3669. WriteOptions write_options;
  3670. ReadOptions read_options;
  3671. TransactionOptions txn_options;
  3672. std::string value;
  3673. Status s;
  3674. txn_options.lock_timeout = 1; // 1 ms
  3675. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  3676. ASSERT_TRUE(txn1);
  3677. txn1->UndoGetForUpdate("A");
  3678. s = txn1->Commit();
  3679. ASSERT_OK(s);
  3680. delete txn1;
  3681. txn1 = db->BeginTransaction(write_options, txn_options);
  3682. txn1->UndoGetForUpdate("A");
  3683. s = txn1->GetForUpdate(read_options, "A", &value);
  3684. ASSERT_TRUE(s.IsNotFound());
  3685. // Verify that A is locked
  3686. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  3687. s = txn2->Put("A", "a");
  3688. ASSERT_TRUE(s.IsTimedOut());
  3689. txn1->UndoGetForUpdate("A");
  3690. // Verify that A is now unlocked
  3691. s = txn2->Put("A", "a2");
  3692. ASSERT_OK(s);
  3693. ASSERT_OK(txn2->Commit());
  3694. delete txn2;
  3695. s = db->Get(read_options, "A", &value);
  3696. ASSERT_OK(s);
  3697. ASSERT_EQ("a2", value);
  3698. s = txn1->Delete("A");
  3699. ASSERT_OK(s);
  3700. s = txn1->GetForUpdate(read_options, "A", &value);
  3701. ASSERT_TRUE(s.IsNotFound());
  3702. s = txn1->Put("B", "b3");
  3703. ASSERT_OK(s);
  3704. s = txn1->GetForUpdate(read_options, "B", &value);
  3705. ASSERT_OK(s);
  3706. txn1->UndoGetForUpdate("A");
  3707. txn1->UndoGetForUpdate("B");
  3708. // Verify that A and B are still locked
  3709. txn2 = db->BeginTransaction(write_options, txn_options);
  3710. s = txn2->Put("A", "a4");
  3711. ASSERT_TRUE(s.IsTimedOut());
  3712. s = txn2->Put("B", "b4");
  3713. ASSERT_TRUE(s.IsTimedOut());
  3714. ASSERT_OK(txn1->Rollback());
  3715. delete txn1;
  3716. // Verify that A and B are no longer locked
  3717. s = txn2->Put("A", "a5");
  3718. ASSERT_OK(s);
  3719. s = txn2->Put("B", "b5");
  3720. ASSERT_OK(s);
  3721. s = txn2->Commit();
  3722. delete txn2;
  3723. ASSERT_OK(s);
  3724. txn1 = db->BeginTransaction(write_options, txn_options);
  3725. s = txn1->GetForUpdate(read_options, "A", &value);
  3726. ASSERT_OK(s);
  3727. s = txn1->GetForUpdate(read_options, "A", &value);
  3728. ASSERT_OK(s);
  3729. s = txn1->GetForUpdate(read_options, "C", &value);
  3730. ASSERT_TRUE(s.IsNotFound());
  3731. s = txn1->GetForUpdate(read_options, "A", &value);
  3732. ASSERT_OK(s);
  3733. s = txn1->GetForUpdate(read_options, "C", &value);
  3734. ASSERT_TRUE(s.IsNotFound());
  3735. s = txn1->GetForUpdate(read_options, "B", &value);
  3736. ASSERT_OK(s);
  3737. s = txn1->Put("B", "b5");
  3738. s = txn1->GetForUpdate(read_options, "B", &value);
  3739. ASSERT_OK(s);
  3740. txn1->UndoGetForUpdate("A");
  3741. txn1->UndoGetForUpdate("B");
  3742. txn1->UndoGetForUpdate("C");
  3743. txn1->UndoGetForUpdate("X");
  3744. // Verify A,B,C are locked
  3745. txn2 = db->BeginTransaction(write_options, txn_options);
  3746. s = txn2->Put("A", "a6");
  3747. ASSERT_TRUE(s.IsTimedOut());
  3748. s = txn2->Delete("B");
  3749. ASSERT_TRUE(s.IsTimedOut());
  3750. s = txn2->Put("C", "c6");
  3751. ASSERT_TRUE(s.IsTimedOut());
  3752. s = txn2->Put("X", "x6");
  3753. ASSERT_OK(s);
  3754. txn1->UndoGetForUpdate("A");
  3755. txn1->UndoGetForUpdate("B");
  3756. txn1->UndoGetForUpdate("C");
  3757. txn1->UndoGetForUpdate("X");
  3758. // Verify A,B are locked and C is not
  3759. s = txn2->Put("A", "a6");
  3760. ASSERT_TRUE(s.IsTimedOut());
  3761. s = txn2->Delete("B");
  3762. ASSERT_TRUE(s.IsTimedOut());
  3763. s = txn2->Put("C", "c6");
  3764. ASSERT_OK(s);
  3765. s = txn2->Put("X", "x6");
  3766. ASSERT_OK(s);
  3767. txn1->UndoGetForUpdate("A");
  3768. txn1->UndoGetForUpdate("B");
  3769. txn1->UndoGetForUpdate("C");
  3770. txn1->UndoGetForUpdate("X");
  3771. // Verify B is locked and A and C are not
  3772. s = txn2->Put("A", "a7");
  3773. ASSERT_OK(s);
  3774. s = txn2->Delete("B");
  3775. ASSERT_TRUE(s.IsTimedOut());
  3776. s = txn2->Put("C", "c7");
  3777. ASSERT_OK(s);
  3778. s = txn2->Put("X", "x7");
  3779. ASSERT_OK(s);
  3780. s = txn2->Commit();
  3781. ASSERT_OK(s);
  3782. delete txn2;
  3783. s = txn1->Commit();
  3784. ASSERT_OK(s);
  3785. delete txn1;
  3786. }
  3787. TEST_P(TransactionTest, UndoGetForUpdateTest2) {
  3788. WriteOptions write_options;
  3789. ReadOptions read_options;
  3790. TransactionOptions txn_options;
  3791. std::string value;
  3792. Status s;
  3793. s = db->Put(write_options, "A", "");
  3794. ASSERT_OK(s);
  3795. txn_options.lock_timeout = 1; // 1 ms
  3796. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  3797. ASSERT_TRUE(txn1);
  3798. s = txn1->GetForUpdate(read_options, "A", &value);
  3799. ASSERT_OK(s);
  3800. s = txn1->GetForUpdate(read_options, "B", &value);
  3801. ASSERT_TRUE(s.IsNotFound());
  3802. s = txn1->Put("F", "f");
  3803. ASSERT_OK(s);
  3804. txn1->SetSavePoint(); // 1
  3805. txn1->UndoGetForUpdate("A");
  3806. s = txn1->GetForUpdate(read_options, "C", &value);
  3807. ASSERT_TRUE(s.IsNotFound());
  3808. s = txn1->GetForUpdate(read_options, "D", &value);
  3809. ASSERT_TRUE(s.IsNotFound());
  3810. s = txn1->Put("E", "e");
  3811. ASSERT_OK(s);
  3812. s = txn1->GetForUpdate(read_options, "E", &value);
  3813. ASSERT_OK(s);
  3814. s = txn1->GetForUpdate(read_options, "F", &value);
  3815. ASSERT_OK(s);
  3816. // Verify A,B,C,D,E,F are still locked
  3817. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  3818. s = txn2->Put("A", "a1");
  3819. ASSERT_TRUE(s.IsTimedOut());
  3820. s = txn2->Put("B", "b1");
  3821. ASSERT_TRUE(s.IsTimedOut());
  3822. s = txn2->Put("C", "c1");
  3823. ASSERT_TRUE(s.IsTimedOut());
  3824. s = txn2->Put("D", "d1");
  3825. ASSERT_TRUE(s.IsTimedOut());
  3826. s = txn2->Put("E", "e1");
  3827. ASSERT_TRUE(s.IsTimedOut());
  3828. s = txn2->Put("F", "f1");
  3829. ASSERT_TRUE(s.IsTimedOut());
  3830. txn1->UndoGetForUpdate("C");
  3831. txn1->UndoGetForUpdate("E");
  3832. // Verify A,B,D,E,F are still locked and C is not.
  3833. s = txn2->Put("A", "a2");
  3834. ASSERT_TRUE(s.IsTimedOut());
  3835. s = txn2->Put("B", "b2");
  3836. ASSERT_TRUE(s.IsTimedOut());
  3837. s = txn2->Put("D", "d2");
  3838. ASSERT_TRUE(s.IsTimedOut());
  3839. s = txn2->Put("E", "e2");
  3840. ASSERT_TRUE(s.IsTimedOut());
  3841. s = txn2->Put("F", "f2");
  3842. ASSERT_TRUE(s.IsTimedOut());
  3843. s = txn2->Put("C", "c2");
  3844. ASSERT_OK(s);
  3845. txn1->SetSavePoint(); // 2
  3846. s = txn1->Put("H", "h");
  3847. ASSERT_OK(s);
  3848. txn1->UndoGetForUpdate("A");
  3849. txn1->UndoGetForUpdate("B");
  3850. txn1->UndoGetForUpdate("C");
  3851. txn1->UndoGetForUpdate("D");
  3852. txn1->UndoGetForUpdate("E");
  3853. txn1->UndoGetForUpdate("F");
  3854. txn1->UndoGetForUpdate("G");
  3855. txn1->UndoGetForUpdate("H");
  3856. // Verify A,B,D,E,F,H are still locked and C,G are not.
  3857. s = txn2->Put("A", "a3");
  3858. ASSERT_TRUE(s.IsTimedOut());
  3859. s = txn2->Put("B", "b3");
  3860. ASSERT_TRUE(s.IsTimedOut());
  3861. s = txn2->Put("D", "d3");
  3862. ASSERT_TRUE(s.IsTimedOut());
  3863. s = txn2->Put("E", "e3");
  3864. ASSERT_TRUE(s.IsTimedOut());
  3865. s = txn2->Put("F", "f3");
  3866. ASSERT_TRUE(s.IsTimedOut());
  3867. s = txn2->Put("H", "h3");
  3868. ASSERT_TRUE(s.IsTimedOut());
  3869. s = txn2->Put("C", "c3");
  3870. ASSERT_OK(s);
  3871. s = txn2->Put("G", "g3");
  3872. ASSERT_OK(s);
  3873. ASSERT_OK(txn1->RollbackToSavePoint()); // rollback to 2
  3874. // Verify A,B,D,E,F are still locked and C,G,H are not.
  3875. s = txn2->Put("A", "a3");
  3876. ASSERT_TRUE(s.IsTimedOut());
  3877. s = txn2->Put("B", "b3");
  3878. ASSERT_TRUE(s.IsTimedOut());
  3879. s = txn2->Put("D", "d3");
  3880. ASSERT_TRUE(s.IsTimedOut());
  3881. s = txn2->Put("E", "e3");
  3882. ASSERT_TRUE(s.IsTimedOut());
  3883. s = txn2->Put("F", "f3");
  3884. ASSERT_TRUE(s.IsTimedOut());
  3885. s = txn2->Put("C", "c3");
  3886. ASSERT_OK(s);
  3887. s = txn2->Put("G", "g3");
  3888. ASSERT_OK(s);
  3889. s = txn2->Put("H", "h3");
  3890. ASSERT_OK(s);
  3891. txn1->UndoGetForUpdate("A");
  3892. txn1->UndoGetForUpdate("B");
  3893. txn1->UndoGetForUpdate("C");
  3894. txn1->UndoGetForUpdate("D");
  3895. txn1->UndoGetForUpdate("E");
  3896. txn1->UndoGetForUpdate("F");
  3897. txn1->UndoGetForUpdate("G");
  3898. txn1->UndoGetForUpdate("H");
  3899. // Verify A,B,E,F are still locked and C,D,G,H are not.
  3900. s = txn2->Put("A", "a3");
  3901. ASSERT_TRUE(s.IsTimedOut());
  3902. s = txn2->Put("B", "b3");
  3903. ASSERT_TRUE(s.IsTimedOut());
  3904. s = txn2->Put("E", "e3");
  3905. ASSERT_TRUE(s.IsTimedOut());
  3906. s = txn2->Put("F", "f3");
  3907. ASSERT_TRUE(s.IsTimedOut());
  3908. s = txn2->Put("C", "c3");
  3909. ASSERT_OK(s);
  3910. s = txn2->Put("D", "d3");
  3911. ASSERT_OK(s);
  3912. s = txn2->Put("G", "g3");
  3913. ASSERT_OK(s);
  3914. s = txn2->Put("H", "h3");
  3915. ASSERT_OK(s);
  3916. ASSERT_OK(txn1->RollbackToSavePoint()); // rollback to 1
  3917. // Verify A,B,F are still locked and C,D,E,G,H are not.
  3918. s = txn2->Put("A", "a3");
  3919. ASSERT_TRUE(s.IsTimedOut());
  3920. s = txn2->Put("B", "b3");
  3921. ASSERT_TRUE(s.IsTimedOut());
  3922. s = txn2->Put("F", "f3");
  3923. ASSERT_TRUE(s.IsTimedOut());
  3924. s = txn2->Put("C", "c3");
  3925. ASSERT_OK(s);
  3926. s = txn2->Put("D", "d3");
  3927. ASSERT_OK(s);
  3928. s = txn2->Put("E", "e3");
  3929. ASSERT_OK(s);
  3930. s = txn2->Put("G", "g3");
  3931. ASSERT_OK(s);
  3932. s = txn2->Put("H", "h3");
  3933. ASSERT_OK(s);
  3934. txn1->UndoGetForUpdate("A");
  3935. txn1->UndoGetForUpdate("B");
  3936. txn1->UndoGetForUpdate("C");
  3937. txn1->UndoGetForUpdate("D");
  3938. txn1->UndoGetForUpdate("E");
  3939. txn1->UndoGetForUpdate("F");
  3940. txn1->UndoGetForUpdate("G");
  3941. txn1->UndoGetForUpdate("H");
  3942. // Verify F is still locked and A,B,C,D,E,G,H are not.
  3943. s = txn2->Put("F", "f3");
  3944. ASSERT_TRUE(s.IsTimedOut());
  3945. s = txn2->Put("A", "a3");
  3946. ASSERT_OK(s);
  3947. s = txn2->Put("B", "b3");
  3948. ASSERT_OK(s);
  3949. s = txn2->Put("C", "c3");
  3950. ASSERT_OK(s);
  3951. s = txn2->Put("D", "d3");
  3952. ASSERT_OK(s);
  3953. s = txn2->Put("E", "e3");
  3954. ASSERT_OK(s);
  3955. s = txn2->Put("G", "g3");
  3956. ASSERT_OK(s);
  3957. s = txn2->Put("H", "h3");
  3958. ASSERT_OK(s);
  3959. s = txn1->Commit();
  3960. ASSERT_OK(s);
  3961. s = txn2->Commit();
  3962. ASSERT_OK(s);
  3963. delete txn1;
  3964. delete txn2;
  3965. }
  3966. TEST_P(TransactionTest, TimeoutTest) {
  3967. WriteOptions write_options;
  3968. ReadOptions read_options;
  3969. std::string value;
  3970. Status s;
  3971. delete db;
  3972. db = nullptr;
  3973. // transaction writes have an infinite timeout,
  3974. // but we will override this when we start a txn
  3975. // db writes have infinite timeout
  3976. txn_db_options.transaction_lock_timeout = -1;
  3977. txn_db_options.default_lock_timeout = -1;
  3978. s = TransactionDB::Open(options, txn_db_options, dbname, &db);
  3979. assert(db != nullptr);
  3980. ASSERT_OK(s);
  3981. s = db->Put(write_options, "aaa", "aaa");
  3982. ASSERT_OK(s);
  3983. TransactionOptions txn_options0;
  3984. txn_options0.expiration = 100; // 100ms
  3985. txn_options0.lock_timeout = 50; // txn timeout no longer infinite
  3986. Transaction* txn1 = db->BeginTransaction(write_options, txn_options0);
  3987. s = txn1->GetForUpdate(read_options, "aaa", (std::string*)nullptr);
  3988. ASSERT_OK(s);
  3989. // Conflicts with previous GetForUpdate.
  3990. // Since db writes do not have a timeout, this should eventually succeed when
  3991. // the transaction expires.
  3992. s = db->Put(write_options, "aaa", "xxx");
  3993. ASSERT_OK(s);
  3994. ASSERT_GE(txn1->GetElapsedTime(),
  3995. static_cast<uint64_t>(txn_options0.expiration));
  3996. s = txn1->Commit();
  3997. ASSERT_TRUE(s.IsExpired()); // expired!
  3998. s = db->Get(read_options, "aaa", &value);
  3999. ASSERT_OK(s);
  4000. ASSERT_EQ("xxx", value);
  4001. delete txn1;
  4002. delete db;
  4003. // transaction writes have 10ms timeout,
  4004. // db writes have infinite timeout
  4005. txn_db_options.transaction_lock_timeout = 50;
  4006. txn_db_options.default_lock_timeout = -1;
  4007. s = TransactionDB::Open(options, txn_db_options, dbname, &db);
  4008. ASSERT_OK(s);
  4009. s = db->Put(write_options, "aaa", "aaa");
  4010. ASSERT_OK(s);
  4011. TransactionOptions txn_options;
  4012. txn_options.expiration = 100; // 100ms
  4013. txn1 = db->BeginTransaction(write_options, txn_options);
  4014. s = txn1->GetForUpdate(read_options, "aaa", (std::string*)nullptr);
  4015. ASSERT_OK(s);
  4016. // Conflicts with previous GetForUpdate.
  4017. // Since db writes do not have a timeout, this should eventually succeed when
  4018. // the transaction expires.
  4019. s = db->Put(write_options, "aaa", "xxx");
  4020. ASSERT_OK(s);
  4021. s = txn1->Commit();
  4022. ASSERT_NOK(s); // expired!
  4023. s = db->Get(read_options, "aaa", &value);
  4024. ASSERT_OK(s);
  4025. ASSERT_EQ("xxx", value);
  4026. delete txn1;
  4027. txn_options.expiration = 6000000; // 100 minutes
  4028. txn_options.lock_timeout = 1; // 1ms
  4029. txn1 = db->BeginTransaction(write_options, txn_options);
  4030. txn1->SetLockTimeout(100);
  4031. TransactionOptions txn_options2;
  4032. txn_options2.expiration = 10; // 10ms
  4033. Transaction* txn2 = db->BeginTransaction(write_options, txn_options2);
  4034. ASSERT_OK(s);
  4035. s = txn2->Put("a", "2");
  4036. ASSERT_OK(s);
  4037. // txn1 has a lock timeout longer than txn2's expiration, so it will win
  4038. s = txn1->Delete("a");
  4039. ASSERT_OK(s);
  4040. s = txn1->Commit();
  4041. ASSERT_OK(s);
  4042. // txn2 should be expired out since txn1 waiting until its timeout expired.
  4043. s = txn2->Commit();
  4044. ASSERT_TRUE(s.IsExpired());
  4045. delete txn1;
  4046. delete txn2;
  4047. txn_options.expiration = 6000000; // 100 minutes
  4048. txn1 = db->BeginTransaction(write_options, txn_options);
  4049. txn_options2.expiration = 100000000;
  4050. txn2 = db->BeginTransaction(write_options, txn_options2);
  4051. s = txn1->Delete("asdf");
  4052. ASSERT_OK(s);
  4053. // txn2 has a smaller lock timeout than txn1's expiration, so it will time out
  4054. s = txn2->Delete("asdf");
  4055. ASSERT_TRUE(s.IsTimedOut());
  4056. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  4057. s = txn1->Commit();
  4058. ASSERT_OK(s);
  4059. s = txn2->Put("asdf", "asdf");
  4060. ASSERT_OK(s);
  4061. s = txn2->Commit();
  4062. ASSERT_OK(s);
  4063. s = db->Get(read_options, "asdf", &value);
  4064. ASSERT_OK(s);
  4065. ASSERT_EQ("asdf", value);
  4066. delete txn1;
  4067. delete txn2;
  4068. }
  4069. TEST_P(TransactionTest, SingleDeleteTest) {
  4070. WriteOptions write_options;
  4071. ReadOptions read_options;
  4072. std::string value;
  4073. Status s;
  4074. Transaction* txn = db->BeginTransaction(write_options);
  4075. ASSERT_TRUE(txn);
  4076. s = txn->SingleDelete("A");
  4077. ASSERT_OK(s);
  4078. s = txn->Get(read_options, "A", &value);
  4079. ASSERT_TRUE(s.IsNotFound());
  4080. s = txn->Commit();
  4081. ASSERT_OK(s);
  4082. delete txn;
  4083. txn = db->BeginTransaction(write_options);
  4084. s = txn->SingleDelete("A");
  4085. ASSERT_OK(s);
  4086. s = txn->Put("A", "a");
  4087. ASSERT_OK(s);
  4088. s = txn->Get(read_options, "A", &value);
  4089. ASSERT_OK(s);
  4090. ASSERT_EQ("a", value);
  4091. s = txn->Commit();
  4092. ASSERT_OK(s);
  4093. delete txn;
  4094. s = db->Get(read_options, "A", &value);
  4095. ASSERT_OK(s);
  4096. ASSERT_EQ("a", value);
  4097. txn = db->BeginTransaction(write_options);
  4098. s = txn->SingleDelete("A");
  4099. ASSERT_OK(s);
  4100. s = txn->Get(read_options, "A", &value);
  4101. ASSERT_TRUE(s.IsNotFound());
  4102. s = txn->Commit();
  4103. ASSERT_OK(s);
  4104. delete txn;
  4105. s = db->Get(read_options, "A", &value);
  4106. ASSERT_TRUE(s.IsNotFound());
  4107. txn = db->BeginTransaction(write_options);
  4108. Transaction* txn2 = db->BeginTransaction(write_options);
  4109. txn2->SetSnapshot();
  4110. s = txn->Put("A", "a");
  4111. ASSERT_OK(s);
  4112. s = txn->Put("A", "a2");
  4113. ASSERT_OK(s);
  4114. s = txn->SingleDelete("A");
  4115. ASSERT_OK(s);
  4116. s = txn->SingleDelete("B");
  4117. ASSERT_OK(s);
  4118. // According to db.h, doing a SingleDelete on a key that has been
  4119. // overwritten will have undefinied behavior. So it is unclear what the
  4120. // result of fetching "A" should be. The current implementation will
  4121. // return NotFound in this case.
  4122. s = txn->Get(read_options, "A", &value);
  4123. ASSERT_TRUE(s.IsNotFound());
  4124. s = txn2->Put("B", "b");
  4125. ASSERT_TRUE(s.IsTimedOut());
  4126. s = txn2->Commit();
  4127. ASSERT_OK(s);
  4128. delete txn2;
  4129. s = txn->Commit();
  4130. ASSERT_OK(s);
  4131. delete txn;
  4132. // According to db.h, doing a SingleDelete on a key that has been
  4133. // overwritten will have undefinied behavior. So it is unclear what the
  4134. // result of fetching "A" should be. The current implementation will
  4135. // return NotFound in this case.
  4136. s = db->Get(read_options, "A", &value);
  4137. ASSERT_TRUE(s.IsNotFound());
  4138. s = db->Get(read_options, "B", &value);
  4139. ASSERT_TRUE(s.IsNotFound());
  4140. }
  4141. TEST_P(TransactionTest, MergeTest) {
  4142. WriteOptions write_options;
  4143. ReadOptions read_options;
  4144. std::string value;
  4145. Status s;
  4146. Transaction* txn = db->BeginTransaction(write_options, TransactionOptions());
  4147. ASSERT_TRUE(txn);
  4148. s = db->Put(write_options, "A", "a0");
  4149. ASSERT_OK(s);
  4150. s = txn->Merge("A", "1");
  4151. ASSERT_OK(s);
  4152. s = txn->Merge("A", "2");
  4153. ASSERT_OK(s);
  4154. s = txn->Get(read_options, "A", &value);
  4155. ASSERT_OK(s);
  4156. ASSERT_EQ("a0,1,2", value);
  4157. s = txn->Put("A", "a");
  4158. ASSERT_OK(s);
  4159. s = txn->Get(read_options, "A", &value);
  4160. ASSERT_OK(s);
  4161. ASSERT_EQ("a", value);
  4162. s = txn->Merge("A", "3");
  4163. ASSERT_OK(s);
  4164. s = txn->Get(read_options, "A", &value);
  4165. ASSERT_OK(s);
  4166. ASSERT_EQ("a,3", value);
  4167. TransactionOptions txn_options;
  4168. txn_options.lock_timeout = 1; // 1 ms
  4169. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  4170. ASSERT_TRUE(txn2);
  4171. // verify that txn has "A" locked
  4172. s = txn2->Merge("A", "4");
  4173. ASSERT_TRUE(s.IsTimedOut());
  4174. s = txn2->Commit();
  4175. ASSERT_OK(s);
  4176. delete txn2;
  4177. s = txn->Commit();
  4178. ASSERT_OK(s);
  4179. delete txn;
  4180. s = db->Get(read_options, "A", &value);
  4181. ASSERT_OK(s);
  4182. ASSERT_EQ("a,3", value);
  4183. }
  4184. TEST_P(TransactionTest, DeleteRangeSupportTest) {
  4185. // The `DeleteRange()` API is banned everywhere.
  4186. ASSERT_TRUE(
  4187. db->DeleteRange(WriteOptions(), db->DefaultColumnFamily(), "a", "b")
  4188. .IsNotSupported());
  4189. // But range deletions can be added via the `Write()` API by specifying the
  4190. // proper flags to promise there are no conflicts according to the DB type
  4191. // (see `TransactionDB::DeleteRange()` API doc for details).
  4192. for (bool skip_concurrency_control : {false, true}) {
  4193. for (bool skip_duplicate_key_check : {false, true}) {
  4194. ASSERT_OK(db->Put(WriteOptions(), "a", "val"));
  4195. WriteBatch wb;
  4196. ASSERT_OK(wb.DeleteRange("a", "b"));
  4197. TransactionDBWriteOptimizations flags;
  4198. flags.skip_concurrency_control = skip_concurrency_control;
  4199. flags.skip_duplicate_key_check = skip_duplicate_key_check;
  4200. Status s = db->Write(WriteOptions(), flags, &wb);
  4201. std::string value;
  4202. switch (txn_db_options.write_policy) {
  4203. case WRITE_COMMITTED:
  4204. if (skip_concurrency_control) {
  4205. ASSERT_OK(s);
  4206. ASSERT_TRUE(db->Get(ReadOptions(), "a", &value).IsNotFound());
  4207. } else {
  4208. ASSERT_NOK(s);
  4209. ASSERT_OK(db->Get(ReadOptions(), "a", &value));
  4210. }
  4211. break;
  4212. case WRITE_PREPARED:
  4213. FALLTHROUGH_INTENDED;
  4214. case WRITE_UNPREPARED:
  4215. if (skip_concurrency_control && skip_duplicate_key_check) {
  4216. ASSERT_OK(s);
  4217. ASSERT_TRUE(db->Get(ReadOptions(), "a", &value).IsNotFound());
  4218. } else {
  4219. ASSERT_NOK(s);
  4220. ASSERT_OK(db->Get(ReadOptions(), "a", &value));
  4221. }
  4222. break;
  4223. }
  4224. // Without any promises from the user, range deletion via other `Write()`
  4225. // APIs are still banned.
  4226. ASSERT_OK(db->Put(WriteOptions(), "a", "val"));
  4227. ASSERT_NOK(db->Write(WriteOptions(), &wb));
  4228. ASSERT_OK(db->Get(ReadOptions(), "a", &value));
  4229. }
  4230. }
  4231. }
  4232. TEST_P(TransactionTest, DeferSnapshotTest) {
  4233. WriteOptions write_options;
  4234. ReadOptions read_options;
  4235. std::string value;
  4236. Status s;
  4237. s = db->Put(write_options, "A", "a0");
  4238. ASSERT_OK(s);
  4239. Transaction* txn1 = db->BeginTransaction(write_options);
  4240. Transaction* txn2 = db->BeginTransaction(write_options);
  4241. txn1->SetSnapshotOnNextOperation();
  4242. auto snapshot = txn1->GetSnapshot();
  4243. ASSERT_FALSE(snapshot);
  4244. s = txn2->Put("A", "a2");
  4245. ASSERT_OK(s);
  4246. s = txn2->Commit();
  4247. ASSERT_OK(s);
  4248. delete txn2;
  4249. s = txn1->GetForUpdate(read_options, "A", &value);
  4250. // Should not conflict with txn2 since snapshot wasn't set until
  4251. // GetForUpdate was called.
  4252. ASSERT_OK(s);
  4253. ASSERT_EQ("a2", value);
  4254. s = txn1->Put("A", "a1");
  4255. ASSERT_OK(s);
  4256. s = db->Put(write_options, "B", "b0");
  4257. ASSERT_OK(s);
  4258. // Cannot lock B since it was written after the snapshot was set
  4259. s = txn1->Put("B", "b1");
  4260. ASSERT_TRUE(s.IsBusy());
  4261. s = txn1->Commit();
  4262. ASSERT_OK(s);
  4263. delete txn1;
  4264. s = db->Get(read_options, "A", &value);
  4265. ASSERT_OK(s);
  4266. ASSERT_EQ("a1", value);
  4267. s = db->Get(read_options, "B", &value);
  4268. ASSERT_OK(s);
  4269. ASSERT_EQ("b0", value);
  4270. }
  4271. TEST_P(TransactionTest, DeferSnapshotTest2) {
  4272. WriteOptions write_options;
  4273. ReadOptions read_options, snapshot_read_options;
  4274. std::string value;
  4275. Status s;
  4276. Transaction* txn1 = db->BeginTransaction(write_options);
  4277. txn1->SetSnapshot();
  4278. s = txn1->Put("A", "a1");
  4279. ASSERT_OK(s);
  4280. s = db->Put(write_options, "C", "c0");
  4281. ASSERT_OK(s);
  4282. s = db->Put(write_options, "D", "d0");
  4283. ASSERT_OK(s);
  4284. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4285. txn1->SetSnapshotOnNextOperation();
  4286. s = txn1->Get(snapshot_read_options, "C", &value);
  4287. // Snapshot was set before C was written
  4288. ASSERT_TRUE(s.IsNotFound());
  4289. s = txn1->Get(snapshot_read_options, "D", &value);
  4290. // Snapshot was set before D was written
  4291. ASSERT_TRUE(s.IsNotFound());
  4292. // Snapshot should not have changed yet.
  4293. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4294. s = txn1->Get(snapshot_read_options, "C", &value);
  4295. // Snapshot was set before C was written
  4296. ASSERT_TRUE(s.IsNotFound());
  4297. s = txn1->Get(snapshot_read_options, "D", &value);
  4298. // Snapshot was set before D was written
  4299. ASSERT_TRUE(s.IsNotFound());
  4300. s = txn1->GetForUpdate(read_options, "C", &value);
  4301. ASSERT_OK(s);
  4302. ASSERT_EQ("c0", value);
  4303. s = db->Put(write_options, "D", "d00");
  4304. ASSERT_OK(s);
  4305. // Snapshot is now set
  4306. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4307. s = txn1->Get(snapshot_read_options, "D", &value);
  4308. ASSERT_OK(s);
  4309. ASSERT_EQ("d0", value);
  4310. s = txn1->Commit();
  4311. ASSERT_OK(s);
  4312. delete txn1;
  4313. }
  4314. TEST_P(TransactionTest, DeferSnapshotSavePointTest) {
  4315. WriteOptions write_options;
  4316. ReadOptions read_options, snapshot_read_options;
  4317. std::string value;
  4318. Status s;
  4319. Transaction* txn1 = db->BeginTransaction(write_options);
  4320. txn1->SetSavePoint(); // 1
  4321. s = db->Put(write_options, "T", "1");
  4322. ASSERT_OK(s);
  4323. txn1->SetSnapshotOnNextOperation();
  4324. s = db->Put(write_options, "T", "2");
  4325. ASSERT_OK(s);
  4326. txn1->SetSavePoint(); // 2
  4327. s = db->Put(write_options, "T", "3");
  4328. ASSERT_OK(s);
  4329. s = txn1->Put("A", "a");
  4330. ASSERT_OK(s);
  4331. txn1->SetSavePoint(); // 3
  4332. s = db->Put(write_options, "T", "4");
  4333. ASSERT_OK(s);
  4334. txn1->SetSnapshot();
  4335. txn1->SetSnapshotOnNextOperation();
  4336. txn1->SetSavePoint(); // 4
  4337. s = db->Put(write_options, "T", "5");
  4338. ASSERT_OK(s);
  4339. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4340. s = txn1->Get(snapshot_read_options, "T", &value);
  4341. ASSERT_OK(s);
  4342. ASSERT_EQ("4", value);
  4343. s = txn1->Put("A", "a1");
  4344. ASSERT_OK(s);
  4345. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4346. s = txn1->Get(snapshot_read_options, "T", &value);
  4347. ASSERT_OK(s);
  4348. ASSERT_EQ("5", value);
  4349. s = txn1->RollbackToSavePoint(); // Rollback to 4
  4350. ASSERT_OK(s);
  4351. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4352. s = txn1->Get(snapshot_read_options, "T", &value);
  4353. ASSERT_OK(s);
  4354. ASSERT_EQ("4", value);
  4355. s = txn1->RollbackToSavePoint(); // Rollback to 3
  4356. ASSERT_OK(s);
  4357. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4358. s = txn1->Get(snapshot_read_options, "T", &value);
  4359. ASSERT_OK(s);
  4360. ASSERT_EQ("3", value);
  4361. s = txn1->Get(read_options, "T", &value);
  4362. ASSERT_OK(s);
  4363. ASSERT_EQ("5", value);
  4364. s = txn1->RollbackToSavePoint(); // Rollback to 2
  4365. ASSERT_OK(s);
  4366. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4367. ASSERT_FALSE(snapshot_read_options.snapshot);
  4368. s = txn1->Get(snapshot_read_options, "T", &value);
  4369. ASSERT_OK(s);
  4370. ASSERT_EQ("5", value);
  4371. s = txn1->Delete("A");
  4372. ASSERT_OK(s);
  4373. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4374. ASSERT_TRUE(snapshot_read_options.snapshot);
  4375. s = txn1->Get(snapshot_read_options, "T", &value);
  4376. ASSERT_OK(s);
  4377. ASSERT_EQ("5", value);
  4378. s = txn1->RollbackToSavePoint(); // Rollback to 1
  4379. ASSERT_OK(s);
  4380. s = txn1->Delete("A");
  4381. ASSERT_OK(s);
  4382. snapshot_read_options.snapshot = txn1->GetSnapshot();
  4383. ASSERT_FALSE(snapshot_read_options.snapshot);
  4384. s = txn1->Get(snapshot_read_options, "T", &value);
  4385. ASSERT_OK(s);
  4386. ASSERT_EQ("5", value);
  4387. s = txn1->Commit();
  4388. ASSERT_OK(s);
  4389. delete txn1;
  4390. }
  4391. TEST_P(TransactionTest, SetSnapshotOnNextOperationWithNotification) {
  4392. WriteOptions write_options;
  4393. ReadOptions read_options;
  4394. std::string value;
  4395. class Notifier : public TransactionNotifier {
  4396. private:
  4397. const Snapshot** snapshot_ptr_;
  4398. public:
  4399. explicit Notifier(const Snapshot** snapshot_ptr)
  4400. : snapshot_ptr_(snapshot_ptr) {}
  4401. void SnapshotCreated(const Snapshot* newSnapshot) override {
  4402. *snapshot_ptr_ = newSnapshot;
  4403. }
  4404. };
  4405. std::shared_ptr<Notifier> notifier =
  4406. std::make_shared<Notifier>(&read_options.snapshot);
  4407. Status s;
  4408. s = db->Put(write_options, "B", "0");
  4409. ASSERT_OK(s);
  4410. Transaction* txn1 = db->BeginTransaction(write_options);
  4411. txn1->SetSnapshotOnNextOperation(notifier);
  4412. ASSERT_FALSE(read_options.snapshot);
  4413. s = db->Put(write_options, "B", "1");
  4414. ASSERT_OK(s);
  4415. // A Get does not generate the snapshot
  4416. s = txn1->Get(read_options, "B", &value);
  4417. ASSERT_OK(s);
  4418. ASSERT_FALSE(read_options.snapshot);
  4419. ASSERT_EQ(value, "1");
  4420. // Any other operation does
  4421. s = txn1->Put("A", "0");
  4422. ASSERT_OK(s);
  4423. // Now change "B".
  4424. s = db->Put(write_options, "B", "2");
  4425. ASSERT_OK(s);
  4426. // The original value should still be read
  4427. s = txn1->Get(read_options, "B", &value);
  4428. ASSERT_OK(s);
  4429. ASSERT_TRUE(read_options.snapshot);
  4430. ASSERT_EQ(value, "1");
  4431. s = txn1->Commit();
  4432. ASSERT_OK(s);
  4433. delete txn1;
  4434. }
  4435. TEST_P(TransactionTest, ClearSnapshotTest) {
  4436. WriteOptions write_options;
  4437. ReadOptions read_options, snapshot_read_options;
  4438. std::string value;
  4439. Status s;
  4440. s = db->Put(write_options, "foo", "0");
  4441. ASSERT_OK(s);
  4442. Transaction* txn = db->BeginTransaction(write_options);
  4443. ASSERT_TRUE(txn);
  4444. s = db->Put(write_options, "foo", "1");
  4445. ASSERT_OK(s);
  4446. snapshot_read_options.snapshot = txn->GetSnapshot();
  4447. ASSERT_FALSE(snapshot_read_options.snapshot);
  4448. // No snapshot created yet
  4449. s = txn->Get(snapshot_read_options, "foo", &value);
  4450. ASSERT_EQ(value, "1");
  4451. txn->SetSnapshot();
  4452. snapshot_read_options.snapshot = txn->GetSnapshot();
  4453. ASSERT_TRUE(snapshot_read_options.snapshot);
  4454. s = db->Put(write_options, "foo", "2");
  4455. ASSERT_OK(s);
  4456. // Snapshot was created before change to '2'
  4457. s = txn->Get(snapshot_read_options, "foo", &value);
  4458. ASSERT_EQ(value, "1");
  4459. txn->ClearSnapshot();
  4460. snapshot_read_options.snapshot = txn->GetSnapshot();
  4461. ASSERT_FALSE(snapshot_read_options.snapshot);
  4462. // Snapshot has now been cleared
  4463. s = txn->Get(snapshot_read_options, "foo", &value);
  4464. ASSERT_EQ(value, "2");
  4465. s = txn->Commit();
  4466. ASSERT_OK(s);
  4467. delete txn;
  4468. }
  4469. TEST_P(TransactionTest, ToggleAutoCompactionTest) {
  4470. Status s;
  4471. ColumnFamilyHandle *cfa, *cfb;
  4472. ColumnFamilyOptions cf_options;
  4473. // Create 2 new column families
  4474. s = db->CreateColumnFamily(cf_options, "CFA", &cfa);
  4475. ASSERT_OK(s);
  4476. s = db->CreateColumnFamily(cf_options, "CFB", &cfb);
  4477. ASSERT_OK(s);
  4478. delete cfa;
  4479. delete cfb;
  4480. delete db;
  4481. // open DB with three column families
  4482. std::vector<ColumnFamilyDescriptor> column_families;
  4483. // have to open default column family
  4484. column_families.emplace_back(kDefaultColumnFamilyName, ColumnFamilyOptions());
  4485. // open the new column families
  4486. column_families.emplace_back("CFA", ColumnFamilyOptions());
  4487. column_families.emplace_back("CFB", ColumnFamilyOptions());
  4488. ColumnFamilyOptions* cf_opt_default = &column_families[0].options;
  4489. ColumnFamilyOptions* cf_opt_cfa = &column_families[1].options;
  4490. ColumnFamilyOptions* cf_opt_cfb = &column_families[2].options;
  4491. cf_opt_default->disable_auto_compactions = false;
  4492. cf_opt_cfa->disable_auto_compactions = true;
  4493. cf_opt_cfb->disable_auto_compactions = false;
  4494. std::vector<ColumnFamilyHandle*> handles;
  4495. s = TransactionDB::Open(options, txn_db_options, dbname, column_families,
  4496. &handles, &db);
  4497. ASSERT_OK(s);
  4498. auto cfh_default = static_cast_with_check<ColumnFamilyHandleImpl>(handles[0]);
  4499. auto& opt_default = cfh_default->cfd()->GetLatestMutableCFOptions();
  4500. auto cfh_a = static_cast_with_check<ColumnFamilyHandleImpl>(handles[1]);
  4501. auto& opt_a = cfh_a->cfd()->GetLatestMutableCFOptions();
  4502. auto cfh_b = static_cast_with_check<ColumnFamilyHandleImpl>(handles[2]);
  4503. auto& opt_b = cfh_b->cfd()->GetLatestMutableCFOptions();
  4504. ASSERT_EQ(opt_default.disable_auto_compactions, false);
  4505. ASSERT_EQ(opt_a.disable_auto_compactions, true);
  4506. ASSERT_EQ(opt_b.disable_auto_compactions, false);
  4507. for (auto handle : handles) {
  4508. delete handle;
  4509. }
  4510. }
  4511. TEST_P(TransactionStressTest, ExpiredTransactionDataRace1) {
  4512. // In this test, txn1 should succeed committing,
  4513. // as the callback is called after txn1 starts committing.
  4514. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency(
  4515. {{"TransactionTest::ExpirableTransactionDataRace:1"}});
  4516. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
  4517. "TransactionTest::ExpirableTransactionDataRace:1", [&](void* /*arg*/) {
  4518. WriteOptions write_options;
  4519. TransactionOptions txn_options;
  4520. // Force txn1 to expire
  4521. /* sleep override */
  4522. std::this_thread::sleep_for(std::chrono::milliseconds(1500));
  4523. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  4524. Status s;
  4525. s = txn2->Put("X", "2");
  4526. ASSERT_TRUE(s.IsTimedOut());
  4527. s = txn2->Commit();
  4528. ASSERT_OK(s);
  4529. delete txn2;
  4530. });
  4531. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
  4532. WriteOptions write_options;
  4533. TransactionOptions txn_options;
  4534. txn_options.expiration = 1000; // 1 second
  4535. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  4536. Status s;
  4537. s = txn1->Put("X", "1");
  4538. ASSERT_OK(s);
  4539. s = txn1->Commit();
  4540. ASSERT_OK(s);
  4541. ReadOptions read_options;
  4542. std::string value;
  4543. s = db->Get(read_options, "X", &value);
  4544. ASSERT_OK(s);
  4545. ASSERT_EQ("1", value);
  4546. delete txn1;
  4547. ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
  4548. }
  4549. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  4550. namespace {
  4551. // cmt_delay_ms is the delay between prepare and commit
  4552. // first_id is the id of the first transaction
  4553. Status TransactionStressTestInserter(
  4554. TransactionDB* db, const size_t num_transactions, const size_t num_sets,
  4555. const size_t num_keys_per_set, Random64* rand,
  4556. const uint64_t cmt_delay_ms = 0, const uint64_t first_id = 0) {
  4557. WriteOptions write_options;
  4558. ReadOptions read_options;
  4559. TransactionOptions txn_options;
  4560. txn_options.use_only_the_last_commit_time_batch_for_recovery = true;
  4561. // Inside the inserter we might also retake the snapshot. We do both since
  4562. // two separte functions are engaged for each.
  4563. txn_options.set_snapshot = rand->OneIn(2);
  4564. RandomTransactionInserter inserter(
  4565. rand, write_options, read_options, num_keys_per_set,
  4566. static_cast<uint16_t>(num_sets), cmt_delay_ms, first_id);
  4567. for (size_t t = 0; t < num_transactions; t++) {
  4568. bool success = inserter.TransactionDBInsert(db, txn_options);
  4569. if (!success) {
  4570. // unexpected failure
  4571. return inserter.GetLastStatus();
  4572. }
  4573. }
  4574. inserter.GetLastStatus().PermitUncheckedError();
  4575. // Make sure at least some of the transactions succeeded. It's ok if
  4576. // some failed due to write-conflicts.
  4577. if (num_transactions != 1 &&
  4578. inserter.GetFailureCount() > num_transactions / 2) {
  4579. return Status::TryAgain("Too many transactions failed! " +
  4580. std::to_string(inserter.GetFailureCount()) + " / " +
  4581. std::to_string(num_transactions));
  4582. }
  4583. return Status::OK();
  4584. }
  4585. } // namespace
  4586. // Worker threads add a number to a key from each set of keys. The checker
  4587. // threads verify that the sum of all keys in each set are equal.
  4588. TEST_P(MySQLStyleTransactionTest, TransactionStressTest) {
  4589. // Small write buffer to trigger more compactions
  4590. options.write_buffer_size = 1024;
  4591. txn_db_options.rollback_deletion_type_callback =
  4592. [](TransactionDB*, ColumnFamilyHandle*, const Slice& key) {
  4593. return RandomTransactionInserter::RollbackDeletionTypeCallback(key);
  4594. };
  4595. ASSERT_OK(ReOpenNoDelete());
  4596. constexpr size_t num_workers = 4; // worker threads count
  4597. constexpr size_t num_checkers = 2; // checker threads count
  4598. constexpr size_t num_slow_checkers = 2; // checker threads emulating backups
  4599. constexpr size_t num_slow_workers = 1; // slow worker threads count
  4600. constexpr size_t num_transactions_per_thread = 1000;
  4601. constexpr uint16_t num_sets = 3;
  4602. constexpr size_t num_keys_per_set = 100;
  4603. // Setting the key-space to be 100 keys should cause enough write-conflicts
  4604. // to make this test interesting.
  4605. std::vector<port::Thread> threads;
  4606. std::atomic<uint32_t> finished = {0};
  4607. constexpr bool TAKE_SNAPSHOT = true;
  4608. uint64_t time_seed = env->NowMicros();
  4609. printf("time_seed is %" PRIu64 "\n", time_seed); // would help to reproduce
  4610. std::function<void()> call_inserter = [&] {
  4611. size_t thd_seed = std::hash<std::thread::id>()(std::this_thread::get_id());
  4612. Random64 rand(time_seed * thd_seed);
  4613. ASSERT_OK(TransactionStressTestInserter(db, num_transactions_per_thread,
  4614. num_sets, num_keys_per_set, &rand));
  4615. finished++;
  4616. };
  4617. std::function<void()> call_checker = [&] {
  4618. size_t thd_seed = std::hash<std::thread::id>()(std::this_thread::get_id());
  4619. Random64 rand(time_seed * thd_seed);
  4620. // Verify that data is consistent
  4621. while (finished < num_workers) {
  4622. ASSERT_OK(RandomTransactionInserter::Verify(
  4623. db, num_sets, num_keys_per_set, TAKE_SNAPSHOT, &rand));
  4624. }
  4625. };
  4626. std::function<void()> call_slow_checker = [&] {
  4627. size_t thd_seed = std::hash<std::thread::id>()(std::this_thread::get_id());
  4628. Random64 rand(time_seed * thd_seed);
  4629. // Verify that data is consistent
  4630. while (finished < num_workers) {
  4631. uint64_t delay_ms = rand.Uniform(100) + 1;
  4632. Status s = RandomTransactionInserter::Verify(
  4633. db, num_sets, num_keys_per_set, TAKE_SNAPSHOT, &rand, delay_ms);
  4634. ASSERT_OK(s);
  4635. }
  4636. };
  4637. std::function<void()> call_slow_inserter = [&] {
  4638. size_t thd_seed = std::hash<std::thread::id>()(std::this_thread::get_id());
  4639. Random64 rand(time_seed * thd_seed);
  4640. uint64_t id = 0;
  4641. // Verify that data is consistent
  4642. while (finished < num_workers) {
  4643. uint64_t delay_ms = rand.Uniform(500) + 1;
  4644. ASSERT_OK(TransactionStressTestInserter(db, 1, num_sets, num_keys_per_set,
  4645. &rand, delay_ms, id++));
  4646. }
  4647. };
  4648. for (uint32_t i = 0; i < num_workers; i++) {
  4649. threads.emplace_back(call_inserter);
  4650. }
  4651. for (uint32_t i = 0; i < num_checkers; i++) {
  4652. threads.emplace_back(call_checker);
  4653. }
  4654. if (with_slow_threads_) {
  4655. for (uint32_t i = 0; i < num_slow_checkers; i++) {
  4656. threads.emplace_back(call_slow_checker);
  4657. }
  4658. for (uint32_t i = 0; i < num_slow_workers; i++) {
  4659. threads.emplace_back(call_slow_inserter);
  4660. }
  4661. }
  4662. // Wait for all threads to finish
  4663. for (auto& t : threads) {
  4664. t.join();
  4665. }
  4666. // Verify that data is consistent
  4667. Status s = RandomTransactionInserter::Verify(db, num_sets, num_keys_per_set,
  4668. !TAKE_SNAPSHOT);
  4669. ASSERT_OK(s);
  4670. }
  4671. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  4672. TEST_P(TransactionTest, MemoryLimitTest) {
  4673. TransactionOptions txn_options;
  4674. // Header (12 bytes) + NOOP (1 byte) + 2 * 8 bytes for data.
  4675. txn_options.max_write_batch_size = 29;
  4676. // Set threshold to unlimited so that the write batch does not get flushed,
  4677. // and can hit the memory limit.
  4678. txn_options.write_batch_flush_threshold = 0;
  4679. std::string value;
  4680. Status s;
  4681. Transaction* txn = db->BeginTransaction(WriteOptions(), txn_options);
  4682. ASSERT_TRUE(txn);
  4683. ASSERT_EQ(0, txn->GetNumPuts());
  4684. ASSERT_LE(0, txn->GetID());
  4685. s = txn->Put(Slice("a"), Slice("...."));
  4686. ASSERT_OK(s);
  4687. ASSERT_EQ(1, txn->GetNumPuts());
  4688. s = txn->Put(Slice("b"), Slice("...."));
  4689. ASSERT_OK(s);
  4690. ASSERT_EQ(2, txn->GetNumPuts());
  4691. s = txn->Put(Slice("b"), Slice("...."));
  4692. ASSERT_TRUE(s.IsMemoryLimit());
  4693. ASSERT_EQ(2, txn->GetNumPuts());
  4694. ASSERT_OK(txn->Rollback());
  4695. delete txn;
  4696. }
  4697. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  4698. // This test clarifies the existing expectation from the sequence number
  4699. // algorithm. It could detect mistakes in updating the code but it is not
  4700. // necessarily the one acceptable way. If the algorithm is legitimately changed,
  4701. // this unit test should be updated as well.
  4702. TEST_P(TransactionStressTest, SeqAdvanceTest) {
  4703. // TODO(myabandeh): must be test with false before new releases
  4704. const bool short_test = true;
  4705. WriteOptions wopts;
  4706. FlushOptions fopt;
  4707. options.disable_auto_compactions = true;
  4708. ASSERT_OK(ReOpen());
  4709. // Do the test with NUM_BRANCHES branches in it. Each run of a test takes some
  4710. // of the branches. This is the same as counting a binary number where i-th
  4711. // bit represents whether we take branch i in the represented by the number.
  4712. const size_t NUM_BRANCHES = short_test ? 6 : 10;
  4713. // Helper function that shows if the branch is to be taken in the run
  4714. // represented by the number n.
  4715. auto branch_do = [&](size_t n, size_t* branch) {
  4716. assert(*branch < NUM_BRANCHES);
  4717. const size_t filter = static_cast<size_t>(1) << *branch;
  4718. return n & filter;
  4719. };
  4720. const size_t max_n = static_cast<size_t>(1) << NUM_BRANCHES;
  4721. for (size_t n = 0; n < max_n; n++) {
  4722. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  4723. size_t branch = 0;
  4724. auto seq = db_impl->GetLatestSequenceNumber();
  4725. exp_seq = seq;
  4726. TestTxn0(0);
  4727. seq = db_impl->TEST_GetLastVisibleSequence();
  4728. ASSERT_EQ(exp_seq, seq);
  4729. if (branch_do(n, &branch)) {
  4730. ASSERT_OK(db_impl->Flush(fopt));
  4731. seq = db_impl->TEST_GetLastVisibleSequence();
  4732. ASSERT_EQ(exp_seq, seq);
  4733. }
  4734. if (!short_test && branch_do(n, &branch)) {
  4735. ASSERT_OK(db_impl->FlushWAL(true));
  4736. ASSERT_OK(ReOpenNoDelete());
  4737. db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  4738. seq = db_impl->GetLatestSequenceNumber();
  4739. ASSERT_EQ(exp_seq, seq);
  4740. }
  4741. // Doing it twice might detect some bugs
  4742. TestTxn0(1);
  4743. seq = db_impl->TEST_GetLastVisibleSequence();
  4744. ASSERT_EQ(exp_seq, seq);
  4745. TestTxn1(0);
  4746. seq = db_impl->TEST_GetLastVisibleSequence();
  4747. ASSERT_EQ(exp_seq, seq);
  4748. if (branch_do(n, &branch)) {
  4749. ASSERT_OK(db_impl->Flush(fopt));
  4750. seq = db_impl->TEST_GetLastVisibleSequence();
  4751. ASSERT_EQ(exp_seq, seq);
  4752. }
  4753. if (!short_test && branch_do(n, &branch)) {
  4754. ASSERT_OK(db_impl->FlushWAL(true));
  4755. ASSERT_OK(ReOpenNoDelete());
  4756. db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  4757. seq = db_impl->GetLatestSequenceNumber();
  4758. ASSERT_EQ(exp_seq, seq);
  4759. }
  4760. TestTxn3(0);
  4761. seq = db_impl->TEST_GetLastVisibleSequence();
  4762. ASSERT_EQ(exp_seq, seq);
  4763. if (branch_do(n, &branch)) {
  4764. ASSERT_OK(db_impl->Flush(fopt));
  4765. seq = db_impl->TEST_GetLastVisibleSequence();
  4766. ASSERT_EQ(exp_seq, seq);
  4767. }
  4768. if (!short_test && branch_do(n, &branch)) {
  4769. ASSERT_OK(db_impl->FlushWAL(true));
  4770. ASSERT_OK(ReOpenNoDelete());
  4771. db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  4772. seq = db_impl->GetLatestSequenceNumber();
  4773. ASSERT_EQ(exp_seq, seq);
  4774. }
  4775. TestTxn4(0);
  4776. seq = db_impl->TEST_GetLastVisibleSequence();
  4777. ASSERT_EQ(exp_seq, seq);
  4778. if (branch_do(n, &branch)) {
  4779. ASSERT_OK(db_impl->Flush(fopt));
  4780. seq = db_impl->TEST_GetLastVisibleSequence();
  4781. ASSERT_EQ(exp_seq, seq);
  4782. }
  4783. if (!short_test && branch_do(n, &branch)) {
  4784. ASSERT_OK(db_impl->FlushWAL(true));
  4785. ASSERT_OK(ReOpenNoDelete());
  4786. db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  4787. seq = db_impl->GetLatestSequenceNumber();
  4788. ASSERT_EQ(exp_seq, seq);
  4789. }
  4790. TestTxn2(0);
  4791. seq = db_impl->TEST_GetLastVisibleSequence();
  4792. ASSERT_EQ(exp_seq, seq);
  4793. if (branch_do(n, &branch)) {
  4794. ASSERT_OK(db_impl->Flush(fopt));
  4795. seq = db_impl->TEST_GetLastVisibleSequence();
  4796. ASSERT_EQ(exp_seq, seq);
  4797. }
  4798. if (!short_test && branch_do(n, &branch)) {
  4799. ASSERT_OK(db_impl->FlushWAL(true));
  4800. ASSERT_OK(ReOpenNoDelete());
  4801. db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  4802. seq = db_impl->GetLatestSequenceNumber();
  4803. ASSERT_EQ(exp_seq, seq);
  4804. }
  4805. ASSERT_OK(ReOpen());
  4806. }
  4807. }
  4808. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  4809. // Verify that the optimization would not compromize the correctness
  4810. TEST_P(TransactionTest, Optimizations) {
  4811. size_t comb_cnt = size_t(1) << 2; // 2 is number of optimization vars
  4812. for (size_t new_comb = 0; new_comb < comb_cnt; new_comb++) {
  4813. TransactionDBWriteOptimizations optimizations;
  4814. optimizations.skip_concurrency_control = IsInCombination(0, new_comb);
  4815. optimizations.skip_duplicate_key_check = IsInCombination(1, new_comb);
  4816. ASSERT_OK(ReOpen());
  4817. WriteOptions write_options;
  4818. WriteBatch batch;
  4819. ASSERT_OK(batch.Put(Slice("k"), Slice("v1")));
  4820. ASSERT_OK(db->Write(write_options, &batch));
  4821. ReadOptions ropt;
  4822. PinnableSlice pinnable_val;
  4823. ASSERT_OK(db->Get(ropt, db->DefaultColumnFamily(), "k", &pinnable_val));
  4824. ASSERT_TRUE(pinnable_val == ("v1"));
  4825. }
  4826. }
  4827. // A comparator that uses only the first three bytes
  4828. class ThreeBytewiseComparator : public Comparator {
  4829. public:
  4830. ThreeBytewiseComparator() = default;
  4831. const char* Name() const override { return "test.ThreeBytewiseComparator"; }
  4832. int Compare(const Slice& a, const Slice& b) const override {
  4833. Slice na = Slice(a.data(), a.size() < 3 ? a.size() : 3);
  4834. Slice nb = Slice(b.data(), b.size() < 3 ? b.size() : 3);
  4835. return na.compare(nb);
  4836. }
  4837. bool Equal(const Slice& a, const Slice& b) const override {
  4838. Slice na = Slice(a.data(), a.size() < 3 ? a.size() : 3);
  4839. Slice nb = Slice(b.data(), b.size() < 3 ? b.size() : 3);
  4840. return na == nb;
  4841. }
  4842. // These methods below don't seem relevant to this test. Implement them if
  4843. // proven othersize.
  4844. void FindShortestSeparator(std::string* start,
  4845. const Slice& limit) const override {
  4846. const Comparator* bytewise_comp = BytewiseComparator();
  4847. bytewise_comp->FindShortestSeparator(start, limit);
  4848. }
  4849. void FindShortSuccessor(std::string* key) const override {
  4850. const Comparator* bytewise_comp = BytewiseComparator();
  4851. bytewise_comp->FindShortSuccessor(key);
  4852. }
  4853. };
  4854. #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  4855. TEST_P(TransactionTest, GetWithoutSnapshot) {
  4856. WriteOptions write_options;
  4857. std::atomic<bool> finish = {false};
  4858. ASSERT_OK(db->Put(write_options, "key", "value"));
  4859. ROCKSDB_NAMESPACE::port::Thread commit_thread([&]() {
  4860. for (int i = 0; i < 100; i++) {
  4861. TransactionOptions txn_options;
  4862. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  4863. ASSERT_OK(txn->SetName("xid"));
  4864. ASSERT_OK(txn->Put("key", "overridedvalue"));
  4865. ASSERT_OK(txn->Put("key", "value"));
  4866. ASSERT_OK(txn->Prepare());
  4867. ASSERT_OK(txn->Commit());
  4868. delete txn;
  4869. }
  4870. finish = true;
  4871. });
  4872. ROCKSDB_NAMESPACE::port::Thread read_thread([&]() {
  4873. while (!finish) {
  4874. ReadOptions ropt;
  4875. PinnableSlice pinnable_val;
  4876. ASSERT_OK(db->Get(ropt, db->DefaultColumnFamily(), "key", &pinnable_val));
  4877. ASSERT_TRUE(pinnable_val == ("value"));
  4878. }
  4879. });
  4880. commit_thread.join();
  4881. read_thread.join();
  4882. }
  4883. #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
  4884. // Test that the transactional db can handle duplicate keys in the write batch
  4885. TEST_P(TransactionTest, DuplicateKeys) {
  4886. ColumnFamilyOptions cf_options;
  4887. std::string cf_name = "two";
  4888. ColumnFamilyHandle* cf_handle = nullptr;
  4889. {
  4890. ASSERT_OK(db->CreateColumnFamily(cf_options, cf_name, &cf_handle));
  4891. WriteOptions write_options;
  4892. WriteBatch batch;
  4893. ASSERT_OK(batch.Put(Slice("key"), Slice("value")));
  4894. ASSERT_OK(batch.Put(Slice("key2"), Slice("value2")));
  4895. // duplicate the keys
  4896. ASSERT_OK(batch.Put(Slice("key"), Slice("value3")));
  4897. // duplicate the 2nd key. It should not be counted duplicate since a
  4898. // sub-patch is cut after the last duplicate.
  4899. ASSERT_OK(batch.Put(Slice("key2"), Slice("value4")));
  4900. // duplicate the keys but in a different cf. It should not be counted as
  4901. // duplicate keys
  4902. ASSERT_OK(batch.Put(cf_handle, Slice("key"), Slice("value5")));
  4903. ASSERT_OK(db->Write(write_options, &batch));
  4904. ReadOptions ropt;
  4905. PinnableSlice pinnable_val;
  4906. auto s = db->Get(ropt, db->DefaultColumnFamily(), "key", &pinnable_val);
  4907. ASSERT_OK(s);
  4908. ASSERT_TRUE(pinnable_val == ("value3"));
  4909. s = db->Get(ropt, db->DefaultColumnFamily(), "key2", &pinnable_val);
  4910. ASSERT_OK(s);
  4911. ASSERT_TRUE(pinnable_val == ("value4"));
  4912. s = db->Get(ropt, cf_handle, "key", &pinnable_val);
  4913. ASSERT_OK(s);
  4914. ASSERT_TRUE(pinnable_val == ("value5"));
  4915. delete cf_handle;
  4916. }
  4917. // Test with non-bytewise comparator
  4918. {
  4919. ASSERT_OK(ReOpen());
  4920. std::unique_ptr<const Comparator> comp_gc(new ThreeBytewiseComparator());
  4921. cf_options.comparator = comp_gc.get();
  4922. ASSERT_OK(db->CreateColumnFamily(cf_options, cf_name, &cf_handle));
  4923. WriteOptions write_options;
  4924. WriteBatch batch;
  4925. ASSERT_OK(batch.Put(cf_handle, Slice("key"), Slice("value")));
  4926. // The first three bytes are the same, do it must be counted as duplicate
  4927. ASSERT_OK(batch.Put(cf_handle, Slice("key2"), Slice("value2")));
  4928. // check for 2nd duplicate key in cf with non-default comparator
  4929. ASSERT_OK(batch.Put(cf_handle, Slice("key2b"), Slice("value2b")));
  4930. ASSERT_OK(db->Write(write_options, &batch));
  4931. // The value must be the most recent value for all the keys equal to "key",
  4932. // including "key2"
  4933. ReadOptions ropt;
  4934. PinnableSlice pinnable_val;
  4935. ASSERT_OK(db->Get(ropt, cf_handle, "key", &pinnable_val));
  4936. ASSERT_TRUE(pinnable_val == ("value2b"));
  4937. // Test duplicate keys with rollback
  4938. TransactionOptions txn_options;
  4939. Transaction* txn0 = db->BeginTransaction(write_options, txn_options);
  4940. ASSERT_OK(txn0->SetName("xid"));
  4941. ASSERT_OK(txn0->Put(cf_handle, Slice("key3"), Slice("value3")));
  4942. ASSERT_OK(txn0->Merge(cf_handle, Slice("key4"), Slice("value4")));
  4943. ASSERT_OK(txn0->Rollback());
  4944. ASSERT_OK(db->Get(ropt, cf_handle, "key5", &pinnable_val));
  4945. ASSERT_TRUE(pinnable_val == ("value2b"));
  4946. delete txn0;
  4947. delete cf_handle;
  4948. cf_options.comparator = BytewiseComparator();
  4949. }
  4950. for (bool do_prepare : {true, false}) {
  4951. for (bool do_rollback : {true, false}) {
  4952. for (bool with_commit_batch : {true, false}) {
  4953. if (with_commit_batch && !do_prepare) {
  4954. continue;
  4955. }
  4956. if (with_commit_batch && do_rollback) {
  4957. continue;
  4958. }
  4959. ASSERT_OK(ReOpen());
  4960. ASSERT_OK(db->CreateColumnFamily(cf_options, cf_name, &cf_handle));
  4961. TransactionOptions txn_options;
  4962. txn_options.use_only_the_last_commit_time_batch_for_recovery = true;
  4963. WriteOptions write_options;
  4964. Transaction* txn0 = db->BeginTransaction(write_options, txn_options);
  4965. auto s = txn0->SetName("xid");
  4966. ASSERT_OK(s);
  4967. s = txn0->Put(Slice("foo0"), Slice("bar0a"));
  4968. ASSERT_OK(s);
  4969. s = txn0->Put(Slice("foo0"), Slice("bar0b"));
  4970. ASSERT_OK(s);
  4971. s = txn0->Put(Slice("foo1"), Slice("bar1"));
  4972. ASSERT_OK(s);
  4973. s = txn0->Merge(Slice("foo2"), Slice("bar2a"));
  4974. ASSERT_OK(s);
  4975. // Repeat a key after the start of a sub-patch. This should not cause a
  4976. // duplicate in the most recent sub-patch and hence not creating a new
  4977. // sub-patch.
  4978. s = txn0->Put(Slice("foo0"), Slice("bar0c"));
  4979. ASSERT_OK(s);
  4980. s = txn0->Merge(Slice("foo2"), Slice("bar2b"));
  4981. ASSERT_OK(s);
  4982. // duplicate the keys but in a different cf. It should not be counted as
  4983. // duplicate.
  4984. s = txn0->Put(cf_handle, Slice("foo0"), Slice("bar0-cf1"));
  4985. ASSERT_OK(s);
  4986. s = txn0->Put(Slice("foo3"), Slice("bar3"));
  4987. ASSERT_OK(s);
  4988. s = txn0->Merge(Slice("foo3"), Slice("bar3"));
  4989. ASSERT_OK(s);
  4990. s = txn0->Put(Slice("foo4"), Slice("bar4"));
  4991. ASSERT_OK(s);
  4992. s = txn0->Delete(Slice("foo4"));
  4993. ASSERT_OK(s);
  4994. s = txn0->SingleDelete(Slice("foo4"));
  4995. ASSERT_OK(s);
  4996. if (do_prepare) {
  4997. s = txn0->Prepare();
  4998. ASSERT_OK(s);
  4999. }
  5000. if (do_rollback) {
  5001. // Test rolling back the batch with duplicates
  5002. s = txn0->Rollback();
  5003. ASSERT_OK(s);
  5004. } else {
  5005. if (with_commit_batch) {
  5006. assert(do_prepare);
  5007. auto cb = txn0->GetCommitTimeWriteBatch();
  5008. // duplicate a key in the original batch
  5009. // TODO(myabandeh): the behavior of GetCommitTimeWriteBatch
  5010. // conflicting with the prepared batch is currently undefined and
  5011. // gives different results in different implementations.
  5012. // s = cb->Put(Slice("foo0"), Slice("bar0d"));
  5013. // ASSERT_OK(s);
  5014. // add a new duplicate key
  5015. s = cb->Put(Slice("foo6"), Slice("bar6a"));
  5016. ASSERT_OK(s);
  5017. s = cb->Put(Slice("foo6"), Slice("bar6b"));
  5018. ASSERT_OK(s);
  5019. // add a duplicate key that is removed in the same batch
  5020. s = cb->Put(Slice("foo7"), Slice("bar7a"));
  5021. ASSERT_OK(s);
  5022. s = cb->Delete(Slice("foo7"));
  5023. ASSERT_OK(s);
  5024. }
  5025. s = txn0->Commit();
  5026. ASSERT_OK(s);
  5027. }
  5028. delete txn0;
  5029. ReadOptions ropt;
  5030. PinnableSlice pinnable_val;
  5031. if (do_rollback) {
  5032. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5033. ASSERT_TRUE(s.IsNotFound());
  5034. s = db->Get(ropt, cf_handle, "foo0", &pinnable_val);
  5035. ASSERT_TRUE(s.IsNotFound());
  5036. s = db->Get(ropt, db->DefaultColumnFamily(), "foo1", &pinnable_val);
  5037. ASSERT_TRUE(s.IsNotFound());
  5038. s = db->Get(ropt, db->DefaultColumnFamily(), "foo2", &pinnable_val);
  5039. ASSERT_TRUE(s.IsNotFound());
  5040. s = db->Get(ropt, db->DefaultColumnFamily(), "foo3", &pinnable_val);
  5041. ASSERT_TRUE(s.IsNotFound());
  5042. s = db->Get(ropt, db->DefaultColumnFamily(), "foo4", &pinnable_val);
  5043. ASSERT_TRUE(s.IsNotFound());
  5044. } else {
  5045. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5046. ASSERT_OK(s);
  5047. ASSERT_TRUE(pinnable_val == ("bar0c"));
  5048. s = db->Get(ropt, cf_handle, "foo0", &pinnable_val);
  5049. ASSERT_OK(s);
  5050. ASSERT_TRUE(pinnable_val == ("bar0-cf1"));
  5051. s = db->Get(ropt, db->DefaultColumnFamily(), "foo1", &pinnable_val);
  5052. ASSERT_OK(s);
  5053. ASSERT_TRUE(pinnable_val == ("bar1"));
  5054. s = db->Get(ropt, db->DefaultColumnFamily(), "foo2", &pinnable_val);
  5055. ASSERT_OK(s);
  5056. ASSERT_TRUE(pinnable_val == ("bar2a,bar2b"));
  5057. s = db->Get(ropt, db->DefaultColumnFamily(), "foo3", &pinnable_val);
  5058. ASSERT_OK(s);
  5059. ASSERT_TRUE(pinnable_val == ("bar3,bar3"));
  5060. s = db->Get(ropt, db->DefaultColumnFamily(), "foo4", &pinnable_val);
  5061. ASSERT_TRUE(s.IsNotFound());
  5062. if (with_commit_batch) {
  5063. s = db->Get(ropt, db->DefaultColumnFamily(), "foo6", &pinnable_val);
  5064. if (txn_db_options.write_policy ==
  5065. TxnDBWritePolicy::WRITE_COMMITTED) {
  5066. ASSERT_OK(s);
  5067. ASSERT_TRUE(pinnable_val == ("bar6b"));
  5068. } else {
  5069. ASSERT_TRUE(s.IsNotFound());
  5070. }
  5071. s = db->Get(ropt, db->DefaultColumnFamily(), "foo7", &pinnable_val);
  5072. ASSERT_TRUE(s.IsNotFound());
  5073. }
  5074. }
  5075. delete cf_handle;
  5076. } // with_commit_batch
  5077. } // do_rollback
  5078. } // do_prepare
  5079. if (!options.unordered_write) {
  5080. // Also test with max_successive_merges > 0. max_successive_merges will not
  5081. // affect our algorithm for duplicate key insertion but we add the test to
  5082. // verify that.
  5083. cf_options.max_successive_merges = 2;
  5084. cf_options.merge_operator = MergeOperators::CreateStringAppendOperator();
  5085. ASSERT_OK(ReOpen());
  5086. ASSERT_OK(db->CreateColumnFamily(cf_options, cf_name, &cf_handle));
  5087. WriteOptions write_options;
  5088. // Ensure one value for the key
  5089. ASSERT_OK(db->Put(write_options, cf_handle, Slice("key"), Slice("value")));
  5090. WriteBatch batch;
  5091. // Merge more than max_successive_merges times
  5092. ASSERT_OK(batch.Merge(cf_handle, Slice("key"), Slice("1")));
  5093. ASSERT_OK(batch.Merge(cf_handle, Slice("key"), Slice("2")));
  5094. ASSERT_OK(batch.Merge(cf_handle, Slice("key"), Slice("3")));
  5095. ASSERT_OK(batch.Merge(cf_handle, Slice("key"), Slice("4")));
  5096. ASSERT_OK(db->Write(write_options, &batch));
  5097. ReadOptions read_options;
  5098. std::string value;
  5099. ASSERT_OK(db->Get(read_options, cf_handle, "key", &value));
  5100. ASSERT_EQ(value, "value,1,2,3,4");
  5101. delete cf_handle;
  5102. }
  5103. {
  5104. // Test that the duplicate detection is not compromised after rolling back
  5105. // to a save point
  5106. TransactionOptions txn_options;
  5107. WriteOptions write_options;
  5108. Transaction* txn0 = db->BeginTransaction(write_options, txn_options);
  5109. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0a")));
  5110. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0b")));
  5111. txn0->SetSavePoint();
  5112. ASSERT_OK(txn0->RollbackToSavePoint());
  5113. ASSERT_OK(txn0->Commit());
  5114. delete txn0;
  5115. }
  5116. // Test sucessfull recovery after a crash
  5117. {
  5118. ASSERT_OK(ReOpen());
  5119. TransactionOptions txn_options;
  5120. WriteOptions write_options;
  5121. ReadOptions ropt;
  5122. Transaction* txn0;
  5123. PinnableSlice pinnable_val;
  5124. Status s;
  5125. std::unique_ptr<const Comparator> comp_gc(new ThreeBytewiseComparator());
  5126. cf_options.comparator = comp_gc.get();
  5127. cf_options.merge_operator = MergeOperators::CreateStringAppendOperator();
  5128. ASSERT_OK(db->CreateColumnFamily(cf_options, cf_name, &cf_handle));
  5129. delete cf_handle;
  5130. std::vector<ColumnFamilyDescriptor> cfds{
  5131. ColumnFamilyDescriptor(kDefaultColumnFamilyName,
  5132. ColumnFamilyOptions(options)),
  5133. ColumnFamilyDescriptor(cf_name, cf_options),
  5134. };
  5135. std::vector<ColumnFamilyHandle*> handles;
  5136. ASSERT_OK(ReOpenNoDelete(cfds, &handles));
  5137. assert(db != nullptr);
  5138. ASSERT_OK(db->Put(write_options, "foo0", "init"));
  5139. ASSERT_OK(db->Put(write_options, "foo1", "init"));
  5140. ASSERT_OK(db->Put(write_options, handles[1], "foo0", "init"));
  5141. ASSERT_OK(db->Put(write_options, handles[1], "foo1", "init"));
  5142. // one entry
  5143. txn0 = db->BeginTransaction(write_options, txn_options);
  5144. ASSERT_OK(txn0->SetName("xid"));
  5145. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0a")));
  5146. ASSERT_OK(txn0->Prepare());
  5147. delete txn0;
  5148. // This will check the asserts inside recovery code
  5149. ASSERT_OK(db->FlushWAL(true));
  5150. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  5151. ASSERT_OK(ReOpenNoDelete(cfds, &handles));
  5152. txn0 = db->GetTransactionByName("xid");
  5153. ASSERT_TRUE(txn0 != nullptr);
  5154. ASSERT_OK(txn0->Commit());
  5155. delete txn0;
  5156. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5157. ASSERT_OK(s);
  5158. ASSERT_TRUE(pinnable_val == ("bar0a"));
  5159. // two entries, no duplicate
  5160. txn0 = db->BeginTransaction(write_options, txn_options);
  5161. ASSERT_OK(txn0->SetName("xid"));
  5162. ASSERT_OK(txn0->Put(handles[1], Slice("foo0"), Slice("bar0b")));
  5163. ASSERT_OK(txn0->Put(handles[1], Slice("fol1"), Slice("bar1b")));
  5164. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0b")));
  5165. ASSERT_OK(txn0->Put(Slice("foo1"), Slice("bar1b")));
  5166. ASSERT_OK(txn0->Prepare());
  5167. delete txn0;
  5168. // This will check the asserts inside recovery code
  5169. ASSERT_OK(db->FlushWAL(true));
  5170. // Flush only cf 1
  5171. ASSERT_OK(static_cast_with_check<DBImpl>(db->GetRootDB())
  5172. ->TEST_FlushMemTable(true, false, handles[1]));
  5173. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  5174. ASSERT_OK(ReOpenNoDelete(cfds, &handles));
  5175. txn0 = db->GetTransactionByName("xid");
  5176. ASSERT_TRUE(txn0 != nullptr);
  5177. ASSERT_OK(txn0->Commit());
  5178. delete txn0;
  5179. pinnable_val.Reset();
  5180. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5181. ASSERT_OK(s);
  5182. ASSERT_TRUE(pinnable_val == ("bar0b"));
  5183. pinnable_val.Reset();
  5184. s = db->Get(ropt, db->DefaultColumnFamily(), "foo1", &pinnable_val);
  5185. ASSERT_OK(s);
  5186. ASSERT_TRUE(pinnable_val == ("bar1b"));
  5187. pinnable_val.Reset();
  5188. s = db->Get(ropt, handles[1], "foo0", &pinnable_val);
  5189. ASSERT_OK(s);
  5190. ASSERT_TRUE(pinnable_val == ("bar0b"));
  5191. pinnable_val.Reset();
  5192. s = db->Get(ropt, handles[1], "fol1", &pinnable_val);
  5193. ASSERT_OK(s);
  5194. ASSERT_TRUE(pinnable_val == ("bar1b"));
  5195. // one duplicate with ::Put
  5196. txn0 = db->BeginTransaction(write_options, txn_options);
  5197. ASSERT_OK(txn0->SetName("xid"));
  5198. ASSERT_OK(txn0->Put(handles[1], Slice("key-nonkey0"), Slice("bar0c")));
  5199. ASSERT_OK(txn0->Put(handles[1], Slice("key-nonkey1"), Slice("bar1d")));
  5200. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0c")));
  5201. ASSERT_OK(txn0->Put(Slice("foo1"), Slice("bar1c")));
  5202. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0d")));
  5203. ASSERT_OK(txn0->Prepare());
  5204. delete txn0;
  5205. // This will check the asserts inside recovery code
  5206. ASSERT_OK(db->FlushWAL(true));
  5207. // Flush only cf 1
  5208. ASSERT_OK(static_cast_with_check<DBImpl>(db->GetRootDB())
  5209. ->TEST_FlushMemTable(true, false, handles[1]));
  5210. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  5211. ASSERT_OK(ReOpenNoDelete(cfds, &handles));
  5212. txn0 = db->GetTransactionByName("xid");
  5213. ASSERT_TRUE(txn0 != nullptr);
  5214. ASSERT_OK(txn0->Commit());
  5215. delete txn0;
  5216. pinnable_val.Reset();
  5217. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5218. ASSERT_OK(s);
  5219. ASSERT_TRUE(pinnable_val == ("bar0d"));
  5220. pinnable_val.Reset();
  5221. s = db->Get(ropt, db->DefaultColumnFamily(), "foo1", &pinnable_val);
  5222. ASSERT_OK(s);
  5223. ASSERT_TRUE(pinnable_val == ("bar1c"));
  5224. pinnable_val.Reset();
  5225. s = db->Get(ropt, handles[1], "key-nonkey2", &pinnable_val);
  5226. ASSERT_OK(s);
  5227. ASSERT_TRUE(pinnable_val == ("bar1d"));
  5228. // Duplicate with ::Put, ::Delete
  5229. txn0 = db->BeginTransaction(write_options, txn_options);
  5230. ASSERT_OK(txn0->SetName("xid"));
  5231. ASSERT_OK(txn0->Put(handles[1], Slice("key-nonkey0"), Slice("bar0e")));
  5232. ASSERT_OK(txn0->Delete(handles[1], Slice("key-nonkey1")));
  5233. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0e")));
  5234. ASSERT_OK(txn0->Delete(Slice("foo0")));
  5235. ASSERT_OK(txn0->Prepare());
  5236. delete txn0;
  5237. // This will check the asserts inside recovery code
  5238. ASSERT_OK(db->FlushWAL(true));
  5239. // Flush only cf 1
  5240. ASSERT_OK(static_cast_with_check<DBImpl>(db->GetRootDB())
  5241. ->TEST_FlushMemTable(true, false, handles[1]));
  5242. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  5243. ASSERT_OK(ReOpenNoDelete(cfds, &handles));
  5244. txn0 = db->GetTransactionByName("xid");
  5245. ASSERT_TRUE(txn0 != nullptr);
  5246. ASSERT_OK(txn0->Commit());
  5247. delete txn0;
  5248. pinnable_val.Reset();
  5249. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5250. ASSERT_TRUE(s.IsNotFound());
  5251. pinnable_val.Reset();
  5252. s = db->Get(ropt, handles[1], "key-nonkey2", &pinnable_val);
  5253. ASSERT_TRUE(s.IsNotFound());
  5254. // Duplicate with ::Put, ::SingleDelete
  5255. txn0 = db->BeginTransaction(write_options, txn_options);
  5256. ASSERT_OK(txn0->SetName("xid"));
  5257. ASSERT_OK(txn0->Put(handles[1], Slice("key-nonkey0"), Slice("bar0g")));
  5258. ASSERT_OK(txn0->SingleDelete(handles[1], Slice("key-nonkey1")));
  5259. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0e")));
  5260. ASSERT_OK(txn0->SingleDelete(Slice("foo0")));
  5261. ASSERT_OK(txn0->Prepare());
  5262. delete txn0;
  5263. // This will check the asserts inside recovery code
  5264. ASSERT_OK(db->FlushWAL(true));
  5265. // Flush only cf 1
  5266. ASSERT_OK(static_cast_with_check<DBImpl>(db->GetRootDB())
  5267. ->TEST_FlushMemTable(true, false, handles[1]));
  5268. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  5269. ASSERT_OK(ReOpenNoDelete(cfds, &handles));
  5270. txn0 = db->GetTransactionByName("xid");
  5271. ASSERT_TRUE(txn0 != nullptr);
  5272. ASSERT_OK(txn0->Commit());
  5273. delete txn0;
  5274. pinnable_val.Reset();
  5275. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5276. ASSERT_TRUE(s.IsNotFound());
  5277. pinnable_val.Reset();
  5278. s = db->Get(ropt, handles[1], "key-nonkey2", &pinnable_val);
  5279. ASSERT_TRUE(s.IsNotFound());
  5280. // Duplicate with ::Put, ::Merge
  5281. txn0 = db->BeginTransaction(write_options, txn_options);
  5282. ASSERT_OK(txn0->SetName("xid"));
  5283. ASSERT_OK(txn0->Put(handles[1], Slice("key-nonkey0"), Slice("bar1i")));
  5284. ASSERT_OK(txn0->Merge(handles[1], Slice("key-nonkey1"), Slice("bar1j")));
  5285. ASSERT_OK(txn0->Put(Slice("foo0"), Slice("bar0f")));
  5286. ASSERT_OK(txn0->Merge(Slice("foo0"), Slice("bar0g")));
  5287. ASSERT_OK(txn0->Prepare());
  5288. delete txn0;
  5289. // This will check the asserts inside recovery code
  5290. ASSERT_OK(db->FlushWAL(true));
  5291. // Flush only cf 1
  5292. ASSERT_OK(static_cast_with_check<DBImpl>(db->GetRootDB())
  5293. ->TEST_FlushMemTable(true, false, handles[1]));
  5294. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  5295. ASSERT_OK(ReOpenNoDelete(cfds, &handles));
  5296. txn0 = db->GetTransactionByName("xid");
  5297. ASSERT_TRUE(txn0 != nullptr);
  5298. ASSERT_OK(txn0->Commit());
  5299. delete txn0;
  5300. pinnable_val.Reset();
  5301. s = db->Get(ropt, db->DefaultColumnFamily(), "foo0", &pinnable_val);
  5302. ASSERT_OK(s);
  5303. ASSERT_TRUE(pinnable_val == ("bar0f,bar0g"));
  5304. pinnable_val.Reset();
  5305. s = db->Get(ropt, handles[1], "key-nonkey2", &pinnable_val);
  5306. ASSERT_OK(s);
  5307. ASSERT_TRUE(pinnable_val == ("bar1i,bar1j"));
  5308. for (auto h : handles) {
  5309. delete h;
  5310. }
  5311. delete db;
  5312. db = nullptr;
  5313. }
  5314. }
  5315. // Test that the reseek optimization in iterators will not result in an infinite
  5316. // loop if there are too many uncommitted entries before the snapshot.
  5317. TEST_P(TransactionTest, ReseekOptimization) {
  5318. WriteOptions write_options;
  5319. write_options.sync = true;
  5320. write_options.disableWAL = false;
  5321. ColumnFamilyDescriptor cfd;
  5322. ASSERT_OK(db->DefaultColumnFamily()->GetDescriptor(&cfd));
  5323. auto max_skip = cfd.options.max_sequential_skip_in_iterations;
  5324. ASSERT_OK(db->Put(write_options, Slice("foo0"), Slice("initv")));
  5325. TransactionOptions txn_options;
  5326. Transaction* txn0 = db->BeginTransaction(write_options, txn_options);
  5327. ASSERT_OK(txn0->SetName("xid"));
  5328. // Duplicate keys will result into separate sequence numbers in WritePrepared
  5329. // and WriteUnPrepared
  5330. for (size_t i = 0; i < 2 * max_skip; i++) {
  5331. ASSERT_OK(txn0->Put(Slice("foo1"), Slice("bar")));
  5332. }
  5333. ASSERT_OK(txn0->Prepare());
  5334. ASSERT_OK(db->Put(write_options, Slice("foo2"), Slice("initv")));
  5335. ReadOptions read_options;
  5336. // To avoid loops
  5337. read_options.max_skippable_internal_keys = 10 * max_skip;
  5338. Iterator* iter = db->NewIterator(read_options);
  5339. ASSERT_OK(iter->status());
  5340. size_t cnt = 0;
  5341. iter->SeekToFirst();
  5342. while (iter->Valid()) {
  5343. iter->Next();
  5344. ASSERT_OK(iter->status());
  5345. cnt++;
  5346. }
  5347. ASSERT_EQ(cnt, 2);
  5348. cnt = 0;
  5349. iter->SeekToLast();
  5350. while (iter->Valid()) {
  5351. iter->Prev();
  5352. ASSERT_OK(iter->status());
  5353. cnt++;
  5354. }
  5355. ASSERT_EQ(cnt, 2);
  5356. delete iter;
  5357. ASSERT_OK(txn0->Rollback());
  5358. delete txn0;
  5359. }
  5360. // After recovery in kPointInTimeRecovery mode, the corrupted log file remains
  5361. // there. The new log files should be still read succesfully during recovery of
  5362. // the 2nd crash.
  5363. TEST_P(TransactionTest, DoubleCrashInRecovery) {
  5364. for (const bool manual_wal_flush : {false, true}) {
  5365. for (const bool write_after_recovery : {false, true}) {
  5366. options.wal_recovery_mode = WALRecoveryMode::kPointInTimeRecovery;
  5367. options.manual_wal_flush = manual_wal_flush;
  5368. ASSERT_OK(ReOpen());
  5369. std::string cf_name = "two";
  5370. ColumnFamilyOptions cf_options;
  5371. ColumnFamilyHandle* cf_handle = nullptr;
  5372. ASSERT_OK(db->CreateColumnFamily(cf_options, cf_name, &cf_handle));
  5373. // Add a prepare entry to prevent the older logs from being deleted.
  5374. WriteOptions write_options;
  5375. TransactionOptions txn_options;
  5376. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  5377. ASSERT_OK(txn->SetName("xid"));
  5378. ASSERT_OK(txn->Put(Slice("foo-prepare"), Slice("bar-prepare")));
  5379. ASSERT_OK(txn->Prepare());
  5380. FlushOptions flush_ops;
  5381. ASSERT_OK(db->Flush(flush_ops));
  5382. // Now we have a log that cannot be deleted
  5383. ASSERT_OK(db->Put(write_options, cf_handle, "foo1", "bar1"));
  5384. // Flush only the 2nd cf
  5385. ASSERT_OK(db->Flush(flush_ops, cf_handle));
  5386. // The value is large enough to be touched by the corruption we ingest
  5387. // below.
  5388. std::string large_value(400, ' ');
  5389. // key/value not touched by corruption
  5390. ASSERT_OK(db->Put(write_options, "foo2", "bar2"));
  5391. // key/value touched by corruption
  5392. ASSERT_OK(db->Put(write_options, "foo3", large_value));
  5393. // key/value not touched by corruption
  5394. ASSERT_OK(db->Put(write_options, "foo4", "bar4"));
  5395. ASSERT_OK(db->FlushWAL(true));
  5396. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  5397. uint64_t wal_file_id = db_impl->TEST_LogfileNumber();
  5398. std::string fname = LogFileName(dbname, wal_file_id);
  5399. static_cast<PessimisticTransactionDB*>(db)->TEST_Crash();
  5400. delete txn;
  5401. delete cf_handle;
  5402. delete db;
  5403. db = nullptr;
  5404. // Corrupt the last log file in the middle, so that it is not corrupted
  5405. // in the tail.
  5406. std::string file_content;
  5407. ASSERT_OK(ReadFileToString(env.get(), fname, &file_content));
  5408. file_content[400] = 'h';
  5409. file_content[401] = 'a';
  5410. ASSERT_OK(env->DeleteFile(fname));
  5411. ASSERT_OK(WriteStringToFile(env.get(), file_content, fname, true));
  5412. // Recover from corruption
  5413. std::vector<ColumnFamilyHandle*> handles;
  5414. std::vector<ColumnFamilyDescriptor> column_families;
  5415. column_families.emplace_back(kDefaultColumnFamilyName,
  5416. ColumnFamilyOptions());
  5417. column_families.emplace_back("two", ColumnFamilyOptions());
  5418. ASSERT_OK(ReOpenNoDelete(column_families, &handles));
  5419. assert(db != nullptr);
  5420. if (write_after_recovery) {
  5421. // Write data to the log right after the corrupted log
  5422. ASSERT_OK(db->Put(write_options, "foo5", large_value));
  5423. }
  5424. // Persist data written to WAL during recovery or by the last Put
  5425. ASSERT_OK(db->FlushWAL(true));
  5426. // 2nd crash to recover while having a valid log after the corrupted one.
  5427. ASSERT_OK(ReOpenNoDelete(column_families, &handles));
  5428. assert(db != nullptr);
  5429. txn = db->GetTransactionByName("xid");
  5430. ASSERT_TRUE(txn != nullptr);
  5431. ASSERT_OK(txn->Commit());
  5432. delete txn;
  5433. for (auto handle : handles) {
  5434. delete handle;
  5435. }
  5436. }
  5437. }
  5438. }
  5439. TEST_P(TransactionTest, CommitWithoutPrepare) {
  5440. {
  5441. // skip_prepare = false.
  5442. WriteOptions write_options;
  5443. TransactionOptions txn_options;
  5444. txn_options.skip_prepare = false;
  5445. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  5446. ASSERT_TRUE(txn->Commit().IsTxnNotPrepared());
  5447. delete txn;
  5448. }
  5449. {
  5450. // skip_prepare = true.
  5451. WriteOptions write_options;
  5452. TransactionOptions txn_options;
  5453. txn_options.skip_prepare = true;
  5454. Transaction* txn = db->BeginTransaction(write_options, txn_options);
  5455. ASSERT_OK(txn->Commit());
  5456. delete txn;
  5457. }
  5458. }
  5459. TEST_P(TransactionTest, OpenAndEnableU64Timestamp) {
  5460. ASSERT_OK(ReOpenNoDelete());
  5461. assert(db);
  5462. const std::string test_cf_name = "test_cf";
  5463. ColumnFamilyOptions cf_opts;
  5464. cf_opts.comparator = test::BytewiseComparatorWithU64TsWrapper();
  5465. {
  5466. ColumnFamilyHandle* cfh = nullptr;
  5467. const Status s = db->CreateColumnFamily(cf_opts, test_cf_name, &cfh);
  5468. if (txn_db_options.write_policy == WRITE_COMMITTED) {
  5469. ASSERT_OK(s);
  5470. delete cfh;
  5471. } else {
  5472. ASSERT_TRUE(s.IsNotSupported());
  5473. assert(!cfh);
  5474. }
  5475. }
  5476. // Bypass transaction db layer.
  5477. if (txn_db_options.write_policy != WRITE_COMMITTED) {
  5478. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  5479. assert(db_impl);
  5480. ColumnFamilyHandle* cfh = nullptr;
  5481. ASSERT_OK(db_impl->CreateColumnFamily(cf_opts, test_cf_name, &cfh));
  5482. delete cfh;
  5483. }
  5484. {
  5485. std::vector<ColumnFamilyDescriptor> cf_descs;
  5486. cf_descs.emplace_back(kDefaultColumnFamilyName, options);
  5487. cf_descs.emplace_back(test_cf_name, cf_opts);
  5488. std::vector<ColumnFamilyHandle*> handles;
  5489. const Status s = ReOpenNoDelete(cf_descs, &handles);
  5490. if (txn_db_options.write_policy == WRITE_COMMITTED) {
  5491. ASSERT_OK(s);
  5492. for (auto* h : handles) {
  5493. delete h;
  5494. }
  5495. } else {
  5496. ASSERT_TRUE(s.IsNotSupported());
  5497. }
  5498. }
  5499. }
  5500. TEST_P(TransactionTest, OpenAndEnableU32Timestamp) {
  5501. class DummyComparatorWithU32Ts : public Comparator {
  5502. public:
  5503. DummyComparatorWithU32Ts() : Comparator(sizeof(uint32_t)) {}
  5504. const char* Name() const override { return "DummyComparatorWithU32Ts"; }
  5505. void FindShortSuccessor(std::string*) const override {}
  5506. void FindShortestSeparator(std::string*, const Slice&) const override {}
  5507. int Compare(const Slice&, const Slice&) const override { return 0; }
  5508. };
  5509. std::unique_ptr<Comparator> dummy_ucmp(new DummyComparatorWithU32Ts());
  5510. ASSERT_OK(ReOpenNoDelete());
  5511. assert(db);
  5512. const std::string test_cf_name = "test_cf";
  5513. ColumnFamilyOptions cf_opts;
  5514. cf_opts.comparator = dummy_ucmp.get();
  5515. {
  5516. ColumnFamilyHandle* cfh = nullptr;
  5517. ASSERT_TRUE(db->CreateColumnFamily(cf_opts, test_cf_name, &cfh)
  5518. .IsInvalidArgument());
  5519. }
  5520. // Bypass transaction db layer.
  5521. {
  5522. ColumnFamilyHandle* cfh = nullptr;
  5523. DBImpl* db_impl = static_cast_with_check<DBImpl>(db->GetRootDB());
  5524. assert(db_impl);
  5525. ASSERT_OK(db_impl->CreateColumnFamily(cf_opts, test_cf_name, &cfh));
  5526. delete cfh;
  5527. }
  5528. {
  5529. std::vector<ColumnFamilyDescriptor> cf_descs;
  5530. cf_descs.emplace_back(kDefaultColumnFamilyName, options);
  5531. cf_descs.emplace_back(test_cf_name, cf_opts);
  5532. std::vector<ColumnFamilyHandle*> handles;
  5533. ASSERT_TRUE(ReOpenNoDelete(cf_descs, &handles).IsInvalidArgument());
  5534. }
  5535. }
  5536. TEST_P(TransactionTest, WriteWithBulkCreatedColumnFamilies) {
  5537. ColumnFamilyOptions cf_options;
  5538. WriteOptions write_options;
  5539. std::vector<std::string> cf_names;
  5540. std::vector<ColumnFamilyHandle*> cf_handles;
  5541. cf_names.emplace_back("test_cf");
  5542. ASSERT_OK(db->CreateColumnFamilies(cf_options, cf_names, &cf_handles));
  5543. ASSERT_OK(db->Put(write_options, cf_handles[0], "foo", "bar"));
  5544. ASSERT_OK(db->DropColumnFamilies(cf_handles));
  5545. for (auto* h : cf_handles) {
  5546. delete h;
  5547. }
  5548. cf_handles.clear();
  5549. std::vector<ColumnFamilyDescriptor> cf_descriptors;
  5550. cf_descriptors.emplace_back("test_cf", ColumnFamilyOptions());
  5551. ASSERT_OK(db->CreateColumnFamilies(cf_options, cf_names, &cf_handles));
  5552. ASSERT_OK(db->Put(write_options, cf_handles[0], "foo", "bar"));
  5553. ASSERT_OK(db->DropColumnFamilies(cf_handles));
  5554. for (auto* h : cf_handles) {
  5555. delete h;
  5556. }
  5557. cf_handles.clear();
  5558. }
  5559. TEST_P(TransactionTest, LockWal) {
  5560. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  5561. if (TxnDBWritePolicy::WRITE_COMMITTED != write_policy) {
  5562. ROCKSDB_GTEST_BYPASS("Test only write-committed for now");
  5563. return;
  5564. }
  5565. ASSERT_OK(ReOpen());
  5566. SyncPoint::GetInstance()->DisableProcessing();
  5567. SyncPoint::GetInstance()->LoadDependency(
  5568. {{"TransactionTest::LockWal:AfterLockWal",
  5569. "TransactionTest::LockWal:BeforePrepareTxn2"}});
  5570. SyncPoint::GetInstance()->EnableProcessing();
  5571. std::unique_ptr<Transaction> txn0;
  5572. WriteOptions wopts;
  5573. wopts.no_slowdown = true;
  5574. txn0.reset(db->BeginTransaction(wopts, TransactionOptions()));
  5575. ASSERT_OK(txn0->SetName("txn0"));
  5576. ASSERT_OK(txn0->Put("foo", "v0"));
  5577. std::unique_ptr<Transaction> txn1;
  5578. txn1.reset(db->BeginTransaction(wopts, TransactionOptions()));
  5579. ASSERT_OK(txn1->SetName("txn1"));
  5580. ASSERT_OK(txn1->Put("dummy", "v0"));
  5581. ASSERT_OK(txn1->Prepare());
  5582. std::unique_ptr<Transaction> txn2;
  5583. port::Thread worker([&]() {
  5584. txn2.reset(db->BeginTransaction(WriteOptions(), TransactionOptions()));
  5585. ASSERT_OK(txn2->SetName("txn2"));
  5586. ASSERT_OK(txn2->Put("bar", "v0"));
  5587. TEST_SYNC_POINT("TransactionTest::LockWal:BeforePrepareTxn2");
  5588. ASSERT_OK(txn2->Prepare());
  5589. ASSERT_OK(txn2->Commit());
  5590. });
  5591. ASSERT_OK(db->LockWAL());
  5592. // txn0 cannot prepare
  5593. Status s = txn0->Prepare();
  5594. ASSERT_TRUE(s.IsIncomplete());
  5595. // txn1 cannot commit
  5596. s = txn1->Commit();
  5597. ASSERT_TRUE(s.IsIncomplete());
  5598. TEST_SYNC_POINT("TransactionTest::LockWal:AfterLockWal");
  5599. ASSERT_OK(db->UnlockWAL());
  5600. txn0.reset();
  5601. txn0.reset(db->BeginTransaction(wopts, TransactionOptions()));
  5602. ASSERT_OK(txn0->SetName("txn0_1"));
  5603. ASSERT_OK(txn0->Put("foo", "v1"));
  5604. ASSERT_OK(txn0->Prepare());
  5605. ASSERT_OK(txn0->Commit());
  5606. worker.join();
  5607. SyncPoint::GetInstance()->DisableProcessing();
  5608. }
  5609. TEST_P(TransactionTest, StallTwoWriteQueues) {
  5610. // There was a two_write_queues bug in which both write thread leaders (for
  5611. // each queue) would attempt to own the stopping of writes in the primary
  5612. // write queue. This nearly worked but could lead to some broken assertions
  5613. // and a kind of deadlock in the test below. (Would resume if someone
  5614. // eventually signalled bg_cv_ again.)
  5615. if (!options.two_write_queues) {
  5616. ROCKSDB_GTEST_BYPASS("Test only needed with two_write_queues");
  5617. return;
  5618. }
  5619. // Stop writes
  5620. ASSERT_OK(db->LockWAL());
  5621. WriteOptions wopts;
  5622. wopts.sync = true;
  5623. wopts.disableWAL = false;
  5624. // Create one write thread that blocks in the primary write queue and one
  5625. // that blocks in the nonmem queue.
  5626. bool t1_completed = false;
  5627. bool t2_completed = false;
  5628. port::Thread t1{[&]() {
  5629. ASSERT_OK(db->Put(wopts, "x", "y"));
  5630. t1_completed = true;
  5631. }};
  5632. port::Thread t2{[&]() {
  5633. std::unique_ptr<Transaction> txn0{db->BeginTransaction(wopts, {})};
  5634. ASSERT_OK(txn0->SetName("xid"));
  5635. ASSERT_OK(txn0->Prepare()); // nonmem
  5636. ASSERT_OK(txn0->Commit());
  5637. t2_completed = true;
  5638. }};
  5639. // Sleep long enough to that above threads can usually reach a waiting point,
  5640. // to usually reveal deadlock if the bug is present.
  5641. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  5642. // Ensure proper test setup
  5643. ASSERT_FALSE(t1_completed);
  5644. ASSERT_FALSE(t2_completed);
  5645. // Resume writes
  5646. ASSERT_OK(db->UnlockWAL());
  5647. // Wait for writes to finish
  5648. t1.join();
  5649. t2.join();
  5650. // Ensure proper test setup
  5651. ASSERT_TRUE(t1_completed);
  5652. ASSERT_TRUE(t2_completed);
  5653. }
  5654. // Make sure UnlockWAL does not return until the stall it controls is cleared.
  5655. TEST_P(TransactionTest, UnlockWALStallCleared) {
  5656. auto dbimpl = static_cast_with_check<DBImpl>(db->GetRootDB());
  5657. for (bool external_stall : {false, true}) {
  5658. WriteOptions wopts;
  5659. wopts.sync = true;
  5660. wopts.disableWAL = false;
  5661. ASSERT_OK(db->Put(wopts, "k1", "val1"));
  5662. // Stall writes
  5663. ASSERT_OK(db->LockWAL());
  5664. std::unique_ptr<WriteControllerToken> token;
  5665. if (external_stall) {
  5666. // Also make sure UnlockWAL can return despite another stall being in
  5667. // effect.
  5668. token = dbimpl->TEST_write_controler().GetStopToken();
  5669. }
  5670. SyncPoint::GetInstance()->DisableProcessing();
  5671. std::vector<SyncPoint::SyncPointPair> sync_deps;
  5672. sync_deps.push_back(
  5673. {"DBImpl::DelayWrite:Wait",
  5674. "TransactionTest::UnlockWALStallCleared:BeforeUnlockWAL1"});
  5675. if (options.two_write_queues &&
  5676. txn_db_options.write_policy == WRITE_COMMITTED) {
  5677. sync_deps.push_back(
  5678. {"DBImpl::DelayWrite:NonmemWait",
  5679. "TransactionTest::UnlockWALStallCleared:BeforeUnlockWAL2"});
  5680. }
  5681. SyncPoint::GetInstance()->LoadDependency(sync_deps);
  5682. SyncPoint::GetInstance()->SetCallBack(
  5683. "DBImpl::DelayWrite:AfterWait", [](void* arg) {
  5684. auto& mu = *static_cast<CacheAlignedInstrumentedMutex*>(arg);
  5685. mu.AssertHeld();
  5686. // Pretend we are slow waking up from bg_cv_, to give a chance for the
  5687. // bug to occur if it can. Randomly prefer one queue over the other.
  5688. mu.Unlock();
  5689. if (Random::GetTLSInstance()->OneIn(2)) {
  5690. std::this_thread::sleep_for(std::chrono::milliseconds(10));
  5691. } else {
  5692. std::this_thread::yield();
  5693. }
  5694. mu.Lock();
  5695. });
  5696. SyncPoint::GetInstance()->EnableProcessing();
  5697. // Create blocking writes (for both queues) in background and use
  5698. // sync point dependency to get the stall into the write queue(s)
  5699. std::atomic<bool> t1_completed{false};
  5700. port::Thread t1{[&]() {
  5701. ASSERT_OK(db->Put(wopts, "k2", "val2"));
  5702. t1_completed = true;
  5703. }};
  5704. std::atomic<bool> t2_completed{false};
  5705. port::Thread t2{[&]() {
  5706. std::unique_ptr<Transaction> txn0{db->BeginTransaction(wopts, {})};
  5707. ASSERT_OK(txn0->SetName("x1"));
  5708. ASSERT_OK(txn0->Put("k3", "val3"));
  5709. ASSERT_OK(txn0->Prepare()); // nonmem
  5710. ASSERT_OK(txn0->Commit());
  5711. }};
  5712. // Be sure the test is set up appropriately
  5713. TEST_SYNC_POINT("TransactionTest::UnlockWALStallCleared:BeforeUnlockWAL1");
  5714. TEST_SYNC_POINT("TransactionTest::UnlockWALStallCleared:BeforeUnlockWAL2");
  5715. ASSERT_FALSE(t1_completed.load());
  5716. ASSERT_FALSE(t2_completed.load());
  5717. // Clear the stall
  5718. ASSERT_OK(db->UnlockWAL());
  5719. WriteOptions wopts2 = wopts;
  5720. if (external_stall) {
  5721. // We did not deadlock in UnlockWAL, so now async clear the external
  5722. // stall and then do a blocking write.
  5723. // DB mutex acquire+release is needed to ensure we don't reset token and
  5724. // signal while DelayWrite() is between IsStopped() and
  5725. // BeginWriteStall().
  5726. token.reset();
  5727. dbimpl->TEST_LockMutex();
  5728. dbimpl->TEST_UnlockMutex();
  5729. dbimpl->TEST_SignalAllBgCv();
  5730. } else {
  5731. // To verify the LockWAL stall is guaranteed cleared, do a non-blocking
  5732. // write that is attempting to catch a bug by attempting to come before
  5733. // the thread that did BeginWriteStall() can do EndWriteStall()
  5734. wopts2.no_slowdown = true;
  5735. }
  5736. std::unique_ptr<Transaction> txn0{db->BeginTransaction(wopts2, {})};
  5737. ASSERT_OK(txn0->SetName("x2"));
  5738. ASSERT_OK(txn0->Put("k1", "val4"));
  5739. ASSERT_OK(txn0->Prepare()); // nonmem
  5740. ASSERT_OK(txn0->Commit());
  5741. t1.join();
  5742. t2.join();
  5743. }
  5744. }
  5745. TEST_P(TransactionTest, PutEntitySuccess) {
  5746. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  5747. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  5748. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  5749. return;
  5750. }
  5751. constexpr char foo[] = "foo";
  5752. const WideColumns foo_columns{
  5753. {kDefaultWideColumnName, "bar"}, {"col1", "val1"}, {"col2", "val2"}};
  5754. const WideColumns foo_new_columns{
  5755. {kDefaultWideColumnName, "baz"}, {"colA", "valA"}, {"colB", "valB"}};
  5756. ASSERT_OK(db->PutEntity(WriteOptions(), db->DefaultColumnFamily(), foo,
  5757. foo_columns));
  5758. {
  5759. std::unique_ptr<Transaction> txn(
  5760. db->BeginTransaction(WriteOptions(), TransactionOptions()));
  5761. ASSERT_NE(txn, nullptr);
  5762. ASSERT_NE(txn->GetID(), 0);
  5763. ASSERT_EQ(txn->GetNumPutEntities(), 0);
  5764. {
  5765. PinnableWideColumns columns;
  5766. ASSERT_OK(txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo,
  5767. &columns));
  5768. ASSERT_EQ(columns.columns(), foo_columns);
  5769. }
  5770. {
  5771. PinnableWideColumns columns;
  5772. ASSERT_OK(txn->GetEntityForUpdate(
  5773. ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  5774. ASSERT_EQ(columns.columns(), foo_columns);
  5775. }
  5776. ASSERT_OK(txn->PutEntity(db->DefaultColumnFamily(), foo, foo_new_columns));
  5777. ASSERT_EQ(txn->GetNumPutEntities(), 1);
  5778. {
  5779. PinnableWideColumns columns;
  5780. ASSERT_OK(txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo,
  5781. &columns));
  5782. ASSERT_EQ(columns.columns(), foo_new_columns);
  5783. }
  5784. {
  5785. PinnableWideColumns columns;
  5786. ASSERT_OK(txn->GetEntityForUpdate(
  5787. ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  5788. ASSERT_EQ(columns.columns(), foo_new_columns);
  5789. }
  5790. ASSERT_OK(txn->Commit());
  5791. }
  5792. {
  5793. PinnableWideColumns columns;
  5794. ASSERT_OK(
  5795. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  5796. ASSERT_EQ(columns.columns(), foo_new_columns);
  5797. }
  5798. }
  5799. TEST_P(TransactionTest, PutEntityWriteConflict) {
  5800. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  5801. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  5802. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  5803. return;
  5804. }
  5805. constexpr char foo[] = "foo";
  5806. const WideColumns foo_columns{
  5807. {kDefaultWideColumnName, "bar"}, {"col1", "val1"}, {"col2", "val2"}};
  5808. constexpr char baz[] = "baz";
  5809. const WideColumns baz_columns{
  5810. {kDefaultWideColumnName, "quux"}, {"colA", "valA"}, {"colB", "valB"}};
  5811. ASSERT_OK(db->PutEntity(WriteOptions(), db->DefaultColumnFamily(), foo,
  5812. foo_columns));
  5813. ASSERT_OK(db->PutEntity(WriteOptions(), db->DefaultColumnFamily(), baz,
  5814. baz_columns));
  5815. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  5816. ASSERT_NE(txn, nullptr);
  5817. {
  5818. PinnableWideColumns columns;
  5819. ASSERT_OK(txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo,
  5820. &columns));
  5821. ASSERT_EQ(columns.columns(), foo_columns);
  5822. }
  5823. {
  5824. PinnableWideColumns columns;
  5825. ASSERT_OK(txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), baz,
  5826. &columns));
  5827. ASSERT_EQ(columns.columns(), baz_columns);
  5828. }
  5829. {
  5830. constexpr size_t num_keys = 2;
  5831. std::array<Slice, num_keys> keys{{foo, baz}};
  5832. std::array<PinnableWideColumns, num_keys> results;
  5833. std::array<Status, num_keys> statuses;
  5834. txn->MultiGetEntity(ReadOptions(), db->DefaultColumnFamily(), num_keys,
  5835. keys.data(), results.data(), statuses.data());
  5836. ASSERT_OK(statuses[0]);
  5837. ASSERT_OK(statuses[1]);
  5838. ASSERT_EQ(results[0].columns(), foo_columns);
  5839. ASSERT_EQ(results[1].columns(), baz_columns);
  5840. }
  5841. const WideColumns foo_new_columns{{kDefaultWideColumnName, "FOO"},
  5842. {"hello", "world"}};
  5843. const WideColumns baz_new_columns{{kDefaultWideColumnName, "BAZ"},
  5844. {"ping", "pong"}};
  5845. ASSERT_OK(txn->PutEntity(db->DefaultColumnFamily(), foo, foo_new_columns));
  5846. ASSERT_OK(txn->PutEntity(db->DefaultColumnFamily(), baz, baz_new_columns));
  5847. {
  5848. PinnableWideColumns columns;
  5849. ASSERT_OK(txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo,
  5850. &columns));
  5851. ASSERT_EQ(columns.columns(), foo_new_columns);
  5852. }
  5853. {
  5854. PinnableWideColumns columns;
  5855. ASSERT_OK(txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), baz,
  5856. &columns));
  5857. ASSERT_EQ(columns.columns(), baz_new_columns);
  5858. }
  5859. {
  5860. constexpr size_t num_keys = 2;
  5861. std::array<Slice, num_keys> keys{{foo, baz}};
  5862. std::array<PinnableWideColumns, num_keys> results;
  5863. std::array<Status, num_keys> statuses;
  5864. txn->MultiGetEntity(ReadOptions(), db->DefaultColumnFamily(), num_keys,
  5865. keys.data(), results.data(), statuses.data());
  5866. ASSERT_OK(statuses[0]);
  5867. ASSERT_OK(statuses[1]);
  5868. ASSERT_EQ(results[0].columns(), foo_new_columns);
  5869. ASSERT_EQ(results[1].columns(), baz_new_columns);
  5870. }
  5871. // This PutEntity outside of a transaction will conflict with the previous
  5872. // write
  5873. const WideColumns foo_conflict_columns{{kDefaultWideColumnName, "X"},
  5874. {"conflicting", "write"}};
  5875. ASSERT_TRUE(db->PutEntity(WriteOptions(), db->DefaultColumnFamily(), foo,
  5876. foo_conflict_columns)
  5877. .IsTimedOut());
  5878. {
  5879. PinnableWideColumns columns;
  5880. ASSERT_OK(
  5881. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  5882. ASSERT_EQ(columns.columns(), foo_columns);
  5883. }
  5884. {
  5885. PinnableWideColumns columns;
  5886. ASSERT_OK(
  5887. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), baz, &columns));
  5888. ASSERT_EQ(columns.columns(), baz_columns);
  5889. }
  5890. {
  5891. constexpr size_t num_keys = 2;
  5892. std::array<Slice, num_keys> keys{{foo, baz}};
  5893. std::array<PinnableWideColumns, num_keys> results;
  5894. std::array<Status, num_keys> statuses;
  5895. constexpr bool sorted_input = false;
  5896. db->MultiGetEntity(ReadOptions(), db->DefaultColumnFamily(), num_keys,
  5897. keys.data(), results.data(), statuses.data(),
  5898. sorted_input);
  5899. ASSERT_OK(statuses[0]);
  5900. ASSERT_OK(statuses[1]);
  5901. ASSERT_EQ(results[0].columns(), foo_columns);
  5902. ASSERT_EQ(results[1].columns(), baz_columns);
  5903. }
  5904. ASSERT_OK(txn->Commit());
  5905. {
  5906. PinnableWideColumns columns;
  5907. ASSERT_OK(
  5908. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  5909. ASSERT_EQ(columns.columns(), foo_new_columns);
  5910. }
  5911. {
  5912. PinnableWideColumns columns;
  5913. ASSERT_OK(
  5914. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), baz, &columns));
  5915. ASSERT_EQ(columns.columns(), baz_new_columns);
  5916. }
  5917. {
  5918. constexpr size_t num_keys = 2;
  5919. std::array<Slice, num_keys> keys{{foo, baz}};
  5920. std::array<PinnableWideColumns, num_keys> results;
  5921. std::array<Status, num_keys> statuses;
  5922. constexpr bool sorted_input = false;
  5923. db->MultiGetEntity(ReadOptions(), db->DefaultColumnFamily(), num_keys,
  5924. keys.data(), results.data(), statuses.data(),
  5925. sorted_input);
  5926. ASSERT_OK(statuses[0]);
  5927. ASSERT_OK(statuses[1]);
  5928. ASSERT_EQ(results[0].columns(), foo_new_columns);
  5929. ASSERT_EQ(results[1].columns(), baz_new_columns);
  5930. }
  5931. }
  5932. TEST_P(TransactionTest, PutEntityReadConflict) {
  5933. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  5934. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  5935. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  5936. return;
  5937. }
  5938. constexpr char foo[] = "foo";
  5939. const WideColumns foo_columns{
  5940. {kDefaultWideColumnName, "bar"}, {"col1", "val1"}, {"col2", "val2"}};
  5941. ASSERT_OK(db->PutEntity(WriteOptions(), db->DefaultColumnFamily(), foo,
  5942. foo_columns));
  5943. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  5944. ASSERT_NE(txn, nullptr);
  5945. txn->SetSnapshot();
  5946. ReadOptions snapshot_read_options;
  5947. snapshot_read_options.snapshot = txn->GetSnapshot();
  5948. {
  5949. PinnableWideColumns columns;
  5950. ASSERT_OK(txn->GetEntityForUpdate(
  5951. snapshot_read_options, db->DefaultColumnFamily(), foo, &columns));
  5952. ASSERT_EQ(columns.columns(), foo_columns);
  5953. }
  5954. // This PutEntity outside of a transaction will conflict with the previous
  5955. // write
  5956. const WideColumns foo_conflict_columns{{kDefaultWideColumnName, "X"},
  5957. {"conflicting", "write"}};
  5958. ASSERT_TRUE(db->PutEntity(WriteOptions(), db->DefaultColumnFamily(), foo,
  5959. foo_conflict_columns)
  5960. .IsTimedOut());
  5961. {
  5962. PinnableWideColumns columns;
  5963. ASSERT_OK(
  5964. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  5965. ASSERT_EQ(columns.columns(), foo_columns);
  5966. }
  5967. {
  5968. PinnableWideColumns columns;
  5969. ASSERT_OK(txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo,
  5970. &columns));
  5971. ASSERT_EQ(columns.columns(), foo_columns);
  5972. }
  5973. ASSERT_OK(txn->Commit());
  5974. {
  5975. PinnableWideColumns columns;
  5976. ASSERT_OK(
  5977. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  5978. ASSERT_EQ(columns.columns(), foo_columns);
  5979. }
  5980. }
  5981. TEST_P(TransactionTest, EntityReadSanityChecks) {
  5982. constexpr char foo[] = "foo";
  5983. constexpr char bar[] = "bar";
  5984. constexpr size_t num_keys = 2;
  5985. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  5986. ASSERT_NE(txn, nullptr);
  5987. {
  5988. constexpr ColumnFamilyHandle* column_family = nullptr;
  5989. PinnableWideColumns columns;
  5990. ASSERT_TRUE(txn->GetEntity(ReadOptions(), column_family, foo, &columns)
  5991. .IsInvalidArgument());
  5992. }
  5993. {
  5994. constexpr PinnableWideColumns* columns = nullptr;
  5995. ASSERT_TRUE(
  5996. txn->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo, columns)
  5997. .IsInvalidArgument());
  5998. }
  5999. {
  6000. ReadOptions read_options;
  6001. read_options.io_activity = Env::IOActivity::kGet;
  6002. PinnableWideColumns columns;
  6003. ASSERT_TRUE(
  6004. txn->GetEntity(read_options, db->DefaultColumnFamily(), foo, &columns)
  6005. .IsInvalidArgument());
  6006. }
  6007. {
  6008. constexpr ColumnFamilyHandle* column_family = nullptr;
  6009. std::array<Slice, num_keys> keys{{foo, bar}};
  6010. std::array<PinnableWideColumns, num_keys> results;
  6011. std::array<Status, num_keys> statuses;
  6012. constexpr bool sorted_input = false;
  6013. txn->MultiGetEntity(ReadOptions(), column_family, num_keys, keys.data(),
  6014. results.data(), statuses.data(), sorted_input);
  6015. ASSERT_TRUE(statuses[0].IsInvalidArgument());
  6016. ASSERT_TRUE(statuses[1].IsInvalidArgument());
  6017. }
  6018. {
  6019. constexpr Slice* keys = nullptr;
  6020. std::array<PinnableWideColumns, num_keys> results;
  6021. std::array<Status, num_keys> statuses;
  6022. constexpr bool sorted_input = false;
  6023. txn->MultiGetEntity(ReadOptions(), db->DefaultColumnFamily(), num_keys,
  6024. keys, results.data(), statuses.data(), sorted_input);
  6025. ASSERT_TRUE(statuses[0].IsInvalidArgument());
  6026. ASSERT_TRUE(statuses[1].IsInvalidArgument());
  6027. }
  6028. {
  6029. std::array<Slice, num_keys> keys{{foo, bar}};
  6030. constexpr PinnableWideColumns* results = nullptr;
  6031. std::array<Status, num_keys> statuses;
  6032. constexpr bool sorted_input = false;
  6033. txn->MultiGetEntity(ReadOptions(), db->DefaultColumnFamily(), num_keys,
  6034. keys.data(), results, statuses.data(), sorted_input);
  6035. ASSERT_TRUE(statuses[0].IsInvalidArgument());
  6036. ASSERT_TRUE(statuses[1].IsInvalidArgument());
  6037. }
  6038. {
  6039. ReadOptions read_options;
  6040. read_options.io_activity = Env::IOActivity::kMultiGet;
  6041. std::array<Slice, num_keys> keys{{foo, bar}};
  6042. std::array<PinnableWideColumns, num_keys> results;
  6043. std::array<Status, num_keys> statuses;
  6044. constexpr bool sorted_input = false;
  6045. txn->MultiGetEntity(read_options, db->DefaultColumnFamily(), num_keys,
  6046. keys.data(), results.data(), statuses.data(),
  6047. sorted_input);
  6048. ASSERT_TRUE(statuses[0].IsInvalidArgument());
  6049. ASSERT_TRUE(statuses[1].IsInvalidArgument());
  6050. }
  6051. {
  6052. constexpr ColumnFamilyHandle* column_family = nullptr;
  6053. PinnableWideColumns columns;
  6054. ASSERT_TRUE(
  6055. txn->GetEntityForUpdate(ReadOptions(), column_family, foo, &columns)
  6056. .IsInvalidArgument());
  6057. }
  6058. {
  6059. constexpr PinnableWideColumns* columns = nullptr;
  6060. ASSERT_TRUE(txn->GetEntityForUpdate(ReadOptions(),
  6061. db->DefaultColumnFamily(), foo, columns)
  6062. .IsInvalidArgument());
  6063. }
  6064. {
  6065. ReadOptions read_options;
  6066. read_options.io_activity = Env::IOActivity::kGet;
  6067. PinnableWideColumns columns;
  6068. ASSERT_TRUE(txn->GetEntityForUpdate(read_options, db->DefaultColumnFamily(),
  6069. foo, &columns)
  6070. .IsInvalidArgument());
  6071. }
  6072. {
  6073. txn->SetSnapshot();
  6074. ReadOptions read_options;
  6075. read_options.snapshot = txn->GetSnapshot();
  6076. PinnableWideColumns columns;
  6077. constexpr bool exclusive = true;
  6078. constexpr bool do_validate = false;
  6079. ASSERT_TRUE(txn->GetEntityForUpdate(read_options, db->DefaultColumnFamily(),
  6080. foo, &columns, exclusive, do_validate)
  6081. .IsInvalidArgument());
  6082. }
  6083. }
  6084. TEST_P(TransactionTest, PutEntityRecovery) {
  6085. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6086. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6087. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  6088. return;
  6089. }
  6090. constexpr char foo[] = "foo";
  6091. const WideColumns foo_columns{
  6092. {kDefaultWideColumnName, "bar"}, {"col1", "val1"}, {"col2", "val2"}};
  6093. constexpr char xid[] = "xid";
  6094. {
  6095. WriteOptions write_options;
  6096. write_options.sync = true;
  6097. write_options.disableWAL = false;
  6098. std::unique_ptr<Transaction> txn(db->BeginTransaction(write_options));
  6099. ASSERT_NE(txn, nullptr);
  6100. ASSERT_OK(txn->SetName(xid));
  6101. ASSERT_OK(txn->PutEntity(db->DefaultColumnFamily(), foo, foo_columns));
  6102. ASSERT_OK(txn->Prepare());
  6103. }
  6104. ASSERT_OK(ReOpenNoDelete());
  6105. {
  6106. std::unique_ptr<Transaction> txn(db->GetTransactionByName(xid));
  6107. ASSERT_NE(txn, nullptr);
  6108. ASSERT_OK(txn->Commit());
  6109. }
  6110. {
  6111. PinnableWideColumns columns;
  6112. ASSERT_OK(
  6113. db->GetEntity(ReadOptions(), db->DefaultColumnFamily(), foo, &columns));
  6114. ASSERT_EQ(columns.columns(), foo_columns);
  6115. }
  6116. }
  6117. TEST_P(TransactionTest, CoalescingIterator) {
  6118. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6119. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6120. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  6121. return;
  6122. }
  6123. ColumnFamilyOptions cf_opts;
  6124. cf_opts.enable_blob_files = true;
  6125. ColumnFamilyHandle* cfh1 = nullptr;
  6126. ASSERT_OK(db->CreateColumnFamily(cf_opts, "cf1", &cfh1));
  6127. std::unique_ptr<ColumnFamilyHandle> cfh1_guard(cfh1);
  6128. ColumnFamilyHandle* cfh2 = nullptr;
  6129. ASSERT_OK(db->CreateColumnFamily(cf_opts, "cf2", &cfh2));
  6130. std::unique_ptr<ColumnFamilyHandle> cfh2_guard(cfh2);
  6131. // Note: "cf1" keys are present only in CF1; "cf2" keys are only present in
  6132. // CF2; "cf12" keys are present in both CFs. "a" keys are present only in the
  6133. // database; "b" keys are present only in the transaction; "c" keys are
  6134. // present in both the database and the transaction. The values indicate the
  6135. // column family as well as whether the entry came from the database or the
  6136. // transaction.
  6137. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf1_a", "cf1_a_db_cf1"));
  6138. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf1_c", "cf1_c_db_cf1"));
  6139. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf2_a", "cf2_a_db_cf2"));
  6140. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf2_c", "cf2_c_db_cf2"));
  6141. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf12_a", "cf12_a_db_cf1"));
  6142. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf12_a", "cf12_a_db_cf2"));
  6143. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf12_c", "cf12_c_db_cf1"));
  6144. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf12_c", "cf12_c_db_cf2"));
  6145. ASSERT_OK(db->Flush(FlushOptions(), cfh1));
  6146. ASSERT_OK(db->Flush(FlushOptions(), cfh2));
  6147. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  6148. ASSERT_OK(txn->Put(cfh1, "cf1_b", "cf1_b_txn_cf1"));
  6149. ASSERT_OK(txn->Put(cfh1, "cf1_c", "cf1_c_txn_cf1"));
  6150. ASSERT_OK(txn->Put(cfh2, "cf2_b", "cf2_b_txn_cf2"));
  6151. ASSERT_OK(txn->Put(cfh2, "cf2_c", "cf2_c_txn_cf2"));
  6152. ASSERT_OK(txn->Put(cfh1, "cf12_b", "cf12_b_txn_cf1"));
  6153. ASSERT_OK(txn->Put(cfh2, "cf12_b", "cf12_b_txn_cf2"));
  6154. ASSERT_OK(txn->Put(cfh1, "cf12_c", "cf12_c_txn_cf1"));
  6155. ASSERT_OK(txn->Put(cfh2, "cf12_c", "cf12_c_txn_cf2"));
  6156. auto verify = [&](bool allow_unprepared_value, auto prepare_if_needed) {
  6157. ReadOptions read_options;
  6158. read_options.allow_unprepared_value = allow_unprepared_value;
  6159. std::unique_ptr<Iterator> iter(
  6160. txn->GetCoalescingIterator(read_options, {cfh1, cfh2}));
  6161. {
  6162. iter->SeekToFirst();
  6163. ASSERT_TRUE(iter->Valid());
  6164. ASSERT_OK(iter->status());
  6165. ASSERT_EQ(iter->key(), "cf12_a");
  6166. prepare_if_needed(iter.get());
  6167. ASSERT_EQ(iter->value(), "cf12_a_db_cf2");
  6168. }
  6169. {
  6170. iter->Next();
  6171. ASSERT_TRUE(iter->Valid());
  6172. ASSERT_OK(iter->status());
  6173. ASSERT_EQ(iter->key(), "cf12_b");
  6174. prepare_if_needed(iter.get());
  6175. ASSERT_EQ(iter->value(), "cf12_b_txn_cf2");
  6176. }
  6177. {
  6178. iter->Next();
  6179. ASSERT_TRUE(iter->Valid());
  6180. ASSERT_OK(iter->status());
  6181. ASSERT_EQ(iter->key(), "cf12_c");
  6182. prepare_if_needed(iter.get());
  6183. ASSERT_EQ(iter->value(), "cf12_c_txn_cf2");
  6184. }
  6185. {
  6186. iter->Next();
  6187. ASSERT_TRUE(iter->Valid());
  6188. ASSERT_OK(iter->status());
  6189. ASSERT_EQ(iter->key(), "cf1_a");
  6190. prepare_if_needed(iter.get());
  6191. ASSERT_EQ(iter->value(), "cf1_a_db_cf1");
  6192. }
  6193. {
  6194. iter->Next();
  6195. ASSERT_TRUE(iter->Valid());
  6196. ASSERT_OK(iter->status());
  6197. ASSERT_EQ(iter->key(), "cf1_b");
  6198. prepare_if_needed(iter.get());
  6199. ASSERT_EQ(iter->value(), "cf1_b_txn_cf1");
  6200. }
  6201. {
  6202. iter->Next();
  6203. ASSERT_TRUE(iter->Valid());
  6204. ASSERT_OK(iter->status());
  6205. ASSERT_EQ(iter->key(), "cf1_c");
  6206. prepare_if_needed(iter.get());
  6207. ASSERT_EQ(iter->value(), "cf1_c_txn_cf1");
  6208. }
  6209. {
  6210. iter->Next();
  6211. ASSERT_TRUE(iter->Valid());
  6212. ASSERT_OK(iter->status());
  6213. ASSERT_EQ(iter->key(), "cf2_a");
  6214. prepare_if_needed(iter.get());
  6215. ASSERT_EQ(iter->value(), "cf2_a_db_cf2");
  6216. }
  6217. {
  6218. iter->Next();
  6219. ASSERT_TRUE(iter->Valid());
  6220. ASSERT_OK(iter->status());
  6221. ASSERT_EQ(iter->key(), "cf2_b");
  6222. prepare_if_needed(iter.get());
  6223. ASSERT_EQ(iter->value(), "cf2_b_txn_cf2");
  6224. }
  6225. {
  6226. iter->Next();
  6227. ASSERT_TRUE(iter->Valid());
  6228. ASSERT_OK(iter->status());
  6229. ASSERT_EQ(iter->key(), "cf2_c");
  6230. prepare_if_needed(iter.get());
  6231. ASSERT_EQ(iter->value(), "cf2_c_txn_cf2");
  6232. }
  6233. {
  6234. iter->Next();
  6235. ASSERT_FALSE(iter->Valid());
  6236. ASSERT_OK(iter->status());
  6237. }
  6238. };
  6239. verify(/* allow_unprepared_value */ false, [](Iterator*) {});
  6240. verify(/* allow_unprepared_value */ true, [](Iterator* iter) {
  6241. ASSERT_TRUE(iter->value().empty());
  6242. ASSERT_TRUE(iter->PrepareValue());
  6243. });
  6244. }
  6245. TEST_P(TransactionTest, CoalescingIteratorSanityChecks) {
  6246. ColumnFamilyOptions cf1_opts;
  6247. ColumnFamilyHandle* cfh1 = nullptr;
  6248. ASSERT_OK(db->CreateColumnFamily(cf1_opts, "cf1", &cfh1));
  6249. std::unique_ptr<ColumnFamilyHandle> cfh1_guard(cfh1);
  6250. ColumnFamilyOptions cf2_opts;
  6251. cf2_opts.comparator = ReverseBytewiseComparator();
  6252. ColumnFamilyHandle* cfh2 = nullptr;
  6253. ASSERT_OK(db->CreateColumnFamily(cf2_opts, "cf2", &cfh2));
  6254. std::unique_ptr<ColumnFamilyHandle> cfh2_guard(cfh2);
  6255. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  6256. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6257. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6258. {
  6259. std::unique_ptr<Iterator> iter(
  6260. txn->GetCoalescingIterator(ReadOptions(), {}));
  6261. ASSERT_TRUE(iter->status().IsNotSupported());
  6262. }
  6263. {
  6264. std::unique_ptr<Iterator> iter(
  6265. txn->GetCoalescingIterator(ReadOptions(), {cfh1, cfh2}));
  6266. ASSERT_TRUE(iter->status().IsNotSupported());
  6267. }
  6268. {
  6269. ReadOptions read_options;
  6270. read_options.io_activity = Env::IOActivity::kCompaction;
  6271. std::unique_ptr<Iterator> iter(
  6272. txn->GetCoalescingIterator(read_options, {cfh1}));
  6273. ASSERT_TRUE(iter->status().IsNotSupported());
  6274. }
  6275. return;
  6276. }
  6277. {
  6278. std::unique_ptr<Iterator> iter(
  6279. txn->GetCoalescingIterator(ReadOptions(), {}));
  6280. ASSERT_TRUE(iter->status().IsInvalidArgument());
  6281. }
  6282. {
  6283. std::unique_ptr<Iterator> iter(
  6284. txn->GetCoalescingIterator(ReadOptions(), {cfh1, cfh2}));
  6285. ASSERT_TRUE(iter->status().IsInvalidArgument());
  6286. }
  6287. {
  6288. ReadOptions read_options;
  6289. read_options.io_activity = Env::IOActivity::kCompaction;
  6290. std::unique_ptr<Iterator> iter(
  6291. txn->GetCoalescingIterator(read_options, {cfh1}));
  6292. ASSERT_TRUE(iter->status().IsInvalidArgument());
  6293. }
  6294. }
  6295. TEST_P(TransactionTest, AttributeGroupIterator) {
  6296. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6297. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6298. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  6299. return;
  6300. }
  6301. ColumnFamilyOptions cf_opts;
  6302. cf_opts.enable_blob_files = true;
  6303. ColumnFamilyHandle* cfh1 = nullptr;
  6304. ASSERT_OK(db->CreateColumnFamily(cf_opts, "cf1", &cfh1));
  6305. std::unique_ptr<ColumnFamilyHandle> cfh1_guard(cfh1);
  6306. ColumnFamilyHandle* cfh2 = nullptr;
  6307. ASSERT_OK(db->CreateColumnFamily(cf_opts, "cf2", &cfh2));
  6308. std::unique_ptr<ColumnFamilyHandle> cfh2_guard(cfh2);
  6309. // Note: "cf1" keys are present only in CF1; "cf2" keys are only present in
  6310. // CF2; "cf12" keys are present in both CFs. "a" keys are present only in the
  6311. // database; "b" keys are present only in the transaction; "c" keys are
  6312. // present in both the database and the transaction. The values indicate the
  6313. // column family as well as whether the entry came from the database or the
  6314. // transaction.
  6315. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf1_a", "cf1_a_db_cf1"));
  6316. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf1_c", "cf1_c_db_cf1"));
  6317. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf2_a", "cf2_a_db_cf2"));
  6318. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf2_c", "cf2_c_db_cf2"));
  6319. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf12_a", "cf12_a_db_cf1"));
  6320. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf12_a", "cf12_a_db_cf2"));
  6321. ASSERT_OK(db->Put(WriteOptions(), cfh1, "cf12_c", "cf12_c_db_cf1"));
  6322. ASSERT_OK(db->Put(WriteOptions(), cfh2, "cf12_c", "cf12_c_db_cf2"));
  6323. ASSERT_OK(db->Flush(FlushOptions(), cfh1));
  6324. ASSERT_OK(db->Flush(FlushOptions(), cfh2));
  6325. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  6326. ASSERT_OK(txn->Put(cfh1, "cf1_b", "cf1_b_txn_cf1"));
  6327. ASSERT_OK(txn->Put(cfh1, "cf1_c", "cf1_c_txn_cf1"));
  6328. ASSERT_OK(txn->Put(cfh2, "cf2_b", "cf2_b_txn_cf2"));
  6329. ASSERT_OK(txn->Put(cfh2, "cf2_c", "cf2_c_txn_cf2"));
  6330. ASSERT_OK(txn->Put(cfh1, "cf12_b", "cf12_b_txn_cf1"));
  6331. ASSERT_OK(txn->Put(cfh2, "cf12_b", "cf12_b_txn_cf2"));
  6332. ASSERT_OK(txn->Put(cfh1, "cf12_c", "cf12_c_txn_cf1"));
  6333. ASSERT_OK(txn->Put(cfh2, "cf12_c", "cf12_c_txn_cf2"));
  6334. auto verify = [&](bool allow_unprepared_value, auto prepare_if_needed) {
  6335. ReadOptions read_options;
  6336. read_options.allow_unprepared_value = allow_unprepared_value;
  6337. std::unique_ptr<AttributeGroupIterator> iter(
  6338. txn->GetAttributeGroupIterator(read_options, {cfh1, cfh2}));
  6339. {
  6340. iter->SeekToFirst();
  6341. ASSERT_TRUE(iter->Valid());
  6342. ASSERT_OK(iter->status());
  6343. ASSERT_EQ(iter->key(), "cf12_a");
  6344. prepare_if_needed(iter.get());
  6345. WideColumns cf1_columns{{kDefaultWideColumnName, "cf12_a_db_cf1"}};
  6346. WideColumns cf2_columns{{kDefaultWideColumnName, "cf12_a_db_cf2"}};
  6347. IteratorAttributeGroups expected{
  6348. IteratorAttributeGroup{cfh1, &cf1_columns},
  6349. IteratorAttributeGroup{cfh2, &cf2_columns}};
  6350. ASSERT_EQ(iter->attribute_groups(), expected);
  6351. }
  6352. {
  6353. iter->Next();
  6354. ASSERT_TRUE(iter->Valid());
  6355. ASSERT_OK(iter->status());
  6356. ASSERT_EQ(iter->key(), "cf12_b");
  6357. prepare_if_needed(iter.get());
  6358. WideColumns cf1_columns{{kDefaultWideColumnName, "cf12_b_txn_cf1"}};
  6359. WideColumns cf2_columns{{kDefaultWideColumnName, "cf12_b_txn_cf2"}};
  6360. IteratorAttributeGroups expected{
  6361. IteratorAttributeGroup{cfh1, &cf1_columns},
  6362. IteratorAttributeGroup{cfh2, &cf2_columns}};
  6363. ASSERT_EQ(iter->attribute_groups(), expected);
  6364. }
  6365. {
  6366. iter->Next();
  6367. ASSERT_TRUE(iter->Valid());
  6368. ASSERT_OK(iter->status());
  6369. ASSERT_EQ(iter->key(), "cf12_c");
  6370. prepare_if_needed(iter.get());
  6371. WideColumns cf1_columns{{kDefaultWideColumnName, "cf12_c_txn_cf1"}};
  6372. WideColumns cf2_columns{{kDefaultWideColumnName, "cf12_c_txn_cf2"}};
  6373. IteratorAttributeGroups expected{
  6374. IteratorAttributeGroup{cfh1, &cf1_columns},
  6375. IteratorAttributeGroup{cfh2, &cf2_columns}};
  6376. ASSERT_EQ(iter->attribute_groups(), expected);
  6377. }
  6378. {
  6379. iter->Next();
  6380. ASSERT_TRUE(iter->Valid());
  6381. ASSERT_OK(iter->status());
  6382. ASSERT_EQ(iter->key(), "cf1_a");
  6383. prepare_if_needed(iter.get());
  6384. WideColumns cf1_columns{{kDefaultWideColumnName, "cf1_a_db_cf1"}};
  6385. IteratorAttributeGroups expected{
  6386. IteratorAttributeGroup{cfh1, &cf1_columns}};
  6387. ASSERT_EQ(iter->attribute_groups(), expected);
  6388. }
  6389. {
  6390. iter->Next();
  6391. ASSERT_TRUE(iter->Valid());
  6392. ASSERT_OK(iter->status());
  6393. ASSERT_EQ(iter->key(), "cf1_b");
  6394. prepare_if_needed(iter.get());
  6395. WideColumns cf1_columns{{kDefaultWideColumnName, "cf1_b_txn_cf1"}};
  6396. IteratorAttributeGroups expected{
  6397. IteratorAttributeGroup{cfh1, &cf1_columns}};
  6398. ASSERT_EQ(iter->attribute_groups(), expected);
  6399. }
  6400. {
  6401. iter->Next();
  6402. ASSERT_TRUE(iter->Valid());
  6403. ASSERT_OK(iter->status());
  6404. ASSERT_EQ(iter->key(), "cf1_c");
  6405. prepare_if_needed(iter.get());
  6406. WideColumns cf1_columns{{kDefaultWideColumnName, "cf1_c_txn_cf1"}};
  6407. IteratorAttributeGroups expected{
  6408. IteratorAttributeGroup{cfh1, &cf1_columns}};
  6409. ASSERT_EQ(iter->attribute_groups(), expected);
  6410. }
  6411. {
  6412. iter->Next();
  6413. ASSERT_TRUE(iter->Valid());
  6414. ASSERT_OK(iter->status());
  6415. ASSERT_EQ(iter->key(), "cf2_a");
  6416. prepare_if_needed(iter.get());
  6417. WideColumns cf2_columns{{kDefaultWideColumnName, "cf2_a_db_cf2"}};
  6418. IteratorAttributeGroups expected{
  6419. IteratorAttributeGroup{cfh2, &cf2_columns}};
  6420. ASSERT_EQ(iter->attribute_groups(), expected);
  6421. }
  6422. {
  6423. iter->Next();
  6424. ASSERT_TRUE(iter->Valid());
  6425. ASSERT_OK(iter->status());
  6426. ASSERT_EQ(iter->key(), "cf2_b");
  6427. prepare_if_needed(iter.get());
  6428. WideColumns cf2_columns{{kDefaultWideColumnName, "cf2_b_txn_cf2"}};
  6429. IteratorAttributeGroups expected{
  6430. IteratorAttributeGroup{cfh2, &cf2_columns}};
  6431. ASSERT_EQ(iter->attribute_groups(), expected);
  6432. }
  6433. {
  6434. iter->Next();
  6435. ASSERT_TRUE(iter->Valid());
  6436. ASSERT_OK(iter->status());
  6437. ASSERT_EQ(iter->key(), "cf2_c");
  6438. prepare_if_needed(iter.get());
  6439. WideColumns cf2_columns{{kDefaultWideColumnName, "cf2_c_txn_cf2"}};
  6440. IteratorAttributeGroups expected{
  6441. IteratorAttributeGroup{cfh2, &cf2_columns}};
  6442. ASSERT_EQ(iter->attribute_groups(), expected);
  6443. }
  6444. {
  6445. iter->Next();
  6446. ASSERT_FALSE(iter->Valid());
  6447. ASSERT_OK(iter->status());
  6448. }
  6449. };
  6450. verify(/* allow_unprepared_value */ false, [](AttributeGroupIterator*) {});
  6451. verify(/* allow_unprepared_value */ true, [](AttributeGroupIterator* iter) {
  6452. ASSERT_TRUE(iter->attribute_groups().empty());
  6453. ASSERT_TRUE(iter->PrepareValue());
  6454. });
  6455. }
  6456. TEST_P(TransactionTest, AttributeGroupIteratorSanityChecks) {
  6457. ColumnFamilyOptions cf1_opts;
  6458. ColumnFamilyHandle* cfh1 = nullptr;
  6459. ASSERT_OK(db->CreateColumnFamily(cf1_opts, "cf1", &cfh1));
  6460. std::unique_ptr<ColumnFamilyHandle> cfh1_guard(cfh1);
  6461. ColumnFamilyOptions cf2_opts;
  6462. cf2_opts.comparator = ReverseBytewiseComparator();
  6463. ColumnFamilyHandle* cfh2 = nullptr;
  6464. ASSERT_OK(db->CreateColumnFamily(cf2_opts, "cf2", &cfh2));
  6465. std::unique_ptr<ColumnFamilyHandle> cfh2_guard(cfh2);
  6466. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  6467. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6468. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6469. {
  6470. std::unique_ptr<AttributeGroupIterator> iter(
  6471. txn->GetAttributeGroupIterator(ReadOptions(), {}));
  6472. ASSERT_TRUE(iter->status().IsNotSupported());
  6473. }
  6474. {
  6475. std::unique_ptr<AttributeGroupIterator> iter(
  6476. txn->GetAttributeGroupIterator(ReadOptions(), {cfh1, cfh2}));
  6477. ASSERT_TRUE(iter->status().IsNotSupported());
  6478. }
  6479. {
  6480. ReadOptions read_options;
  6481. read_options.io_activity = Env::IOActivity::kCompaction;
  6482. std::unique_ptr<AttributeGroupIterator> iter(
  6483. txn->GetAttributeGroupIterator(read_options, {cfh1}));
  6484. ASSERT_TRUE(iter->status().IsNotSupported());
  6485. }
  6486. return;
  6487. }
  6488. {
  6489. std::unique_ptr<AttributeGroupIterator> iter(
  6490. txn->GetAttributeGroupIterator(ReadOptions(), {}));
  6491. ASSERT_TRUE(iter->status().IsInvalidArgument());
  6492. }
  6493. {
  6494. std::unique_ptr<AttributeGroupIterator> iter(
  6495. txn->GetAttributeGroupIterator(ReadOptions(), {cfh1, cfh2}));
  6496. ASSERT_TRUE(iter->status().IsInvalidArgument());
  6497. }
  6498. {
  6499. ReadOptions read_options;
  6500. read_options.io_activity = Env::IOActivity::kCompaction;
  6501. std::unique_ptr<AttributeGroupIterator> iter(
  6502. txn->GetAttributeGroupIterator(read_options, {cfh1}));
  6503. ASSERT_TRUE(iter->status().IsInvalidArgument());
  6504. }
  6505. }
  6506. TEST_P(TransactionTest, SecondaryIndexPutDelete) {
  6507. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6508. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6509. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  6510. return;
  6511. }
  6512. txn_db_options.secondary_indices.emplace_back(
  6513. std::make_shared<SimpleSecondaryIndex>(
  6514. kDefaultWideColumnName.ToString()));
  6515. ASSERT_OK(ReOpen());
  6516. ColumnFamilyOptions cf1_opts;
  6517. ColumnFamilyHandle* cfh1 = nullptr;
  6518. ASSERT_OK(db->CreateColumnFamily(cf1_opts, "cf1", &cfh1));
  6519. std::unique_ptr<ColumnFamilyHandle> cfh1_guard(cfh1);
  6520. ColumnFamilyOptions cf2_opts;
  6521. ColumnFamilyHandle* cfh2 = nullptr;
  6522. ASSERT_OK(db->CreateColumnFamily(cf2_opts, "cf2", &cfh2));
  6523. std::unique_ptr<ColumnFamilyHandle> cfh2_guard(cfh2);
  6524. auto& index = txn_db_options.secondary_indices.back();
  6525. index->SetPrimaryColumnFamily(cfh1);
  6526. index->SetSecondaryColumnFamily(cfh2);
  6527. {
  6528. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  6529. // Default CF => OK but not indexed
  6530. ASSERT_OK(txn->Put(db->DefaultColumnFamily(), "key0", "foo"));
  6531. // CF1 but no default column => OK but not indexed
  6532. ASSERT_OK(txn->PutEntity(cfh1, "key1", {{"hello", "world"}}));
  6533. // CF1, "bar" in the default column => OK and indexed
  6534. ASSERT_OK(txn->Put(cfh1, "key2", "bar"));
  6535. // CF1, "baz" in the default column => OK and indexed
  6536. ASSERT_OK(txn->Put(cfh1, "key3", "baz"));
  6537. ASSERT_OK(txn->Commit());
  6538. }
  6539. // Expected keys: "key0" in the default CF; "key1", "key2", "key3" in CF1;
  6540. // secondary index entries for "key2" and "key3" in CF2
  6541. {
  6542. std::unique_ptr<Iterator> it(
  6543. db->NewIterator(ReadOptions(), db->DefaultColumnFamily()));
  6544. it->SeekToFirst();
  6545. ASSERT_TRUE(it->Valid());
  6546. ASSERT_EQ(it->key(), "key0");
  6547. ASSERT_EQ(it->value(), "foo");
  6548. it->Next();
  6549. ASSERT_FALSE(it->Valid());
  6550. ASSERT_OK(it->status());
  6551. }
  6552. {
  6553. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh1));
  6554. it->SeekToFirst();
  6555. ASSERT_TRUE(it->Valid());
  6556. ASSERT_EQ(it->key(), "key1");
  6557. WideColumns expected1{{"hello", "world"}};
  6558. ASSERT_EQ(it->columns(), expected1);
  6559. it->Next();
  6560. ASSERT_TRUE(it->Valid());
  6561. ASSERT_EQ(it->key(), "key2");
  6562. ASSERT_EQ(it->value(), "bar");
  6563. it->Next();
  6564. ASSERT_TRUE(it->Valid());
  6565. ASSERT_EQ(it->key(), "key3");
  6566. ASSERT_EQ(it->value(), "baz");
  6567. it->Next();
  6568. ASSERT_FALSE(it->Valid());
  6569. ASSERT_OK(it->status());
  6570. }
  6571. {
  6572. // Read the raw secondary index entries from CF2
  6573. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh2));
  6574. it->SeekToFirst();
  6575. ASSERT_TRUE(it->Valid());
  6576. ASSERT_EQ(it->key(), "\3barkey2");
  6577. ASSERT_TRUE(it->value().empty());
  6578. it->Next();
  6579. ASSERT_TRUE(it->Valid());
  6580. ASSERT_EQ(it->key(), "\3bazkey3");
  6581. ASSERT_TRUE(it->value().empty());
  6582. it->Next();
  6583. ASSERT_FALSE(it->Valid());
  6584. ASSERT_OK(it->status());
  6585. }
  6586. {
  6587. // Query the secondary index
  6588. std::unique_ptr<Iterator> underlying_it(
  6589. db->NewIterator(ReadOptions(), cfh2));
  6590. auto it = std::make_unique<SecondaryIndexIterator>(
  6591. index.get(), std::move(underlying_it));
  6592. it->Seek("bar");
  6593. ASSERT_TRUE(it->Valid());
  6594. ASSERT_OK(it->status());
  6595. ASSERT_EQ(it->key(), "key2");
  6596. ASSERT_TRUE(it->value().empty());
  6597. it->Next();
  6598. ASSERT_FALSE(it->Valid());
  6599. ASSERT_OK(it->status());
  6600. it->Seek("baz");
  6601. ASSERT_TRUE(it->Valid());
  6602. ASSERT_OK(it->status());
  6603. ASSERT_EQ(it->key(), "key3");
  6604. ASSERT_TRUE(it->value().empty());
  6605. it->Next();
  6606. ASSERT_FALSE(it->Valid());
  6607. ASSERT_OK(it->status());
  6608. }
  6609. // Make some updates to the key-values indexed above through the database
  6610. // interface (i.e. using implicit transactions)
  6611. // Add a default column to "key1" which previously had none
  6612. ASSERT_OK(
  6613. db->PutEntity(WriteOptions(), cfh1, "key1",
  6614. {{"hello", "world"}, {kDefaultWideColumnName, "quux"}}));
  6615. // Change the value of the default column in "key2"
  6616. ASSERT_OK(db->Put(WriteOptions(), cfh1, "key2", "quux"));
  6617. // Remove the default column from "key3"
  6618. ASSERT_OK(db->PutEntity(WriteOptions(), cfh1, "key3", {{"1", "2"}}));
  6619. // Expected keys: "key0" in the default CF; "key1", "key2", "key3" in CF1;
  6620. // secondary index entries for "key1" and "key2" in CF2
  6621. {
  6622. std::unique_ptr<Iterator> it(
  6623. db->NewIterator(ReadOptions(), db->DefaultColumnFamily()));
  6624. it->SeekToFirst();
  6625. ASSERT_TRUE(it->Valid());
  6626. ASSERT_EQ(it->key(), "key0");
  6627. ASSERT_EQ(it->value(), "foo");
  6628. it->Next();
  6629. ASSERT_FALSE(it->Valid());
  6630. ASSERT_OK(it->status());
  6631. }
  6632. {
  6633. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh1));
  6634. it->SeekToFirst();
  6635. ASSERT_TRUE(it->Valid());
  6636. ASSERT_EQ(it->key(), "key1");
  6637. WideColumns expected1{{kDefaultWideColumnName, "quux"}, {"hello", "world"}};
  6638. ASSERT_EQ(it->columns(), expected1);
  6639. it->Next();
  6640. ASSERT_TRUE(it->Valid());
  6641. ASSERT_EQ(it->key(), "key2");
  6642. ASSERT_EQ(it->value(), "quux");
  6643. it->Next();
  6644. ASSERT_TRUE(it->Valid());
  6645. ASSERT_EQ(it->key(), "key3");
  6646. WideColumns expected3{{"1", "2"}};
  6647. ASSERT_EQ(it->columns(), expected3);
  6648. it->Next();
  6649. ASSERT_FALSE(it->Valid());
  6650. ASSERT_OK(it->status());
  6651. }
  6652. {
  6653. // Read the raw secondary index entries from CF2
  6654. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh2));
  6655. it->SeekToFirst();
  6656. ASSERT_TRUE(it->Valid());
  6657. ASSERT_EQ(it->key(), "\4quuxkey1");
  6658. ASSERT_TRUE(it->value().empty());
  6659. it->Next();
  6660. ASSERT_TRUE(it->Valid());
  6661. ASSERT_EQ(it->key(), "\4quuxkey2");
  6662. ASSERT_TRUE(it->value().empty());
  6663. it->Next();
  6664. ASSERT_FALSE(it->Valid());
  6665. ASSERT_OK(it->status());
  6666. }
  6667. {
  6668. // Query the secondary index
  6669. std::unique_ptr<Iterator> underlying_it(
  6670. db->NewIterator(ReadOptions(), cfh2));
  6671. auto it = std::make_unique<SecondaryIndexIterator>(
  6672. index.get(), std::move(underlying_it));
  6673. it->Seek("quux");
  6674. ASSERT_TRUE(it->Valid());
  6675. ASSERT_OK(it->status());
  6676. ASSERT_EQ(it->key(), "key1");
  6677. ASSERT_TRUE(it->value().empty());
  6678. it->Next();
  6679. ASSERT_TRUE(it->Valid());
  6680. ASSERT_OK(it->status());
  6681. ASSERT_EQ(it->key(), "key2");
  6682. ASSERT_TRUE(it->value().empty());
  6683. it->Next();
  6684. ASSERT_FALSE(it->Valid());
  6685. ASSERT_OK(it->status());
  6686. }
  6687. // Delete/SingleDelete "key1" and "key3" via an explicit transaction and
  6688. // "key2" and a non-existing "key4" via the DB interface (i.e. an implicit
  6689. // transaction)
  6690. {
  6691. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  6692. ASSERT_OK(txn->Delete(cfh1, "key1"));
  6693. ASSERT_OK(txn->SingleDelete(cfh1, "key3"));
  6694. ASSERT_OK(txn->Commit());
  6695. }
  6696. ASSERT_OK(db->SingleDelete(WriteOptions(), cfh1, "key2"));
  6697. ASSERT_OK(db->Delete(WriteOptions(), cfh1, "key4"));
  6698. // cfh1 and cfh2 are expected to be empty
  6699. {
  6700. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh1));
  6701. it->SeekToFirst();
  6702. ASSERT_FALSE(it->Valid());
  6703. ASSERT_OK(it->status());
  6704. }
  6705. {
  6706. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh2));
  6707. it->SeekToFirst();
  6708. ASSERT_FALSE(it->Valid());
  6709. ASSERT_OK(it->status());
  6710. }
  6711. }
  6712. TEST_P(TransactionTest, SecondaryIndexPutEntity) {
  6713. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6714. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6715. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  6716. return;
  6717. }
  6718. // A kind of silly secondary index that indexes the column "foo".
  6719. class FooSecondaryIndex : public SecondaryIndex {
  6720. public:
  6721. void SetPrimaryColumnFamily(ColumnFamilyHandle* cfh) override {
  6722. primary_cfh_ = cfh;
  6723. }
  6724. void SetSecondaryColumnFamily(ColumnFamilyHandle* cfh) override {
  6725. secondary_cfh_ = cfh;
  6726. }
  6727. ColumnFamilyHandle* GetPrimaryColumnFamily() const override {
  6728. return primary_cfh_;
  6729. }
  6730. ColumnFamilyHandle* GetSecondaryColumnFamily() const override {
  6731. return secondary_cfh_;
  6732. }
  6733. Slice GetPrimaryColumnName() const override { return "foo"; }
  6734. Status UpdatePrimaryColumnValue(
  6735. const Slice& /* primary_key */, const Slice& primary_column_value,
  6736. std::optional<std::variant<Slice, std::string>>* updated_column_value)
  6737. const override {
  6738. assert(updated_column_value);
  6739. if (primary_column_value == "bar") {
  6740. return Status::InvalidArgument();
  6741. }
  6742. if (primary_column_value == "baz") {
  6743. updated_column_value->emplace(Slice("quux"));
  6744. }
  6745. return Status::OK();
  6746. }
  6747. Status GetSecondaryKeyPrefix(
  6748. const Slice& /* primary_key */, const Slice& primary_column_value,
  6749. std::variant<Slice, std::string>* secondary_key_prefix) const override {
  6750. assert(secondary_key_prefix);
  6751. if (primary_column_value.empty()) {
  6752. return Status::NotFound();
  6753. }
  6754. *secondary_key_prefix = Slice(
  6755. primary_column_value.data() + primary_column_value.size() - 1, 1);
  6756. return Status::OK();
  6757. }
  6758. Status FinalizeSecondaryKeyPrefix(
  6759. std::variant<Slice, std::string>* secondary_key_prefix) const override {
  6760. if (SecondaryIndexHelper::AsSlice(*secondary_key_prefix) == "!") {
  6761. return Status::Corruption();
  6762. }
  6763. return Status::OK();
  6764. }
  6765. Status GetSecondaryValue(const Slice& /* primary_key */,
  6766. const Slice& primary_column_value,
  6767. const Slice& previous_column_value,
  6768. std::optional<std::variant<Slice, std::string>>*
  6769. secondary_value) const override {
  6770. if (primary_column_value == "corge") {
  6771. return Status::NotSupported();
  6772. }
  6773. std::string value = previous_column_value.ToString();
  6774. std::reverse(value.begin(), value.end());
  6775. *secondary_value = value;
  6776. return Status::OK();
  6777. }
  6778. private:
  6779. ColumnFamilyHandle* primary_cfh_{};
  6780. ColumnFamilyHandle* secondary_cfh_{};
  6781. };
  6782. txn_db_options.secondary_indices.emplace_back(
  6783. std::make_shared<FooSecondaryIndex>());
  6784. ASSERT_OK(ReOpen());
  6785. ColumnFamilyOptions cf1_opts;
  6786. ColumnFamilyHandle* cfh1 = nullptr;
  6787. ASSERT_OK(db->CreateColumnFamily(cf1_opts, "cf1", &cfh1));
  6788. std::unique_ptr<ColumnFamilyHandle> cfh1_guard(cfh1);
  6789. ColumnFamilyOptions cf2_opts;
  6790. ColumnFamilyHandle* cfh2 = nullptr;
  6791. ASSERT_OK(db->CreateColumnFamily(cf2_opts, "cf2", &cfh2));
  6792. std::unique_ptr<ColumnFamilyHandle> cfh2_guard(cfh2);
  6793. auto& index = txn_db_options.secondary_indices.back();
  6794. index->SetPrimaryColumnFamily(cfh1);
  6795. index->SetSecondaryColumnFamily(cfh2);
  6796. {
  6797. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  6798. // Default CF => OK but not indexed
  6799. ASSERT_OK(txn->PutEntity(db->DefaultColumnFamily(), "key0",
  6800. {{"a", "b"}, {"foo", "c"}}));
  6801. // CF1 but no "foo" column => OK but not indexed
  6802. ASSERT_OK(txn->PutEntity(cfh1, "key1", {{"hello", "world"}}));
  6803. // CF1, "bar" in the "foo" column => UpdatePrimaryColumnValue errors out
  6804. ASSERT_TRUE(
  6805. txn->PutEntity(cfh1, "key2", {{"foo", "bar"}}).IsInvalidArgument());
  6806. // CF1, "baz" in the "foo" column => updated to "quux", OK and indexed
  6807. ASSERT_OK(txn->PutEntity(cfh1, "key3", {{"foo", "baz"}, {"x", "y"}}));
  6808. // CF1, "quux" in the "foo" column => OK and indexed
  6809. ASSERT_OK(txn->PutEntity(cfh1, "key4", {{"foo", "quux"}, {"1", "2"}}));
  6810. // CF1, empty value in the "foo" column => GetSecondaryKeyPrefix errors out
  6811. ASSERT_TRUE(txn->PutEntity(cfh1, "key5", {{"foo", ""}}).IsNotFound());
  6812. // CF1, "!!!" in the "foo" column => FinalizeSecondaryKeyPrefix errors out
  6813. ASSERT_TRUE(txn->PutEntity(cfh1, "key6", {{"foo", "!!!"}}).IsCorruption());
  6814. // CF1, "corge" in the "foo" column => GetSecondaryValue errors out
  6815. ASSERT_TRUE(
  6816. txn->PutEntity(cfh1, "key7", {{"foo", "corge"}}).IsNotSupported());
  6817. ASSERT_OK(txn->Commit());
  6818. }
  6819. // Expected keys: "key0" in the default CF; "key1", "key3", "key4" in CF1;
  6820. // secondary index entries for "key3" and "key4" in CF2
  6821. {
  6822. std::unique_ptr<Iterator> it(
  6823. db->NewIterator(ReadOptions(), db->DefaultColumnFamily()));
  6824. it->SeekToFirst();
  6825. ASSERT_TRUE(it->Valid());
  6826. ASSERT_EQ(it->key(), "key0");
  6827. WideColumns expected0{{"a", "b"}, {"foo", "c"}};
  6828. ASSERT_EQ(it->columns(), expected0);
  6829. it->Next();
  6830. ASSERT_FALSE(it->Valid());
  6831. ASSERT_OK(it->status());
  6832. }
  6833. {
  6834. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh1));
  6835. it->SeekToFirst();
  6836. ASSERT_TRUE(it->Valid());
  6837. ASSERT_EQ(it->key(), "key1");
  6838. WideColumns expected1{{"hello", "world"}};
  6839. ASSERT_EQ(it->columns(), expected1);
  6840. it->Next();
  6841. ASSERT_TRUE(it->Valid());
  6842. ASSERT_EQ(it->key(), "key3");
  6843. WideColumns expected3{{"foo", "quux"}, {"x", "y"}};
  6844. ASSERT_EQ(it->columns(), expected3);
  6845. it->Next();
  6846. ASSERT_TRUE(it->Valid());
  6847. ASSERT_EQ(it->key(), "key4");
  6848. WideColumns expected4{{"1", "2"}, {"foo", "quux"}};
  6849. ASSERT_EQ(it->columns(), expected4);
  6850. it->Next();
  6851. ASSERT_FALSE(it->Valid());
  6852. ASSERT_OK(it->status());
  6853. }
  6854. {
  6855. // Read the raw secondary index entries from CF2
  6856. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh2));
  6857. it->SeekToFirst();
  6858. ASSERT_TRUE(it->Valid());
  6859. ASSERT_EQ(it->key(), "xkey3");
  6860. ASSERT_EQ(it->value(), "zab");
  6861. it->Next();
  6862. ASSERT_TRUE(it->Valid());
  6863. ASSERT_EQ(it->key(), "xkey4");
  6864. ASSERT_EQ(it->value(), "xuuq");
  6865. it->Next();
  6866. ASSERT_FALSE(it->Valid());
  6867. ASSERT_OK(it->status());
  6868. }
  6869. {
  6870. // Query the secondary index
  6871. std::unique_ptr<Iterator> underlying_it(
  6872. db->NewIterator(ReadOptions(), cfh2));
  6873. auto it = std::make_unique<SecondaryIndexIterator>(
  6874. index.get(), std::move(underlying_it));
  6875. it->Seek("x");
  6876. ASSERT_TRUE(it->Valid());
  6877. ASSERT_OK(it->status());
  6878. ASSERT_EQ(it->key(), "key3");
  6879. ASSERT_EQ(it->value(), "zab");
  6880. it->Next();
  6881. ASSERT_TRUE(it->Valid());
  6882. ASSERT_OK(it->status());
  6883. ASSERT_EQ(it->key(), "key4");
  6884. ASSERT_EQ(it->value(), "xuuq");
  6885. it->Prev();
  6886. ASSERT_TRUE(it->Valid());
  6887. ASSERT_OK(it->status());
  6888. ASSERT_EQ(it->key(), "key3");
  6889. ASSERT_EQ(it->value(), "zab");
  6890. it->Next();
  6891. ASSERT_TRUE(it->Valid());
  6892. ASSERT_OK(it->status());
  6893. ASSERT_EQ(it->key(), "key4");
  6894. ASSERT_EQ(it->value(), "xuuq");
  6895. it->Next();
  6896. ASSERT_FALSE(it->Valid());
  6897. ASSERT_OK(it->status());
  6898. it->Seek("y");
  6899. ASSERT_FALSE(it->Valid());
  6900. ASSERT_OK(it->status());
  6901. }
  6902. // Make some updates to the key-values indexed above through the database
  6903. // interface (i.e. using implicit transactions)
  6904. // Add a "foo" column to "key1" which previously had none
  6905. ASSERT_OK(db->PutEntity(WriteOptions(), cfh1, "key1",
  6906. {{"hello", "world"}, {"foo", "grault"}}));
  6907. // Change the value of the "foo" column in "key3"
  6908. ASSERT_OK(db->PutEntity(WriteOptions(), cfh1, "key3",
  6909. {{"foo", "garply"}, {"x", "y"}}));
  6910. // Remove the "foo" column from "key4"
  6911. ASSERT_OK(db->PutEntity(WriteOptions(), cfh1, "key4", {{"1", "2"}}));
  6912. // Expected keys: "key0" in the default CF; "key1", "key3", "key4" in CF1;
  6913. // secondary index entries for "key1" and "key3" in CF2
  6914. {
  6915. std::unique_ptr<Iterator> it(
  6916. db->NewIterator(ReadOptions(), db->DefaultColumnFamily()));
  6917. it->SeekToFirst();
  6918. ASSERT_TRUE(it->Valid());
  6919. ASSERT_EQ(it->key(), "key0");
  6920. WideColumns expected0{{"a", "b"}, {"foo", "c"}};
  6921. ASSERT_EQ(it->columns(), expected0);
  6922. it->Next();
  6923. ASSERT_FALSE(it->Valid());
  6924. ASSERT_OK(it->status());
  6925. }
  6926. {
  6927. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh1));
  6928. it->SeekToFirst();
  6929. ASSERT_TRUE(it->Valid());
  6930. ASSERT_EQ(it->key(), "key1");
  6931. WideColumns expected1{{"foo", "grault"}, {"hello", "world"}};
  6932. ASSERT_EQ(it->columns(), expected1);
  6933. it->Next();
  6934. ASSERT_TRUE(it->Valid());
  6935. ASSERT_EQ(it->key(), "key3");
  6936. WideColumns expected3{{"foo", "garply"}, {"x", "y"}};
  6937. ASSERT_EQ(it->columns(), expected3);
  6938. it->Next();
  6939. ASSERT_TRUE(it->Valid());
  6940. ASSERT_EQ(it->key(), "key4");
  6941. WideColumns expected4{{"1", "2"}};
  6942. ASSERT_EQ(it->columns(), expected4);
  6943. it->Next();
  6944. ASSERT_FALSE(it->Valid());
  6945. ASSERT_OK(it->status());
  6946. }
  6947. {
  6948. // Read the raw secondary index entries from CF2
  6949. std::unique_ptr<Iterator> it(db->NewIterator(ReadOptions(), cfh2));
  6950. it->SeekToFirst();
  6951. ASSERT_TRUE(it->Valid());
  6952. ASSERT_EQ(it->key(), "tkey1");
  6953. ASSERT_EQ(it->value(), "tluarg");
  6954. it->Next();
  6955. ASSERT_TRUE(it->Valid());
  6956. ASSERT_EQ(it->key(), "ykey3");
  6957. ASSERT_EQ(it->value(), "ylprag");
  6958. it->Next();
  6959. ASSERT_FALSE(it->Valid());
  6960. ASSERT_OK(it->status());
  6961. }
  6962. {
  6963. // Query the secondary index
  6964. std::unique_ptr<Iterator> underlying_it(
  6965. db->NewIterator(ReadOptions(), cfh2));
  6966. auto it = std::make_unique<SecondaryIndexIterator>(
  6967. index.get(), std::move(underlying_it));
  6968. it->Seek("t");
  6969. ASSERT_TRUE(it->Valid());
  6970. ASSERT_OK(it->status());
  6971. ASSERT_EQ(it->key(), "key1");
  6972. ASSERT_EQ(it->value(), "tluarg");
  6973. it->Next();
  6974. ASSERT_FALSE(it->Valid());
  6975. ASSERT_OK(it->status());
  6976. it->Seek("y");
  6977. ASSERT_TRUE(it->Valid());
  6978. ASSERT_OK(it->status());
  6979. ASSERT_EQ(it->key(), "key3");
  6980. ASSERT_EQ(it->value(), "ylprag");
  6981. it->Next();
  6982. ASSERT_FALSE(it->Valid());
  6983. ASSERT_OK(it->status());
  6984. }
  6985. }
  6986. TEST_P(TransactionTest, SecondaryIndexOnKey) {
  6987. const TxnDBWritePolicy write_policy = std::get<2>(GetParam());
  6988. if (write_policy != TxnDBWritePolicy::WRITE_COMMITTED) {
  6989. ROCKSDB_GTEST_BYPASS("Test only WriteCommitted for now");
  6990. return;
  6991. }
  6992. // A secondary index that removes the first three characters of the primary
  6993. // key and indexes the rest.
  6994. class KeySecondaryIndex : public SecondaryIndex {
  6995. public:
  6996. void SetPrimaryColumnFamily(ColumnFamilyHandle* cfh) override {
  6997. primary_cfh_ = cfh;
  6998. }
  6999. void SetSecondaryColumnFamily(ColumnFamilyHandle* cfh) override {
  7000. secondary_cfh_ = cfh;
  7001. }
  7002. ColumnFamilyHandle* GetPrimaryColumnFamily() const override {
  7003. return primary_cfh_;
  7004. }
  7005. ColumnFamilyHandle* GetSecondaryColumnFamily() const override {
  7006. return secondary_cfh_;
  7007. }
  7008. Slice GetPrimaryColumnName() const override {
  7009. return kDefaultWideColumnName;
  7010. }
  7011. Status UpdatePrimaryColumnValue(
  7012. const Slice& /* primary_key */, const Slice& /* primary_column_value */,
  7013. std::optional<
  7014. std::variant<Slice, std::string>>* /* updated_column_value */)
  7015. const override {
  7016. return Status::OK();
  7017. }
  7018. Status GetSecondaryKeyPrefix(
  7019. const Slice& primary_key, const Slice& /* primary_column_value */,
  7020. std::variant<Slice, std::string>* secondary_key_prefix) const override {
  7021. assert(secondary_key_prefix);
  7022. constexpr size_t prefix_len = 3;
  7023. if (primary_key.size() < prefix_len) {
  7024. return Status::InvalidArgument();
  7025. }
  7026. Slice transformed_key = primary_key;
  7027. transformed_key.remove_prefix(prefix_len);
  7028. *secondary_key_prefix = transformed_key;
  7029. return Status::OK();
  7030. }
  7031. Status FinalizeSecondaryKeyPrefix(
  7032. std::variant<Slice, std::string>* /* secondary_key_prefix */)
  7033. const override {
  7034. return Status::OK();
  7035. }
  7036. Status GetSecondaryValue(const Slice& primary_key,
  7037. const Slice& /* primary_column_value */,
  7038. const Slice& /* previous_column_value */,
  7039. std::optional<std::variant<Slice, std::string>>*
  7040. secondary_value) const override {
  7041. assert(secondary_value);
  7042. std::string index_value = primary_key.ToString();
  7043. std::reverse(index_value.begin(), index_value.end());
  7044. *secondary_value = std::move(index_value);
  7045. return Status::OK();
  7046. }
  7047. private:
  7048. ColumnFamilyHandle* primary_cfh_{};
  7049. ColumnFamilyHandle* secondary_cfh_{};
  7050. };
  7051. txn_db_options.secondary_indices.emplace_back(
  7052. std::make_shared<KeySecondaryIndex>());
  7053. ASSERT_OK(ReOpen());
  7054. ColumnFamilyOptions cf1_opts;
  7055. ColumnFamilyHandle* cfh1 = nullptr;
  7056. ASSERT_OK(db->CreateColumnFamily(cf1_opts, "cf1", &cfh1));
  7057. std::unique_ptr<ColumnFamilyHandle> cfh1_guard(cfh1);
  7058. ColumnFamilyOptions cf2_opts;
  7059. ColumnFamilyHandle* cfh2 = nullptr;
  7060. ASSERT_OK(db->CreateColumnFamily(cf2_opts, "cf2", &cfh2));
  7061. std::unique_ptr<ColumnFamilyHandle> cfh2_guard(cfh2);
  7062. auto& index = txn_db_options.secondary_indices.back();
  7063. index->SetPrimaryColumnFamily(cfh1);
  7064. index->SetSecondaryColumnFamily(cfh2);
  7065. {
  7066. std::unique_ptr<Transaction> txn(db->BeginTransaction(WriteOptions()));
  7067. ASSERT_OK(txn->Put(cfh1, "123foo", "a"));
  7068. ASSERT_OK(txn->Put(cfh1, "123bar", "b"));
  7069. ASSERT_OK(txn->Put(cfh1, "123baz", "c"));
  7070. ASSERT_OK(txn->Put(cfh1, "456foo", "d"));
  7071. ASSERT_OK(txn->Put(cfh1, "456bar", "e"));
  7072. ASSERT_OK(txn->Put(cfh1, "456baz", "f"));
  7073. ASSERT_OK(txn->Put(cfh1, "789foo", "g"));
  7074. ASSERT_OK(txn->Put(cfh1, "789bar", "h"));
  7075. ASSERT_OK(txn->Put(cfh1, "789baz", "i"));
  7076. ASSERT_OK(txn->Commit());
  7077. }
  7078. {
  7079. std::unique_ptr<Iterator> underlying_it(
  7080. db->NewIterator(ReadOptions(), cfh2));
  7081. auto it = std::make_unique<SecondaryIndexIterator>(
  7082. index.get(), std::move(underlying_it));
  7083. it->Seek("foo");
  7084. ASSERT_TRUE(it->Valid());
  7085. ASSERT_OK(it->status());
  7086. ASSERT_EQ(it->key(), "123foo");
  7087. ASSERT_EQ(it->value(), "oof321");
  7088. it->Next();
  7089. ASSERT_TRUE(it->Valid());
  7090. ASSERT_OK(it->status());
  7091. ASSERT_EQ(it->key(), "456foo");
  7092. ASSERT_EQ(it->value(), "oof654");
  7093. it->Next();
  7094. ASSERT_TRUE(it->Valid());
  7095. ASSERT_OK(it->status());
  7096. ASSERT_EQ(it->key(), "789foo");
  7097. ASSERT_EQ(it->value(), "oof987");
  7098. it->Next();
  7099. ASSERT_FALSE(it->Valid());
  7100. ASSERT_OK(it->status());
  7101. it->Seek("bar");
  7102. ASSERT_TRUE(it->Valid());
  7103. ASSERT_OK(it->status());
  7104. ASSERT_EQ(it->key(), "123bar");
  7105. ASSERT_EQ(it->value(), "rab321");
  7106. it->Next();
  7107. ASSERT_TRUE(it->Valid());
  7108. ASSERT_OK(it->status());
  7109. ASSERT_EQ(it->key(), "456bar");
  7110. ASSERT_EQ(it->value(), "rab654");
  7111. it->Next();
  7112. ASSERT_TRUE(it->Valid());
  7113. ASSERT_OK(it->status());
  7114. ASSERT_EQ(it->key(), "789bar");
  7115. ASSERT_EQ(it->value(), "rab987");
  7116. it->Next();
  7117. ASSERT_FALSE(it->Valid());
  7118. ASSERT_OK(it->status());
  7119. it->Seek("baz");
  7120. ASSERT_TRUE(it->Valid());
  7121. ASSERT_OK(it->status());
  7122. ASSERT_EQ(it->key(), "123baz");
  7123. ASSERT_EQ(it->value(), "zab321");
  7124. it->Next();
  7125. ASSERT_TRUE(it->Valid());
  7126. ASSERT_OK(it->status());
  7127. ASSERT_EQ(it->key(), "456baz");
  7128. ASSERT_EQ(it->value(), "zab654");
  7129. it->Next();
  7130. ASSERT_TRUE(it->Valid());
  7131. ASSERT_OK(it->status());
  7132. ASSERT_EQ(it->key(), "789baz");
  7133. ASSERT_EQ(it->value(), "zab987");
  7134. it->Next();
  7135. ASSERT_FALSE(it->Valid());
  7136. ASSERT_OK(it->status());
  7137. }
  7138. }
  7139. TEST_P(TransactionDBTest, CollapseKey) {
  7140. ASSERT_OK(ReOpen());
  7141. ASSERT_OK(db->Put({}, "hello", "world"));
  7142. ASSERT_OK(db->Flush({}));
  7143. ASSERT_OK(db->Merge({}, "hello", "world"));
  7144. ASSERT_OK(db->Flush({}));
  7145. ASSERT_OK(db->Merge({}, "hello", "world"));
  7146. ASSERT_OK(db->Flush({}));
  7147. std::string value;
  7148. ASSERT_OK(db->Get({}, "hello", &value));
  7149. ASSERT_EQ("world,world,world", value);
  7150. // get merge op info
  7151. std::vector<PinnableSlice> operands(3);
  7152. GetMergeOperandsOptions mergeOperandOptions;
  7153. mergeOperandOptions.expected_max_number_of_operands = 3;
  7154. int numOperands;
  7155. ASSERT_OK(db->GetMergeOperands({}, db->DefaultColumnFamily(), "hello",
  7156. operands.data(), &mergeOperandOptions,
  7157. &numOperands));
  7158. ASSERT_EQ(3, numOperands);
  7159. // collapse key
  7160. {
  7161. std::unique_ptr<Transaction> txn0{
  7162. db->BeginTransaction(WriteOptions{}, TransactionOptions{})};
  7163. ASSERT_OK(txn0->CollapseKey(ReadOptions{}, "hello"));
  7164. ASSERT_OK(txn0->Commit());
  7165. }
  7166. // merge operands should be 1
  7167. ASSERT_OK(db->GetMergeOperands({}, db->DefaultColumnFamily(), "hello",
  7168. operands.data(), &mergeOperandOptions,
  7169. &numOperands));
  7170. ASSERT_EQ(1, numOperands);
  7171. // get again after collapse
  7172. ASSERT_OK(db->Get({}, "hello", &value));
  7173. ASSERT_EQ("world,world,world", value);
  7174. // collapse of non-existent key
  7175. {
  7176. std::unique_ptr<Transaction> txn1{
  7177. db->BeginTransaction(WriteOptions{}, TransactionOptions{})};
  7178. ASSERT_TRUE(txn1->CollapseKey(ReadOptions{}, "dummy").IsNotFound());
  7179. }
  7180. }
  7181. TEST_P(TransactionDBTest, FlushedLogWithPendingPrepareIsSynced) {
  7182. // Repro for a bug where we missed a necessary sync of the old WAL during
  7183. // memtable flush. It happened due to applying an optimization to skip syncing
  7184. // the old WAL in too many scenarios (all memtable flushes on single CF
  7185. // databases). That optimization is only valid when memtable flush can
  7186. // guarantee the old WAL will not be read by crash-recovery. When the old WAL
  7187. // contains a prepare record without its corresponding commit, that WAL will
  7188. // be read by crash-recovery and therefore it must be synced.
  7189. const int kStartIndex = 1000;
  7190. int next_index = kStartIndex;
  7191. ASSERT_OK(ReOpen());
  7192. ASSERT_OK(
  7193. db->Put(WriteOptions(), "key" + std::to_string(next_index), "value"));
  7194. next_index++;
  7195. Transaction* txn = db->BeginTransaction(WriteOptions(), TransactionOptions());
  7196. ASSERT_OK(txn->SetName("xid" + std::to_string(next_index)));
  7197. ASSERT_OK(
  7198. txn->Put(Slice("key" + std::to_string(next_index)), Slice("value")));
  7199. next_index++;
  7200. ASSERT_OK(txn->Prepare());
  7201. // Set it directly writable so new WAL containing the commit record will be
  7202. // recovered despite not being explicitly synced.
  7203. fault_fs->SetFilesystemDirectWritable(true);
  7204. ASSERT_OK(db->Flush(FlushOptions()));
  7205. ASSERT_OK(txn->Commit());
  7206. delete txn;
  7207. ASSERT_OK(
  7208. db->Put(WriteOptions(), "key" + std::to_string(next_index), "value"));
  7209. next_index++;
  7210. ASSERT_OK(ReOpenNoDelete());
  7211. for (int i = kStartIndex; i < next_index; i++) {
  7212. PinnableSlice value;
  7213. ASSERT_OK(db->Get(ReadOptions(), db->DefaultColumnFamily(),
  7214. "key" + std::to_string(i), &value));
  7215. ASSERT_EQ("value", value);
  7216. }
  7217. }
  7218. class CommitBypassMemtableTest
  7219. : public DBTestBase,
  7220. public ::testing::WithParamInterface<std::tuple<bool, bool>> {
  7221. public:
  7222. CommitBypassMemtableTest() : DBTestBase("commit_bypass_memtable_test", true) {
  7223. SetUpTransactionDB();
  7224. }
  7225. protected:
  7226. TransactionDB* txn_db = nullptr;
  7227. Options options;
  7228. TransactionDBOptions txn_db_opts;
  7229. void SetUpTransactionDB(bool atomic_flush = false) {
  7230. options = CurrentOptions();
  7231. options.create_if_missing = true;
  7232. options.allow_2pc = true;
  7233. options.two_write_queues = std::get<0>(GetParam());
  7234. // Avoid write stall
  7235. options.max_write_buffer_number = 8;
  7236. options.atomic_flush = atomic_flush;
  7237. // Destroy the DB to recreate as a TransactionDB.
  7238. Close();
  7239. Destroy(options, true);
  7240. txn_db_opts.write_policy = TxnDBWritePolicy::WRITE_COMMITTED;
  7241. txn_db_opts.use_per_key_point_lock_mgr = std::get<1>(GetParam());
  7242. ASSERT_OK(TransactionDB::Open(options, txn_db_opts, dbname_, &txn_db));
  7243. ASSERT_NE(txn_db, nullptr);
  7244. db_ = txn_db;
  7245. }
  7246. };
  7247. INSTANTIATE_TEST_CASE_P(, CommitBypassMemtableTest,
  7248. ::testing::Combine(::testing::Bool(),
  7249. ::testing::Bool()));
  7250. // TODO: parameterize other tests in the file with commit_bypass_memtable
  7251. TEST_P(CommitBypassMemtableTest, SingleCFUpdate) {
  7252. // 10000 updates for one CF in a single transaction.
  7253. // Tests basic read before and after flush, with and w/o snapshot.
  7254. for (bool disable_flush : {false, true}) {
  7255. SetUpTransactionDB();
  7256. if (disable_flush) {
  7257. ASSERT_OK(db_->PauseBackgroundWork());
  7258. }
  7259. WriteOptions wopts;
  7260. std::unordered_set<std::string> not_found_at_snapshot;
  7261. std::map<std::string, std::string> snapshot_map;
  7262. std::map<std::string, std::string> expected_map;
  7263. for (int i = 0; i < 10000; i += 3) {
  7264. ASSERT_OK(db_->Put(wopts, Key(i), "foo"));
  7265. not_found_at_snapshot.insert(Key(i + 1));
  7266. snapshot_map[Key(i)] = "foo";
  7267. }
  7268. const Snapshot* snapshot = db_->GetSnapshot();
  7269. TransactionOptions txn_opts;
  7270. txn_opts.commit_bypass_memtable = true;
  7271. Transaction* txn1 = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7272. std::unordered_set<std::string> expected_not_found;
  7273. for (int i = 0; i < 10000; i += 2) {
  7274. std::string v = "val" + std::to_string(i);
  7275. ASSERT_OK(txn1->Put(Key(i), v));
  7276. expected_map[Key(i)] = v;
  7277. ASSERT_OK(txn1->Delete(Key(i + 1)));
  7278. expected_not_found.insert(Key(i + 1));
  7279. }
  7280. ASSERT_OK(txn1->SetName("xid1"));
  7281. ASSERT_OK(txn1->Prepare());
  7282. ASSERT_OK(txn1->Commit());
  7283. delete txn1;
  7284. ReadOptions ro_snapshot;
  7285. ro_snapshot.snapshot = snapshot;
  7286. // Verify at snapshot
  7287. VerifyDBFromMap(snapshot_map, nullptr, false, &ro_snapshot, nullptr,
  7288. &not_found_at_snapshot);
  7289. // Verify latest state
  7290. VerifyDBFromMap(expected_map, nullptr, false, nullptr, nullptr,
  7291. &expected_not_found);
  7292. db_->ReleaseSnapshot(snapshot);
  7293. if (disable_flush) {
  7294. ASSERT_OK(db_->ContinueBackgroundWork());
  7295. }
  7296. ASSERT_OK(db_->Flush({}));
  7297. VerifyDBFromMap(expected_map, nullptr, false, nullptr, nullptr,
  7298. &expected_not_found);
  7299. }
  7300. }
  7301. TEST_P(CommitBypassMemtableTest, SingleCFUpdateWithOverWrite) {
  7302. // Test the case where DB has base data and there are overwrites
  7303. // over the data in WBWI for one CF.
  7304. //
  7305. // live mem has k2
  7306. // ingested wbwi has k2 del k4, del k5, k6
  7307. // older imm mem has k3, k4, k5, k6
  7308. // SST has k1, k2, k4 (if not using single del)
  7309. for (bool single_del : {false, true}) {
  7310. SCOPED_TRACE("use single_del " + std::to_string(single_del));
  7311. for (bool disable_flush : {false, true}) {
  7312. SCOPED_TRACE("disable_flush: " + std::to_string(disable_flush));
  7313. SetUpTransactionDB();
  7314. std::map<std::string, std::string> expected = {{"k1", "sst"},
  7315. {"k2", "sst"}};
  7316. WriteOptions wopts;
  7317. ASSERT_OK(txn_db->Put(wopts, "k1", "sst"));
  7318. ASSERT_OK(txn_db->Put(wopts, "k2", "sst"));
  7319. if (!single_del) {
  7320. // single del does not allow overwrite. We write to this key below.
  7321. ASSERT_OK(txn_db->Put(wopts, "k4", "sst"));
  7322. expected["k4"] = "sst";
  7323. }
  7324. ASSERT_OK(txn_db->Flush({}));
  7325. std::unordered_set<std::string> not_found;
  7326. VerifyDBFromMap(expected, nullptr, false, nullptr, nullptr, &not_found);
  7327. if (disable_flush) {
  7328. ASSERT_OK(db_->PauseBackgroundWork());
  7329. }
  7330. // immutable mem
  7331. TransactionOptions topts;
  7332. Transaction* txn = txn_db->BeginTransaction(wopts, topts);
  7333. ASSERT_OK(txn->Put("k3", "imm"));
  7334. ASSERT_OK(txn->Put("k4", "imm"));
  7335. ASSERT_OK(txn->Put("k5", "imm"));
  7336. ASSERT_OK(txn->Put("k6", "imm"));
  7337. ASSERT_OK(txn->SetName("xid1"));
  7338. ASSERT_OK(txn->Prepare());
  7339. ASSERT_OK(txn->Commit());
  7340. auto dbimpl = static_cast_with_check<DBImpl>(txn_db->GetRootDB());
  7341. ASSERT_OK(dbimpl->TEST_SwitchMemtable());
  7342. for (const auto k : {"k3", "k4", "k5", "k6"}) {
  7343. expected[k] = "imm";
  7344. }
  7345. VerifyDBFromMap(expected, nullptr, false, nullptr, nullptr, &not_found);
  7346. uint64_t num_imm_mems;
  7347. if (disable_flush) {
  7348. ASSERT_TRUE(txn_db->GetIntProperty(
  7349. DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7350. ASSERT_EQ(num_imm_mems, 1);
  7351. }
  7352. // ingest wbwi
  7353. const Snapshot* snapshot = txn_db->GetSnapshot();
  7354. TransactionOptions topts_ingest;
  7355. topts_ingest.commit_bypass_memtable = true;
  7356. // reuse txn1
  7357. txn = txn_db->BeginTransaction(wopts, topts_ingest, txn);
  7358. ASSERT_OK(txn->Put("k2", "wbwi"));
  7359. if (single_del) {
  7360. ASSERT_OK(txn->SingleDelete("k4"));
  7361. ASSERT_OK(txn->SingleDelete("k5"));
  7362. } else {
  7363. ASSERT_OK(txn->Delete("k4"));
  7364. ASSERT_OK(txn->Delete("k5"));
  7365. }
  7366. ASSERT_OK(txn->Put("k6", "wbwi"));
  7367. ASSERT_OK(txn->SetName("xid2"));
  7368. ASSERT_OK(txn->Prepare());
  7369. VerifyDBFromMap(expected, nullptr, false, nullptr, nullptr, &not_found);
  7370. ASSERT_OK(txn->Commit());
  7371. if (disable_flush) {
  7372. ASSERT_TRUE(txn_db->GetIntProperty(
  7373. DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7374. // During Commit(), current empty memtable becomes a new immutable
  7375. // memtable. 3 here includes wbwi for this transaction, the empty
  7376. // immutable memtable, and the immutable memtable created
  7377. // by TEST_SwitchMemtable() above.
  7378. ASSERT_EQ(num_imm_mems, 3);
  7379. }
  7380. ReadOptions ro_snapshot;
  7381. ro_snapshot.snapshot = snapshot;
  7382. auto expected_at_snapshot = expected;
  7383. auto not_found_at_snapshot = not_found;
  7384. VerifyDBFromMap(expected, nullptr, false, &ro_snapshot, nullptr,
  7385. &not_found);
  7386. not_found = {"k4", "k5"};
  7387. expected.erase("k4");
  7388. expected.erase("k5");
  7389. expected["k2"] = "wbwi";
  7390. expected["k6"] = "wbwi";
  7391. VerifyDBFromMap(expected, nullptr, false, nullptr, nullptr, &not_found);
  7392. // live mem
  7393. txn = txn_db->BeginTransaction(wopts, topts, txn);
  7394. ASSERT_OK(txn->Put("k2", "live_mem"));
  7395. ASSERT_OK(txn->SetName("xid3"));
  7396. ASSERT_OK(txn->Prepare());
  7397. ASSERT_OK(txn->Commit());
  7398. delete txn;
  7399. expected["k2"] = "live_mem";
  7400. VerifyDBFromMap(expected, nullptr, false, nullptr, nullptr, &not_found);
  7401. if (disable_flush) {
  7402. ASSERT_OK(db_->ContinueBackgroundWork());
  7403. ASSERT_OK(db_->Flush({}));
  7404. } else {
  7405. ASSERT_OK(db_->WaitForCompact({}));
  7406. }
  7407. ASSERT_TRUE(txn_db->GetIntProperty(DB::Properties::kNumImmutableMemTable,
  7408. &num_imm_mems));
  7409. ASSERT_EQ(num_imm_mems, 0);
  7410. VerifyDBFromMap(expected, nullptr, false, nullptr, nullptr, &not_found);
  7411. VerifyDBFromMap(expected_at_snapshot, nullptr, false, &ro_snapshot,
  7412. nullptr, &not_found_at_snapshot);
  7413. txn_db->ReleaseSnapshot(snapshot);
  7414. }
  7415. }
  7416. }
  7417. TEST_P(CommitBypassMemtableTest, MultiCFOverwrite) {
  7418. // mini-stress test multi CF update
  7419. const int kNumKeys = 10000;
  7420. for (bool disable_flush : {false, true}) {
  7421. SCOPED_TRACE("disable_flush: " + std::to_string(disable_flush));
  7422. SetUpTransactionDB();
  7423. if (disable_flush) {
  7424. ASSERT_OK(txn_db->PauseBackgroundWork());
  7425. }
  7426. std::vector<std::string> cfs = {"puppy", "kitty", "meta"};
  7427. CreateColumnFamilies(cfs, options);
  7428. ASSERT_EQ(handles_.size(), 3);
  7429. ASSERT_EQ(handles_[0]->GetName(), cfs[0]);
  7430. ASSERT_EQ(handles_[1]->GetName(), cfs[1]);
  7431. ASSERT_EQ(handles_[2]->GetName(), cfs[2]);
  7432. std::map<std::string, std::string> expected_cf0;
  7433. std::unordered_set<std::string> not_found_cf0;
  7434. std::map<std::string, std::string> expected_cf1;
  7435. std::unordered_set<std::string> not_found_cf1;
  7436. WriteOptions wopts;
  7437. Random* rnd = Random::GetTLSInstance();
  7438. // Some base data
  7439. for (int i = 0; i < kNumKeys; ++i) {
  7440. std::string val_cf0 = "cf0_sst" + std::to_string(i);
  7441. if (rnd->OneIn(2)) {
  7442. ASSERT_OK(txn_db->Put(wopts, handles_[0], Key(i), val_cf0));
  7443. expected_cf0[Key(i)] = val_cf0;
  7444. } else {
  7445. not_found_cf0.insert(Key(i));
  7446. }
  7447. std::string val_cf1 = "cf1_sst" + std::to_string(i);
  7448. ASSERT_OK(txn_db->Put(wopts, handles_[1], Key(i), val_cf1));
  7449. expected_cf1[Key(i)] = val_cf1;
  7450. }
  7451. SCOPED_TRACE("Verify after SST");
  7452. ASSERT_OK(txn_db->Put(wopts, handles_[2], "id", "0"));
  7453. std::map<std::string, std::string> expected_cf2 = {{"id", "0"}};
  7454. VerifyDBFromMap(expected_cf0, nullptr, false, nullptr, handles_[0],
  7455. &not_found_cf0);
  7456. VerifyDBFromMap(expected_cf1, nullptr, false, nullptr, handles_[1],
  7457. &not_found_cf1);
  7458. if (!disable_flush) {
  7459. ASSERT_OK(txn_db->Flush({}, handles_[0]));
  7460. ASSERT_OK(txn_db->Flush({}, handles_[1]));
  7461. }
  7462. const Snapshot* snapshot = nullptr;
  7463. std::map<std::string, std::string> expected_cf0_snapshot;
  7464. std::unordered_set<std::string> not_found_cf0_snapshot;
  7465. std::map<std::string, std::string> expected_cf1_snapshot;
  7466. std::unordered_set<std::string> not_found_cf1_snapshot;
  7467. std::map<std::string, std::string> expected_cf2_snapshot;
  7468. auto init_snapshot_states = [&]() {
  7469. snapshot = txn_db->GetSnapshot();
  7470. expected_cf0_snapshot = expected_cf0;
  7471. not_found_cf0_snapshot = not_found_cf0;
  7472. expected_cf1_snapshot = expected_cf1;
  7473. not_found_cf1_snapshot = not_found_cf1;
  7474. expected_cf2_snapshot = expected_cf2;
  7475. };
  7476. if (rnd->OneIn(4)) {
  7477. init_snapshot_states();
  7478. }
  7479. // Transaction 1
  7480. TransactionOptions topts;
  7481. topts.commit_bypass_memtable = true;
  7482. Transaction* txn1 = txn_db->BeginTransaction(wopts, topts);
  7483. auto fill_txn = [&](Transaction* txn, const std::string& v) {
  7484. std::vector<int> indices(kNumKeys);
  7485. std::iota(indices.begin(), indices.end(), 0);
  7486. RandomShuffle(indices.begin(), indices.end());
  7487. for (int i : indices) {
  7488. // CF0 update
  7489. if (rnd->OneIn(4)) {
  7490. std::string val_cf0 = "cf0_" + v + std::to_string(i);
  7491. ASSERT_OK(txn->Put(handles_[0], Key(i), val_cf0));
  7492. expected_cf0[Key(i)] = val_cf0;
  7493. not_found_cf0.erase(Key(i));
  7494. } else if (rnd->OneIn(4)) {
  7495. ASSERT_OK(txn->Delete(handles_[0], Key(i)));
  7496. expected_cf0.erase(Key(i));
  7497. not_found_cf0.insert(Key(i));
  7498. }
  7499. // CF1 update
  7500. if (rnd->OneIn(4)) {
  7501. ASSERT_OK(txn->SingleDelete(handles_[1], Key(i)));
  7502. expected_cf1.erase(Key(i));
  7503. not_found_cf1.insert(Key(i));
  7504. }
  7505. if (rnd->OneIn(4) &&
  7506. not_found_cf1.find(Key(i)) != not_found_cf1.end()) {
  7507. // Can not overwrite when using SD.
  7508. std::string val_cf1 = "cf1_" + v + std::to_string(i);
  7509. ASSERT_OK(txn->Put(handles_[1], Key(i), val_cf1));
  7510. expected_cf1[Key(i)] = val_cf1;
  7511. not_found_cf1.erase(Key(i));
  7512. }
  7513. }
  7514. };
  7515. fill_txn(txn1, "txn1");
  7516. ASSERT_OK(txn1->SetName("xid1"));
  7517. ASSERT_OK(txn1->Prepare());
  7518. if (rnd->OneIn(2)) {
  7519. ASSERT_OK(txn1->GetCommitTimeWriteBatch()->Put(handles_[2], "id", "1"));
  7520. expected_cf2["id"] = "1";
  7521. }
  7522. ASSERT_OK(txn1->Commit());
  7523. delete txn1;
  7524. uint64_t num_imm_mems = 0;
  7525. if (disable_flush) {
  7526. ASSERT_TRUE(txn_db->GetIntProperty(
  7527. handles_[0], DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7528. ASSERT_EQ(num_imm_mems, 2);
  7529. ASSERT_TRUE(txn_db->GetIntProperty(
  7530. handles_[1], DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7531. ASSERT_EQ(num_imm_mems, 2);
  7532. ASSERT_TRUE(txn_db->GetIntProperty(
  7533. handles_[2], DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7534. ASSERT_EQ(num_imm_mems, 0);
  7535. }
  7536. SCOPED_TRACE("Verify cf0 after txn1");
  7537. VerifyDBFromMap(expected_cf0, nullptr, false, nullptr, handles_[0],
  7538. &not_found_cf0);
  7539. SCOPED_TRACE("Verify cf1 after txn1");
  7540. SCOPED_TRACE("db is " + txn_db->GetName());
  7541. VerifyDBFromMap(expected_cf1, nullptr, false, nullptr, handles_[1],
  7542. &not_found_cf1);
  7543. VerifyDBFromMap(expected_cf2, nullptr, false, nullptr, handles_[2]);
  7544. auto verify_at_snapshot = [&](const std::string& m) {
  7545. if (snapshot) {
  7546. SCOPED_TRACE("Verify at snapshot " + m);
  7547. ReadOptions ro;
  7548. ro.snapshot = snapshot;
  7549. SCOPED_TRACE("Verify cf0 after txn1");
  7550. VerifyDBFromMap(expected_cf0_snapshot, nullptr, false, &ro, handles_[0],
  7551. &not_found_cf0_snapshot);
  7552. SCOPED_TRACE("Verify cf1 after txn1");
  7553. VerifyDBFromMap(expected_cf1_snapshot, nullptr, false, &ro, handles_[1],
  7554. &not_found_cf1_snapshot);
  7555. VerifyDBFromMap(expected_cf2_snapshot, nullptr, false, &ro,
  7556. handles_[2]);
  7557. if (rnd->OneIn(2)) {
  7558. txn_db->ReleaseSnapshot(snapshot);
  7559. snapshot = nullptr;
  7560. }
  7561. }
  7562. };
  7563. verify_at_snapshot("txn1");
  7564. if (!snapshot && rnd->OneIn(4)) {
  7565. init_snapshot_states();
  7566. }
  7567. // Live memtable or another transaction with commit_bypass_memtable
  7568. TransactionOptions topts2;
  7569. topts2.commit_bypass_memtable = rnd->OneIn(2);
  7570. SCOPED_TRACE("txn2 commit_bypass_memtable = " +
  7571. std::to_string(topts2.commit_bypass_memtable));
  7572. Transaction* txn2 = txn_db->BeginTransaction(wopts, topts2);
  7573. fill_txn(txn2, "txn2");
  7574. ASSERT_OK(txn2->SetName("xid2"));
  7575. ASSERT_OK(txn2->Prepare());
  7576. if (rnd->OneIn(2)) {
  7577. ASSERT_OK(txn2->GetCommitTimeWriteBatch()->Put(handles_[2], "id", "2"));
  7578. expected_cf2["id"] = "2";
  7579. }
  7580. ASSERT_OK(txn2->Commit());
  7581. delete txn2;
  7582. if (disable_flush) {
  7583. ASSERT_TRUE(txn_db->GetIntProperty(
  7584. handles_[0], DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7585. ASSERT_EQ(num_imm_mems, topts2.commit_bypass_memtable ? 4 : 2);
  7586. ASSERT_TRUE(txn_db->GetIntProperty(
  7587. handles_[1], DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7588. ASSERT_EQ(num_imm_mems, topts2.commit_bypass_memtable ? 4 : 2);
  7589. ASSERT_TRUE(txn_db->GetIntProperty(
  7590. handles_[2], DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7591. ASSERT_EQ(num_imm_mems, 0);
  7592. }
  7593. SCOPED_TRACE("Verify cf0 after txn2");
  7594. VerifyDBFromMap(expected_cf0, nullptr, false, nullptr, handles_[0],
  7595. &not_found_cf0);
  7596. SCOPED_TRACE("Verify cf1 after txn2");
  7597. VerifyDBFromMap(expected_cf1, nullptr, false, nullptr, handles_[1],
  7598. &not_found_cf1);
  7599. // cf2 should not have keys in not_found_cf1 either
  7600. VerifyDBFromMap(expected_cf2, nullptr, false, nullptr, handles_[2],
  7601. &not_found_cf1);
  7602. verify_at_snapshot("txn2");
  7603. if (!snapshot && rnd->OneIn(4)) {
  7604. init_snapshot_states();
  7605. }
  7606. // Verify all data is flushed
  7607. if (disable_flush) {
  7608. ASSERT_OK(db_->ContinueBackgroundWork());
  7609. ASSERT_OK(db_->Flush({}, handles_[0]));
  7610. ASSERT_OK(db_->Flush({}, handles_[1]));
  7611. } else {
  7612. ASSERT_OK(db_->WaitForCompact({}));
  7613. }
  7614. VerifyDBFromMap(expected_cf0, nullptr, false, nullptr, handles_[0],
  7615. &not_found_cf0);
  7616. VerifyDBFromMap(expected_cf1, nullptr, false, nullptr, handles_[1],
  7617. &not_found_cf1);
  7618. VerifyDBFromMap(expected_cf2, nullptr, false, nullptr, handles_[2],
  7619. &not_found_cf1);
  7620. verify_at_snapshot("flush");
  7621. if (snapshot) {
  7622. db_->ReleaseSnapshot(snapshot);
  7623. }
  7624. }
  7625. }
  7626. TEST_P(CommitBypassMemtableTest, Recovery) {
  7627. // Test that ingested txn can be recovered.
  7628. // Implementation detail: this tests that write path reserves enough sequence
  7629. // number for the ingested memtables (see seq_inc in WriteImpl()). For
  7630. // example, suppose that we only assign one sequence number per ingested
  7631. // memtable. Then txn1 will be assigned seqno 1 and txn2 will be assigned 2.
  7632. // During recovery, we will not use memtable ingestion and will fall back
  7633. // to memtable insertion. The sequence number for the first key in a
  7634. // transaction is the commit sequence number. So for txn1, we will insert into
  7635. // memtable k2@1 and k1@2. And for txn2, we will insert k1@2 and k2@3. This
  7636. // results in duplicated key@seqno.
  7637. WriteOptions wopts;
  7638. TransactionOptions txn_opts;
  7639. txn_opts.commit_bypass_memtable = true;
  7640. Transaction* txn1 = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7641. ASSERT_OK(txn1->SetName("xid1"));
  7642. ASSERT_OK(txn1->Put("k2", "v2"));
  7643. ASSERT_OK(txn1->Put("k1", "v1"));
  7644. ASSERT_OK(txn1->Prepare());
  7645. ASSERT_OK(txn1->Commit());
  7646. // Test txn reuse code path
  7647. txn1 = txn_db->BeginTransaction(wopts, txn_opts, txn1);
  7648. ASSERT_OK(txn1->SetName("xid2"));
  7649. ASSERT_OK(txn1->Put("k1", "v3"));
  7650. ASSERT_OK(txn1->Put("k2", "v4"));
  7651. ASSERT_OK(txn1->Prepare());
  7652. ASSERT_OK(txn1->Commit());
  7653. delete txn1;
  7654. std::map<std::string, std::string> expected = {{"k1", "v3"}, {"k2", "v4"}};
  7655. VerifyDBFromMap(expected);
  7656. ASSERT_OK(txn_db->Close());
  7657. delete txn_db;
  7658. ASSERT_OK(TransactionDB::Open(options, txn_db_opts, dbname_, &txn_db));
  7659. db_ = txn_db;
  7660. VerifyDBFromMap(expected);
  7661. }
  7662. TEST_P(CommitBypassMemtableTest, OptimizeLargeTxnCommitThreshold) {
  7663. // Tests TransactionOptions::large_txn_commit_optimize_threshold
  7664. const uint32_t threshold = 10;
  7665. SetUpTransactionDB();
  7666. bool commit_bypass_memtable = false;
  7667. // TODO: add and use stats for this
  7668. SyncPoint::GetInstance()->SetCallBack(
  7669. "WriteCommittedTxn::CommitInternal:bypass_memtable",
  7670. [&](void* arg) { commit_bypass_memtable = *(static_cast<bool*>(arg)); });
  7671. SyncPoint::GetInstance()->EnableProcessing();
  7672. WriteOptions wopts;
  7673. // Test default (disabled)
  7674. TransactionOptions txn_opts;
  7675. auto txn1 = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7676. ASSERT_OK(txn1->SetName("xid0"));
  7677. for (int i = 0; i < 100; ++i) {
  7678. ASSERT_OK(
  7679. txn1->Put("key" + std::to_string(i), "value" + std::to_string(i)));
  7680. }
  7681. ASSERT_OK(txn1->Prepare());
  7682. ASSERT_OK(txn1->Commit());
  7683. ASSERT_FALSE(commit_bypass_memtable);
  7684. delete txn1;
  7685. // Test with transaction option only
  7686. txn_opts.large_txn_commit_optimize_threshold = threshold;
  7687. // Test with transaction below threshold
  7688. txn1 = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7689. ASSERT_OK(txn1->SetName("xid1"));
  7690. ASSERT_OK(txn1->Put("k1", "v1"));
  7691. ASSERT_OK(txn1->Prepare());
  7692. ASSERT_OK(txn1->Commit());
  7693. ASSERT_FALSE(commit_bypass_memtable);
  7694. delete txn1;
  7695. // Test with transaction at threshold
  7696. txn1 = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7697. ASSERT_OK(txn1->SetName("xid2"));
  7698. for (uint32_t i = 0; i < threshold; ++i) {
  7699. ASSERT_OK(
  7700. txn1->Put("key" + std::to_string(i), "value" + std::to_string(i)));
  7701. }
  7702. ASSERT_OK(txn1->Prepare());
  7703. ASSERT_OK(txn1->Commit());
  7704. ASSERT_TRUE(commit_bypass_memtable);
  7705. delete txn1;
  7706. SetUpTransactionDB();
  7707. // Test with multiple column families
  7708. std::vector<std::string> cfs = {"pk", "sk"};
  7709. CreateColumnFamilies(cfs, options);
  7710. txn_opts.large_txn_commit_optimize_threshold = threshold;
  7711. // Below threshold
  7712. auto txn_cf = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7713. ASSERT_OK(txn_cf->SetName("xid_cf_below"));
  7714. for (uint32_t i = 0; i < threshold - 1; ++i) {
  7715. ASSERT_OK(txn_cf->Put(handles_[i % 2], "key" + std::to_string(i),
  7716. "value" + std::to_string(i)));
  7717. }
  7718. ASSERT_OK(txn_cf->Prepare());
  7719. commit_bypass_memtable = false;
  7720. ASSERT_OK(txn_cf->Commit());
  7721. ASSERT_FALSE(commit_bypass_memtable);
  7722. delete txn_cf;
  7723. // At threshold
  7724. txn_cf = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7725. ASSERT_OK(txn_cf->SetName("xid_cf_at_threshold"));
  7726. for (uint32_t i = 0; i < threshold; ++i) {
  7727. ASSERT_OK(txn_cf->Put(handles_[i % 2], "key" + std::to_string(i),
  7728. "value" + std::to_string(i)));
  7729. }
  7730. ASSERT_OK(txn_cf->Prepare());
  7731. commit_bypass_memtable = false;
  7732. ASSERT_OK(txn_cf->Commit());
  7733. ASSERT_TRUE(commit_bypass_memtable);
  7734. delete txn_cf;
  7735. // Test that commit_bypass_memtable takes precedence over
  7736. // large_txn_commit_optimize_threshold
  7737. txn_opts.large_txn_commit_optimize_threshold =
  7738. threshold * 10; // High threshold
  7739. txn_opts.commit_bypass_memtable = true; // Should override threshold
  7740. txn_cf = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  7741. ASSERT_OK(txn_cf->SetName("xid_cf_precedence"));
  7742. ASSERT_OK(txn_cf->Put(handles_[0], "key1", "value1")); // Just one operation
  7743. ASSERT_OK(txn_cf->Prepare());
  7744. commit_bypass_memtable = false;
  7745. ASSERT_OK(txn_cf->Commit());
  7746. ASSERT_TRUE(commit_bypass_memtable); // Should be true because of
  7747. // commit_bypass_memtable
  7748. delete txn_cf;
  7749. }
  7750. TEST_P(CommitBypassMemtableTest, AtomicFlushTest) {
  7751. const uint32_t threshold = 10;
  7752. SetUpTransactionDB(/*atomic_flush=*/true);
  7753. SyncPoint::GetInstance()->EnableProcessing();
  7754. std::vector<std::string> cfs = {"cf0", "cf1", "cf2"};
  7755. CreateColumnFamilies(cfs, options);
  7756. // Seed data in CF1 and 2 as atomic flush picks CFs with non-empty memtable
  7757. ASSERT_OK(db_->Put({}, handles_[1], "key1", "val1"));
  7758. ASSERT_OK(db_->Put({}, handles_[2], "key2", "val2"));
  7759. // Write to cf 0, should see cf1 and cf2 flushed too
  7760. TransactionOptions txn_opts;
  7761. txn_opts.large_txn_commit_optimize_threshold = threshold;
  7762. auto txn = txn_db->BeginTransaction({}, txn_opts, nullptr);
  7763. for (uint32_t i = 0; i <= threshold; ++i) {
  7764. ASSERT_OK(txn->Put(handles_[0], "key" + std::to_string(i),
  7765. "cf0" + std::to_string(i)));
  7766. }
  7767. ASSERT_OK(txn->SetName("cf0"));
  7768. ASSERT_OK(txn->Prepare());
  7769. ASSERT_OK(txn->Commit());
  7770. delete txn;
  7771. ASSERT_OK(db_->WaitForCompact({}));
  7772. for (size_t i = 0; i < 3; ++i) {
  7773. auto cfh = static_cast<ColumnFamilyHandleImpl*>(handles_[i]);
  7774. ASSERT_EQ(0, cfh->cfd()->imm()->NumNotFlushed());
  7775. ASSERT_TRUE(cfh->cfd()->mem()->IsEmpty());
  7776. }
  7777. }
  7778. TEST_P(CommitBypassMemtableTest, MergeAndMultiCF) {
  7779. // disable_flush allows testing Get path with memtables.
  7780. for (bool disable_flush : {false, true}) {
  7781. SCOPED_TRACE("disable_flush: " + std::to_string(disable_flush));
  7782. SetUpTransactionDB();
  7783. if (disable_flush) {
  7784. ASSERT_OK(txn_db->PauseBackgroundWork());
  7785. }
  7786. std::vector<std::string> cfs = {"appendmerge"};
  7787. Options opts;
  7788. opts.max_write_buffer_number = 8;
  7789. opts.merge_operator = MergeOperators::CreateFromStringId("stringappend");
  7790. CreateColumnFamilies(cfs, opts);
  7791. cfs = {"uint64addmerge"};
  7792. opts.merge_operator = MergeOperators::CreateFromStringId("uint64add");
  7793. CreateColumnFamilies(cfs, opts);
  7794. cfs = {"data"};
  7795. opts.merge_operator = nullptr;
  7796. CreateColumnFamilies(cfs, opts);
  7797. ASSERT_TRUE(handles_.size() == 3);
  7798. std::string buf_count;
  7799. PutFixed64(&buf_count, 1);
  7800. // Some base data in SST or memtable
  7801. ASSERT_OK(db_->Merge({}, handles_[1], "count", buf_count));
  7802. ASSERT_OK(db_->Put({}, handles_[0], "k5", "5v1"));
  7803. ASSERT_OK(db_->Merge({}, handles_[0], "k7", "7v1"));
  7804. if (!disable_flush) {
  7805. ASSERT_OK(db_->Flush({}, handles_[1]));
  7806. }
  7807. WriteOptions wopts;
  7808. TransactionOptions txn_opts;
  7809. txn_opts.commit_bypass_memtable = true;
  7810. Transaction* txn = txn_db->BeginTransaction(wopts, txn_opts);
  7811. ASSERT_OK(txn->SetName("xid1"));
  7812. ASSERT_OK(txn->Put(handles_[0], "k1", "v1"));
  7813. ASSERT_OK(txn->Merge(handles_[0], "k1", "v2"));
  7814. ASSERT_OK(txn->Delete(handles_[0], "k2"));
  7815. ASSERT_OK(txn->Merge(handles_[0], "k2", "v1"));
  7816. ASSERT_OK(txn->Merge(handles_[0], "k3", "v1"));
  7817. ASSERT_OK(txn->Delete(handles_[0], "k3"));
  7818. ASSERT_OK(txn->Merge(handles_[0], "k4", "v1"));
  7819. ASSERT_OK(txn->Put(handles_[0], "k4", "v4"));
  7820. ASSERT_OK(txn->Merge(handles_[0], "k5", "5v2"));
  7821. ASSERT_OK(txn->Merge(handles_[0], "k6", "6v1"));
  7822. ASSERT_OK(txn->Merge(handles_[0], "k6", "6v2"));
  7823. ASSERT_OK(txn->Merge(handles_[0], "k7", "7v2"));
  7824. ASSERT_OK(txn->Merge(handles_[0], "k7", "7v3"));
  7825. ASSERT_OK(txn->Merge(handles_[1], "count", buf_count));
  7826. ASSERT_OK(txn->Merge(handles_[1], "count", buf_count));
  7827. ASSERT_OK(txn->Put(handles_[2], "a", "a1"));
  7828. ASSERT_OK(txn->Put(handles_[2], "c", "c1"));
  7829. ASSERT_OK(txn->Prepare());
  7830. ASSERT_OK(txn->Commit());
  7831. // Data in mutable memtable
  7832. txn_opts.commit_bypass_memtable = false;
  7833. txn = txn_db->BeginTransaction(wopts, txn_opts, txn);
  7834. ASSERT_OK(txn->SetName("xid2"));
  7835. ASSERT_OK(txn->Merge(handles_[0], "k1", "v3"));
  7836. ASSERT_OK(txn->Merge(handles_[1], "count", buf_count));
  7837. ASSERT_OK(txn->Prepare());
  7838. ASSERT_OK(txn->Commit());
  7839. delete txn;
  7840. std::map<std::string, std::string> expected_cf0 = {
  7841. {"k1", "v1,v2,v3"}, {"k2", "v1"}, {"k4", "v4"},
  7842. {"k5", "5v1,5v2"}, {"k6", "6v1,6v2"}, {"k7", "7v1,7v2,7v3"},
  7843. };
  7844. std::unordered_set<std::string> not_found_cf0 = {"k3"};
  7845. VerifyDBFromMap(expected_cf0, nullptr, false, nullptr, handles_[0],
  7846. &not_found_cf0);
  7847. std::string count;
  7848. PutFixed64(&count, 4);
  7849. std::map<std::string, std::string> expected_cf1 = {
  7850. {"count", count},
  7851. };
  7852. VerifyDBFromMap(expected_cf1, nullptr, false, nullptr, handles_[1]);
  7853. std::map<std::string, std::string> expected_cf2 = {
  7854. {"a", "a1"},
  7855. {"c", "c1"},
  7856. };
  7857. VerifyDBFromMap(expected_cf2, nullptr, false, nullptr, handles_[2]);
  7858. // Verify all data is flushed
  7859. if (disable_flush) {
  7860. uint64_t num_imm_mems = 0;
  7861. ASSERT_TRUE(txn_db->GetIntProperty(
  7862. handles_[0], DB::Properties::kNumImmutableMemTable, &num_imm_mems));
  7863. ASSERT_EQ(2,
  7864. num_imm_mems); // 1 imm mem before WBWI, 1 imm is WBWI itself
  7865. // Test GetMergeOperands() for CF0
  7866. std::vector<PinnableSlice> merge_operands(4);
  7867. GetMergeOperandsOptions merge_operand_opts;
  7868. merge_operand_opts.expected_max_number_of_operands = 4;
  7869. int num_operands = 0;
  7870. ASSERT_OK(db_->GetMergeOperands({}, handles_[0], "k1",
  7871. merge_operands.data(),
  7872. &merge_operand_opts, &num_operands));
  7873. ASSERT_EQ(num_operands, 3);
  7874. ASSERT_EQ(merge_operands[0], "v1");
  7875. ASSERT_EQ(merge_operands[1], "v2");
  7876. ASSERT_EQ(merge_operands[2], "v3");
  7877. ASSERT_OK(db_->ContinueBackgroundWork());
  7878. ASSERT_OK(db_->Flush({}, {handles_[0], handles_[1], handles_[2]}));
  7879. } else {
  7880. ASSERT_OK(db_->WaitForCompact({}));
  7881. }
  7882. VerifyDBFromMap(expected_cf0, nullptr, false, nullptr, handles_[0],
  7883. &not_found_cf0);
  7884. VerifyDBFromMap(expected_cf1, nullptr, false, nullptr, handles_[1]);
  7885. VerifyDBFromMap(expected_cf2, nullptr, false, nullptr, handles_[2]);
  7886. }
  7887. }
  7888. TEST_P(CommitBypassMemtableTest, MergeMiniStress) {
  7889. // To test the merge path with various LSM shapes
  7890. std::string key_prefix = "key";
  7891. std::string value_prefix = "val";
  7892. Random* rnd = Random::GetTLSInstance();
  7893. const int kBatchSize = 50;
  7894. for (int num_memtable_to_merge : {1, 4}) {
  7895. SetUpTransactionDB();
  7896. std::vector<std::string> cfs = {"appendmerge"};
  7897. Options opts;
  7898. opts.max_write_buffer_number = 10;
  7899. // Exercise read path of memtables.
  7900. opts.min_write_buffer_number_to_merge = num_memtable_to_merge;
  7901. opts.merge_operator = MergeOperators::CreateFromStringId("stringappend");
  7902. CreateColumnFamilies(cfs, opts);
  7903. ASSERT_TRUE(handles_.size() == 1);
  7904. std::map<std::string, std::string> expected_cf;
  7905. std::unordered_set<std::string> not_found_cf;
  7906. for (int i = 0; i < 10000; i += kBatchSize) {
  7907. WriteOptions wopts;
  7908. TransactionOptions txn_opts;
  7909. txn_opts.commit_bypass_memtable = rnd->OneIn(2);
  7910. std::unique_ptr<Transaction> txn{
  7911. txn_db->BeginTransaction(wopts, txn_opts)};
  7912. const int txn_count = i / kBatchSize;
  7913. ASSERT_OK(txn->SetName("xid" + std::to_string(txn_count)));
  7914. const Snapshot* snapshot = txn_db->GetSnapshot();
  7915. // Remember the state for the snapshot
  7916. auto expected_cf_snapshot = expected_cf;
  7917. auto not_found_cf_snapshot = not_found_cf;
  7918. for (int j = 0; j < kBatchSize; ++j) {
  7919. std::string key = key_prefix + std::to_string(rnd->Uniform(1000));
  7920. std::string value = value_prefix + std::to_string(i + j);
  7921. int operation = rnd->Uniform(10);
  7922. if (operation < 8) { // 80% probability for Merge
  7923. ASSERT_OK(txn->Merge(handles_[0], key, value));
  7924. if (expected_cf.find(key) != expected_cf.end()) {
  7925. expected_cf[key] += "," + value;
  7926. } else {
  7927. expected_cf[key] = value;
  7928. }
  7929. not_found_cf.erase(key);
  7930. } else if (operation == 8) { // 10% probability for PUT
  7931. ASSERT_OK(txn->Put(handles_[0], key, value));
  7932. expected_cf[key] = value;
  7933. not_found_cf.erase(key);
  7934. } else { // 10% probability for DEL
  7935. ASSERT_OK(txn->Delete(handles_[0], key));
  7936. expected_cf.erase(key);
  7937. not_found_cf.insert(key);
  7938. }
  7939. }
  7940. ASSERT_OK(txn->Prepare());
  7941. ASSERT_OK(txn->Commit());
  7942. if (txn_count % 10 == 0) {
  7943. VerifyDBFromMap(expected_cf, nullptr, false, nullptr, handles_[0],
  7944. &not_found_cf);
  7945. // Verify read at snapshot
  7946. ReadOptions ro;
  7947. ro.snapshot = snapshot;
  7948. VerifyDBFromMap(expected_cf_snapshot, nullptr, false, &ro, handles_[0],
  7949. &not_found_cf_snapshot);
  7950. }
  7951. txn_db->ReleaseSnapshot(snapshot);
  7952. }
  7953. VerifyDBFromMap(expected_cf, nullptr, false, nullptr, handles_[0]);
  7954. }
  7955. }
  7956. TEST_P(TransactionDBTest, SelfDeadlockBug) {
  7957. ASSERT_OK(ReOpen());
  7958. // Create two transactions
  7959. WriteOptions write_options;
  7960. TransactionOptions txn_options;
  7961. txn_options.lock_timeout = 50; // 50ms
  7962. txn_options.deadlock_detect = true;
  7963. ASSERT_OK(db->Put({}, "shared_key", "shared_value"));
  7964. // First transaction
  7965. Transaction* txn1 = db->BeginTransaction(write_options, txn_options);
  7966. ASSERT_TRUE(txn1);
  7967. ASSERT_OK(txn1->SetName("txn1"));
  7968. // Second transaction
  7969. Transaction* txn2 = db->BeginTransaction(write_options, txn_options);
  7970. ASSERT_TRUE(txn2);
  7971. ASSERT_OK(txn2->SetName("txn2"));
  7972. // Both transactions acquire shared lock on the same key.
  7973. std::string value;
  7974. ASSERT_OK(txn1->GetForUpdate(ReadOptions(), "shared_key", &value,
  7975. /*exclusive=*/false));
  7976. ASSERT_OK(txn2->GetForUpdate(ReadOptions(), "shared_key", &value,
  7977. /*exclusive=*/false));
  7978. // Second transaction tries to upgrade to exclusive lock, which should
  7979. // timeout.
  7980. Status s = txn1->Put({}, "shared_key", "val");
  7981. // Print out the deadlock info buffer
  7982. ASSERT_TRUE(db->GetDeadlockInfoBuffer().empty());
  7983. ASSERT_TRUE(s.IsTimedOut());
  7984. ASSERT_EQ(s.ToString(), "Operation timed out: Timeout waiting to lock key");
  7985. // After release lock from txn2, txn1 should be able to proceed.
  7986. ASSERT_OK(txn2->Rollback());
  7987. ASSERT_OK(txn1->Put({}, "shared_key", "val"));
  7988. ASSERT_OK(txn1->Rollback());
  7989. delete txn1;
  7990. delete txn2;
  7991. }
  7992. INSTANTIATE_TEST_CASE_P(
  7993. TransactionDBBasicTest, TransactionDBTest,
  7994. ::testing::Combine(/*user_per_key_point_lock_manager=*/::testing::Bool(),
  7995. /*deadlock_timeout_us=*/::testing::Values(0, 1000)));
  7996. TEST_P(CommitBypassMemtableTest,
  7997. OptimizeLargeTxnCommitWriteBatchSizeThreshold) {
  7998. // Tests TransactionOptions::large_txn_commit_optimize_byte_threshold
  7999. const uint64_t threshold = 100;
  8000. SetUpTransactionDB();
  8001. bool commit_bypass_memtable = false;
  8002. SyncPoint::GetInstance()->SetCallBack(
  8003. "WriteCommittedTxn::CommitInternal:bypass_memtable",
  8004. [&](void* arg) { commit_bypass_memtable = *(static_cast<bool*>(arg)); });
  8005. SyncPoint::GetInstance()->EnableProcessing();
  8006. Random rnd(301);
  8007. WriteOptions wopts;
  8008. TransactionOptions txn_opts;
  8009. // Test default
  8010. auto txn = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  8011. ASSERT_OK(txn->SetName("xid0"));
  8012. ASSERT_OK(txn->Put("k1", rnd.RandomString(1000)));
  8013. ASSERT_OK(txn->Prepare());
  8014. ASSERT_OK(txn->Commit());
  8015. ASSERT_FALSE(commit_bypass_memtable);
  8016. // Test with transaction option only
  8017. txn_opts.large_txn_commit_optimize_byte_threshold = threshold;
  8018. // Above threshold
  8019. txn = txn_db->BeginTransaction(wopts, txn_opts, txn);
  8020. ASSERT_OK(txn->SetName("xid1"));
  8021. ASSERT_OK(txn->Put("k1", rnd.RandomString(threshold)));
  8022. ASSERT_TRUE(txn->GetWriteBatch()->GetDataSize() >= threshold);
  8023. ASSERT_OK(txn->Prepare());
  8024. ASSERT_OK(txn->Commit());
  8025. ASSERT_TRUE(commit_bypass_memtable);
  8026. // Below threshold
  8027. txn = txn_db->BeginTransaction(wopts, txn_opts, txn);
  8028. ASSERT_OK(txn->SetName("xid2"));
  8029. ASSERT_OK(txn->Put("k2", "v2"));
  8030. ASSERT_TRUE(txn->GetWriteBatch()->GetDataSize() < threshold);
  8031. ASSERT_OK(txn->Prepare());
  8032. ASSERT_OK(txn->Commit());
  8033. ASSERT_FALSE(commit_bypass_memtable);
  8034. delete txn;
  8035. // With commit_bypass_memtbale
  8036. TransactionOptions txn_opts2;
  8037. txn_opts2.commit_bypass_memtable = true;
  8038. txn_opts2.large_txn_commit_optimize_byte_threshold = threshold;
  8039. txn = txn_db->BeginTransaction(wopts, txn_opts2, nullptr);
  8040. ASSERT_OK(txn->SetName("xid3"));
  8041. ASSERT_OK(txn->Put("k3", "v3"));
  8042. ASSERT_TRUE(txn->GetWriteBatch()->GetDataSize() < threshold);
  8043. ASSERT_OK(txn->Prepare());
  8044. ASSERT_OK(txn->Commit());
  8045. ASSERT_TRUE(commit_bypass_memtable);
  8046. delete txn;
  8047. // With count based threshold `large_txn_commit_optimize_threshold`
  8048. TransactionOptions txn_opts3;
  8049. txn_opts3.commit_bypass_memtable = false;
  8050. txn_opts3.large_txn_commit_optimize_byte_threshold = threshold;
  8051. txn_opts3.large_txn_commit_optimize_threshold = 3;
  8052. txn = txn_db->BeginTransaction(wopts, txn_opts3, nullptr);
  8053. ASSERT_OK(txn->SetName("xid4"));
  8054. ASSERT_OK(txn->Put("k3", "v3"));
  8055. ASSERT_OK(txn->Delete("k2"));
  8056. ASSERT_OK(txn->Delete("k1"));
  8057. ASSERT_TRUE(txn->GetWriteBatch()->GetDataSize() < threshold);
  8058. ASSERT_OK(txn->Prepare());
  8059. ASSERT_OK(txn->Commit());
  8060. ASSERT_TRUE(commit_bypass_memtable);
  8061. txn = txn_db->BeginTransaction(wopts, txn_opts3, txn);
  8062. ASSERT_OK(txn->SetName("xid4"));
  8063. ASSERT_OK(txn->Put("k3", "v3"));
  8064. ASSERT_OK(txn->Delete("k2"));
  8065. ASSERT_OK(txn->Delete("k1"));
  8066. ASSERT_TRUE(txn->GetWriteBatch()->GetDataSize() < threshold);
  8067. ASSERT_OK(txn->Prepare());
  8068. ASSERT_OK(txn->Commit());
  8069. ASSERT_TRUE(commit_bypass_memtable);
  8070. txn = txn_db->BeginTransaction(wopts, txn_opts3, txn);
  8071. ASSERT_OK(txn->SetName("xid5"));
  8072. ASSERT_OK(txn->Put("k5", "v5"));
  8073. ASSERT_TRUE(txn->GetWriteBatch()->GetDataSize() < threshold);
  8074. ASSERT_OK(txn->Prepare());
  8075. ASSERT_OK(txn->Commit());
  8076. ASSERT_FALSE(commit_bypass_memtable);
  8077. delete txn;
  8078. // Test with multiple column families
  8079. std::vector<std::string> cfs = {"pk", "sk"};
  8080. CreateColumnFamilies(cfs, options);
  8081. TransactionOptions txn_opts_cf;
  8082. txn_opts_cf.large_txn_commit_optimize_byte_threshold = threshold;
  8083. // Below threshold
  8084. auto txn_cf = txn_db->BeginTransaction(wopts, txn_opts_cf, nullptr);
  8085. ASSERT_OK(txn_cf->SetName("xid_cf_above"));
  8086. ASSERT_OK(txn_cf->Put(handles_[0], "k1", rnd.RandomString(threshold / 2)));
  8087. ASSERT_OK(txn_cf->Put(handles_[1], "k2", rnd.RandomString(threshold / 2)));
  8088. ASSERT_TRUE(txn_cf->GetWriteBatch()->GetDataSize() >= threshold);
  8089. ASSERT_OK(txn_cf->Prepare());
  8090. ASSERT_OK(txn_cf->Commit());
  8091. ASSERT_TRUE(commit_bypass_memtable);
  8092. txn_cf = txn_db->BeginTransaction(wopts, txn_opts_cf, txn_cf);
  8093. ASSERT_OK(txn_cf->SetName("xid_cf_below"));
  8094. ASSERT_OK(txn_cf->Put(handles_[0], "k1", rnd.RandomString(10)));
  8095. ASSERT_OK(txn_cf->Put(handles_[1], "k2", rnd.RandomString(10)));
  8096. ASSERT_TRUE(txn_cf->GetWriteBatch()->GetDataSize() < threshold);
  8097. ASSERT_OK(txn_cf->Prepare());
  8098. ASSERT_OK(txn_cf->Commit());
  8099. ASSERT_FALSE(commit_bypass_memtable);
  8100. delete txn_cf;
  8101. }
  8102. TEST_P(CommitBypassMemtableTest, WBWIOpCountMismatchWBCount) {
  8103. // Tests that large txn optimization checks op count in WBWI vs WB. When an
  8104. // update is written directly to a transaction's underlying write batch, the
  8105. // optimization should not apply.
  8106. SetUpTransactionDB();
  8107. bool commit_bypass_memtable = false;
  8108. SyncPoint::GetInstance()->SetCallBack(
  8109. "WriteCommittedTxn::CommitInternal:bypass_memtable",
  8110. [&](void* arg) { commit_bypass_memtable = *(static_cast<bool*>(arg)); });
  8111. SyncPoint::GetInstance()->EnableProcessing();
  8112. Random rnd(301);
  8113. {
  8114. WriteOptions wopts;
  8115. TransactionOptions txn_opts;
  8116. txn_opts.large_txn_commit_optimize_byte_threshold = 100;
  8117. auto txn = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  8118. ASSERT_OK(txn->SetName("xid0"));
  8119. ASSERT_OK(txn->Put("k1", rnd.RandomString(1000)));
  8120. // This update is written directly to the underlying write batch, so the
  8121. // optimization should not apply.
  8122. ASSERT_OK(txn->GetWriteBatch()->GetWriteBatch()->Put("meta", "1"));
  8123. ASSERT_OK(txn->Prepare());
  8124. ASSERT_OK(txn->Commit());
  8125. ASSERT_FALSE(commit_bypass_memtable);
  8126. ASSERT_EQ(Get("meta"), "1");
  8127. delete txn;
  8128. }
  8129. {
  8130. WriteOptions wopts;
  8131. TransactionOptions txn_opts;
  8132. txn_opts.large_txn_commit_optimize_threshold = 10;
  8133. auto txn = txn_db->BeginTransaction(wopts, txn_opts, nullptr);
  8134. ASSERT_OK(txn->SetName("xid0"));
  8135. for (int i = 0; i < 10; ++i) {
  8136. ASSERT_OK(txn->Put(Key(i), rnd.RandomString(10)));
  8137. }
  8138. // This update is written directly to the underlying write batch, so the
  8139. // optimization should not apply.
  8140. ASSERT_OK(txn->GetWriteBatch()->GetWriteBatch()->Put("meta", "2"));
  8141. ASSERT_OK(txn->Prepare());
  8142. ASSERT_OK(txn->Commit());
  8143. ASSERT_FALSE(commit_bypass_memtable);
  8144. ASSERT_EQ(Get("meta"), "2");
  8145. delete txn;
  8146. }
  8147. }
  8148. } // namespace ROCKSDB_NAMESPACE
  8149. int main(int argc, char** argv) {
  8150. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  8151. ::testing::InitGoogleTest(&argc, argv);
  8152. return RUN_ALL_TESTS();
  8153. }