/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 1 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠThis Ġis Ġa Ġmodern Ġvariant Ġof ĠJ ake ĠWh art on 's ĠDisk ĠL RU ĠCache Ġdeveloped Ġby ĠCol in ĠWhite Ċ Ġ* Ġ Ġwhich Ġis Ġtranslated Ġto ĠKotlin Ġwith Ġimproved ĠI / O Ġby ĠOk io Ġby Ġhim . Ċ Ġ* Ġ( Using Ġthis Ġto Ġnot Ġre invent Ġthe Ġwheel ) Ċ Ġ*/ Ċ Ċ package Ġio . pixel . loader . cache . disk Ċ Ċ import Ġio . pixel . loader . cache . disk . Disk LR U Cache . Editor Ċ import Ġok io .* Ċ import Ġjava . io .* Ċ import Ġjava . io . EOF Exception Ċ import Ġjava . io . IOException Ċ import Ġjava . util .* Ċ import Ġjava . util . concurrent . Linked BlockingQueue Ċ import Ġjava . util . concurrent . ThreadPoolExecutor Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ /** Ċ Ġ* ĠA Ġcache Ġthat Ġuses Ġa Ġbounded Ġamount Ġof Ġspace Ġon Ġa Ġfilesystem . ĠEach Ġcache Ċ Ġ* Ġentry Ġhas Ġa Ġstring Ġkey Ġand Ġa Ġfixed Ġnumber Ġof Ġvalues . ĠEach Ġkey Ġmust Ġmatch Ċ Ġ* Ġthe Ġregex Ġ**[ a - z 0 - 9 _- ]{ 1 , 1 2 0 } **. ĠValues Ġare Ġbyte Ġsequences , Ċ Ġ* Ġaccessible Ġas Ġstreams Ġor Ġfiles . ĠEach Ġvalue Ġmust Ġbe Ġbetween Ġ` 0 ` Ġand Ċ Ġ* Ġ` Integer . MAX _ VALUE ` Ġbytes Ġin Ġlength . Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠThe Ġcache Ġstores Ġits Ġdata Ġin Ġa Ġdirectory Ġon Ġthe Ġfilesystem . ĠThis Ċ Ġ* Ġdirectory Ġmust Ġbe Ġexclusive Ġto Ġthe Ġcache ; Ġthe Ġcache Ġmay Ġdelete Ġor Ġoverwrite Ċ Ġ* Ġfiles Ġfrom Ġits Ġdirectory . ĠIt Ġis Ġan Ġerror Ġfor Ġmultiple Ġprocesses Ġto Ġuse Ġthe Ċ Ġ* Ġsame Ġcache Ġdirectory Ġat Ġthe Ġsame Ġtime . Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠThis Ġcache Ġlimits Ġthe Ġnumber Ġof Ġbytes Ġthat Ġit Ġwill Ġstore Ġon Ġthe Ċ Ġ* Ġfilesystem . ĠWhen Ġthe Ġnumber Ġof Ġstored Ġbytes Ġexceeds Ġthe Ġlimit , Ġthe Ġcache Ġwill Ċ Ġ* Ġremove Ġentries Ġin Ġthe Ġbackground Ġuntil Ġthe Ġlimit Ġis Ġsatisfied . ĠThe Ġlimit Ġis Ċ Ġ* Ġnot Ġstrict : Ġthe Ġcache Ġmay Ġtemporarily Ġexceed Ġit Ġwhile Ġwaiting Ġfor Ġfiles Ġto Ġbe Ċ Ġ* Ġdeleted . ĠThe Ġlimit Ġdoes Ġnot Ġinclude Ġfilesystem Ġoverhead Ġor Ġthe Ġcache Ċ Ġ* Ġjournal Ġso Ġspace - sensitive Ġapplications Ġshould Ġset Ġa Ġcon serv ative Ġlimit . Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠClients Ġcall Ġ[. edit ] Ġto Ġcreate Ġor Ġupdate Ġthe Ġvalues Ġof Ġan Ġentry . ĠAn Ċ Ġ* Ġentry Ġmay Ġhave Ġonly Ġone Ġeditor Ġat Ġone Ġtime ; Ġif Ġa Ġvalue Ġis Ġnot Ġavailable Ġto Ġbe Ċ Ġ* Ġedited Ġthen Ġ[. edit ] Ġwill Ġreturn Ġnull . Ċ Ġ* Ċ Ġ* Ġ Ġ* ĠWhen Ġan Ġentry Ġis Ġbeing Ġ** created ** Ġit Ġis Ġnecessary Ġto Ċ Ġ* Ġsupply Ġa Ġfull Ġset Ġof Ġvalues ; Ġthe Ġempty Ġvalue Ġshould Ġbe Ġused Ġas Ġa Ċ Ġ* Ġplaceholder Ġif Ġnecessary . Ċ Ġ* Ġ Ġ* ĠWhen Ġan Ġentry Ġis Ġbeing Ġ** edited **, Ġit Ġis Ġnot Ġnecessary Ċ Ġ* Ġto Ġsupply Ġdata Ġfor Ġevery Ġvalue ; Ġvalues Ġdefault Ġto Ġtheir Ġprevious Ċ Ġ* Ġvalue . Ċ Ġ* Ċ Ġ* ĠEvery Ġ[. edit ] Ġcall Ġmust Ġbe Ġmatched Ġby Ġa Ġcall Ġto Ġ[ Editor . commit ] Ċ Ġ* Ġor Ġ[ Editor . abort ]. ĠCommit ting Ġis Ġatomic : Ġa Ġread Ġob serves Ġthe Ġfull Ġset Ċ Ġ* Ġof Ġvalues Ġas Ġthey Ġwere Ġbefore Ġor Ġafter Ġthe Ġcommit , Ġbut Ġnever Ġa Ġmix Ġof Ġvalues . Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠClients Ġcall Ġ[. get ] Ġto Ġread Ġa Ġsnapshot Ġof Ġan Ġentry . ĠThe Ġread Ġwill Ċ Ġ* Ġobserve Ġthe Ġvalue Ġat Ġthe Ġtime Ġthat Ġ[. get ] Ġwas Ġcalled . ĠUpdates Ġand Ċ Ġ* Ġremo vals Ġafter Ġthe Ġcall Ġdo Ġnot Ġimpact Ġongoing Ġreads . Ċ Ġ* Ċ Ġ* Ċ Ġ* ĠThis Ġclass Ġis Ġt oler ant Ġof Ġsome ĠI / O Ġerrors . ĠIf Ġfiles Ġare Ġmissing Ġfrom Ġthe Ċ Ġ* Ġfilesystem , Ġthe Ġcorresponding Ġentries Ġwill Ġbe Ġdropped Ġfrom Ġthe Ġcache . ĠIf Ċ Ġ* Ġan Ġerror Ġoccurs Ġwhile Ġwriting Ġa Ġcache Ġvalue , Ġthe Ġedit Ġwill Ġfail Ġsilently . Ċ Ġ* ĠCall ers Ġshould Ġhandle Ġother Ġproblems Ġby Ġcatch ing Ġ` IOException ` Ġand Ċ Ġ* Ġrespon ding Ġappropriately . Ċ Ġ*/ Ċ internal Ġclass ĠDisk LR U Cache Ġprivate Ġconstructor ( ĊĠĠĠ Ġval Ġdirectory : ĠFile , ĊĠĠĠ Ġprivate Ġval Ġapp Version : ĠInt , ĊĠĠĠ Ġprivate Ġval Ġvalue Count : ĠInt , ĊĠĠĠ Ġprivate Ġvar ĠmaxSize : ĠLong Ċ ) Ġ: ĠClose able Ġ{ ĊĊĠĠĠ Ġ/* ĊĠĠĠĠ Ġ* ĠThis Ġcache Ġuses Ġa Ġjournal Ġfile Ġnamed Ġ" journal ". ĠA Ġtypical Ġjournal Ġfile ĊĠĠĠĠ Ġ* Ġlooks Ġlike Ġthis : ĊĠĠĠĠ Ġ* ĠĠĠĠ Ġlib core . io . Disk L ru Cache ĊĠĠĠĠ Ġ* ĠĠĠĠĠ 1 ĊĠĠĠĠ Ġ* ĠĠĠĠĠ 1 0 0 ĊĠĠĠĠ Ġ* ĠĠĠĠĠ 2 ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠC LEAN Ġ 3 4 0 0 3 3 0 d 1 dfc 7 f 3 f 7 f 4 b 8 d 4 d 8 0 3 df cf 6 Ġ 8 3 2 Ġ 2 1 0 5 4 ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠDIR TY Ġ 3 3 5 c 4 c 6 0 2 8 1 7 1 cf dd fb aae 1 a 9 c 3 1 3 c 5 2 ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠC LEAN Ġ 3 3 5 c 4 c 6 0 2 8 1 7 1 cf dd fb aae 1 a 9 c 3 1 3 c 5 2 Ġ 3 9 3 4 Ġ 2 3 4 2 ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠREMOVE Ġ 3 3 5 c 4 c 6 0 2 8 1 7 1 cf dd fb aae 1 a 9 c 3 1 3 c 5 2 ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠDIR TY Ġ 1 ab 9 6 a 1 7 1 fa eeee 3 8 4 9 6 d 8 b 3 3 0 7 7 1 a 7 a ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠC LEAN Ġ 1 ab 9 6 a 1 7 1 fa eeee 3 8 4 9 6 d 8 b 3 3 0 7 7 1 a 7 a Ġ 1 6 0 0 Ġ 2 3 4 ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠREAD Ġ 3 3 5 c 4 c 6 0 2 8 1 7 1 cf dd fb aae 1 a 9 c 3 1 3 c 5 2 ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠREAD Ġ 3 4 0 0 3 3 0 d 1 dfc 7 f 3 f 7 f 4 b 8 d 4 d 8 0 3 df cf 6 ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThe Ġfirst Ġfive Ġlines Ġof Ġthe Ġjournal Ġform Ġits Ġheader . ĠThey Ġare Ġthe ĊĠĠĠĠ Ġ* Ġconstant Ġstring Ġ" lib core . io . Disk L ru Cache ", Ġthe Ġdisk Ġcache 's Ġversion , ĊĠĠĠĠ Ġ* Ġthe Ġapplication 's Ġversion , Ġthe Ġvalue Ġcount , Ġand Ġa Ġblank Ġline . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠEach Ġof Ġthe Ġsubsequent Ġlines Ġin Ġthe Ġfile Ġis Ġa Ġrecord Ġof Ġthe Ġstate Ġof Ġa ĊĠĠĠĠ Ġ* Ġcache Ġentry . ĠEach Ġline Ġcontains Ġspace - separated Ġvalues : Ġa Ġstate , Ġa Ġkey , ĊĠĠĠĠ Ġ* Ġand Ġoptional Ġstate - specific Ġvalues . ĊĠĠĠĠ Ġ* ĠĠ Ġo ĠDIR TY Ġlines Ġtrack Ġthat Ġan Ġentry Ġis Ġactively Ġbeing Ġcreated Ġor Ġupdated . ĊĠĠĠĠ Ġ* ĠĠĠĠ ĠEvery Ġsuccessful ĠDIR TY Ġaction Ġshould Ġbe Ġfollowed Ġby Ġa ĠC LEAN Ġor ĠREMOVE ĊĠĠĠĠ Ġ* ĠĠĠĠ Ġaction . ĠDIR TY Ġlines Ġwithout Ġa Ġmatching ĠC LEAN Ġor ĠREMOVE Ġindicate Ġthat ĊĠĠĠĠ Ġ* ĠĠĠĠ Ġtemporary Ġfiles Ġmay Ġneed Ġto Ġbe Ġdeleted . ĊĠĠĠĠ Ġ* ĠĠ Ġo ĠC LEAN Ġlines Ġtrack Ġa Ġcache Ġentry Ġthat Ġhas Ġbeen Ġsuccessfully Ġpublished ĊĠĠĠĠ Ġ* ĠĠĠĠ Ġand Ġmay Ġbe Ġread . ĠA Ġpublish Ġline Ġis Ġfollowed Ġby Ġthe Ġlengths Ġof Ġeach Ġof ĊĠĠĠĠ Ġ* ĠĠĠĠ Ġits Ġvalues . ĊĠĠĠĠ Ġ* ĠĠ Ġo ĠREAD Ġlines Ġtrack Ġaccesses Ġfor ĠL RU . ĊĠĠĠĠ Ġ* ĠĠ Ġo ĠREMOVE Ġlines Ġtrack Ġentries Ġthat Ġhave Ġbeen Ġdeleted . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThe Ġjournal Ġfile Ġis Ġappended Ġto Ġas Ġcache Ġoperations Ġoccur . ĠThe Ġjournal Ġmay ĊĠĠĠĠ Ġ* Ġoccasion ally Ġbe Ġcompact ed Ġby Ġdropping Ġredundant Ġlines . ĠA Ġtemporary Ġfile Ġnamed ĊĠĠĠĠ Ġ* Ġ" journal . tmp " Ġwill Ġbe Ġused Ġduring Ġcomp action ; Ġthat Ġfile Ġshould Ġbe Ġdeleted Ġif ĊĠĠĠĠ Ġ* Ġit Ġexists Ġwhen Ġthe Ġcache Ġis Ġopened . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġval Ġjournal File Ġ= ĠFile ( directory , ĠJ O URN AL _ FILE ) ĊĠĠĠ Ġprivate Ġval Ġjournal File Tmp Ġ= ĠFile ( directory , ĠJ O URN AL _ FILE _ TEMP ) ĊĠĠĠ Ġprivate Ġval Ġjournal File Backup Ġ= ĠFile ( directory , ĠJ O URN AL _ FILE _ BACKUP ) ĊĊĠĠĠ Ġprivate Ġval Ġl ru Entries Ġ= ĠLinkedHashMap < String , ĠEntry >( 0 , Ġ 0 . 7 5 f , Ġtrue ) ĊĊĠĠĠ Ġ/** ĠThis Ġcache Ġuses Ġa Ġsingle Ġbackground Ġthread Ġto Ġev ict Ġentries . Ġ*/ ĊĠĠĠ Ġprivate Ġval ĠexecutorService Ġ= ĊĠĠĠĠĠĠĠ ĠThreadPool Executor ( 0 , Ġ 1 , Ġ 6 0 L , ĠTimeUnit . SECONDS , ĠLinked BlockingQueue ()) ĊĊĠĠĠ Ġprivate Ġvar Ġjournal Writer : ĠBuffered Sink ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġredundant Op Count Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġsize Ġ= Ġ 0 L ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠTo Ġdifferent iate Ġbetween Ġold Ġand Ġcurrent Ġsnapshots , Ġeach Ġentry Ġis Ġgiven ĊĠĠĠĠ Ġ* Ġa Ġsequence Ġnumber Ġeach Ġtime Ġan Ġedit Ġis Ġcommitted . ĠA Ġsnapshot Ġis Ġstale Ġif ĊĠĠĠĠ Ġ* Ġits Ġsequence Ġnumber Ġis Ġnot Ġequal Ġto Ġits Ġentry 's Ġsequence Ġnumber . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġvar Ġnext SequenceNumber Ġ= Ġ 0 L ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġread Journal () Ġ{ ĊĠĠĠĠĠĠĠ Ġjournal File . source (). buffer (). use Ġ{ Ġreader Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmagic Ġ= Ġreader . read Utf 8 Line Strict () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġversion Ġ= Ġreader . read Utf 8 Line Strict () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġapp Version String Ġ= Ġreader . read Utf 8 Line Strict () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalue Count String Ġ= Ġreader . read Utf 8 Line Strict () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġblank Ġ= Ġreader . read Utf 8 Line Strict () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( MAGIC Ġ!= Ġmagic ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ|| ĠVERSION _ 1 Ġ!= Ġversion ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ|| Ġapp Version . toString () Ġ!= Ġapp Version String ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ|| Ġvalue Count . toString () Ġ!= Ġvalue Count String ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ|| Ġblank . isNotBlank () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Unexpected Ġjournal Ġheader : Ġ[$ magic , Ġ$ version , Ġ$ value Count String , Ġ$ blank ]") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġline Count Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġread Journal Line ( reader . read Utf 8 Line Strict ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġline Count ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignored : ĠEOF Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġredundant Op Count Ġ= Ġline Count Ġ- Ġl ru Entries . count () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġwe Ġended Ġon Ġa Ġtruncated Ġline , Ġrebuild Ġthe Ġjournal Ġbefore Ġapp ending Ġto Ġit . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! reader . ex hausted ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrebuild Journal () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġjournal Writer Ġ= Ġjournal File . append ing Sink (). buffer () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġread Journal Line ( line : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfirst Space Ġ= Ġline . indexOf (' Ġ') ĊĠĠĠĠĠĠĠ Ġif Ġ( first Space Ġ== Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Unexpected Ġjournal Ġline : Ġ$ line ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġkey Begin Ġ= Ġfirst Space Ġ+ Ġ 1 ĊĠĠĠĠĠĠĠ Ġval Ġsecond Space Ġ= Ġline . indexOf (' Ġ', Ġkey Begin ) ĊĠĠĠĠĠĠĠ Ġval Ġkey : ĠString ĊĠĠĠĠĠĠĠ Ġif Ġ( second Space Ġ== Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkey Ġ= Ġline . substring ( key Begin ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( first Space Ġ== ĠREMOVE . count () Ġ&& Ġline . startsWith ( REMOVE )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġl ru Entries . remove ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkey Ġ= Ġline . substring ( key Begin , Ġsecond Space ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġentry Ġ= Ġl ru Entries [ key ] Ġ?: ĠEntry ( key ). also Ġ{ Ġl ru Entries [ key ] Ġ= Ġit Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( second Space Ġ!= Ġ- 1 Ġ&& Ġfirst Space Ġ== ĠC LEAN . count () Ġ&& Ġline . startsWith ( CLEAN )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġparts Ġ= Ġline ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. substring ( second Space Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. split (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. drop Last While Ġ{ Ġit . isEmpty () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . readable Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . current Editor Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . set Lengths ( parts ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( second Space Ġ== Ġ- 1 Ġ&& Ġfirst Space Ġ== ĠDIR TY . count () Ġ&& Ġline . startsWith ( DIR TY )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . current Editor Ġ= ĠEditor ( entry ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( second Space Ġ== Ġ- 1 Ġ&& Ġfirst Space Ġ== ĠREAD . count () Ġ&& Ġline . startsWith ( READ )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠThis Ġwork Ġwas Ġalready Ġdone Ġby Ġcalling Ġl ru Entries . get (). ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Unexpected Ġjournal Ġline : Ġ$ line ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠComputes Ġthe Ġinitial Ġsize Ġand Ġcollect s Ġgarbage Ġas Ġa Ġpart Ġof Ġopening Ġthe ĊĠĠĠĠ Ġ* Ġcache . ĠDir ty Ġentries Ġare Ġassumed Ġto Ġbe Ġinconsistent Ġand Ġwill Ġbe Ġdeleted . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġprocess Journal () Ġ{ ĊĠĠĠĠĠĠĠ Ġjournal File Tmp . delete IfExists () ĊĊĠĠĠĠĠĠĠ Ġval Ġiterator Ġ= Ġl ru Entries . values . iterator () ĊĠĠĠĠĠĠĠ Ġwhile Ġ( iterator . hasNext ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġentry Ġ= Ġiterator . next () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry . current Editor Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsize Ġ+= Ġentry . lengths [ i ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . current Editor Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . get Clean File ( i ). delete IfExists () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . get Dirty File ( i ). delete IfExists () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġiterator . remove () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCreates Ġa Ġnew Ġjournal Ġthat Ġomit s Ġredundant Ġinformation . ĠThis Ġreplaces Ġthe ĊĠĠĠĠ Ġ* Ġcurrent Ġjournal Ġif Ġit Ġexists . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġrebuild Journal () Ġ{ ĊĠĠĠĠĠĠĠ Ġjournal Writer ?. close () ĊĊĠĠĠĠĠĠĠ Ġjournal File Tmp . sink (). buffer (). use Ġ{ Ġwriter Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( MAGIC ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( VERSION _ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( app Version . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( value Count . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ("\ n ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġl ru Entries . values . forEach Ġ{ Ġentry Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry . current Editor Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( DIR TY ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( entry . key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( CLEAN ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( entry . key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ( entry . getLength s String ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwriter . write Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( journal File . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġjournal File . rename To ( journal File Backup , Ġtrue ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġjournal File Tmp . rename To ( journal File , Ġfalse ) ĊĠĠĠĠĠĠĠ Ġjournal File Backup . delete () ĊĊĠĠĠĠĠĠĠ Ġjournal Writer Ġ= Ġjournal File . append ing Sink (). buffer () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġcleanup Journal () Ġ{ ĊĠĠĠĠĠĠĠ Ġjournal Writer Ġ?: Ġreturn Ġ// ĠClosed . ĊĠĠĠĠĠĠĠ Ġtrim To Size () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( journal Rebuild Required ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrebuild Journal () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġredundant Op Count Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġa Ġsnapshot Ġof Ġthe Ġentry Ġnamed Ġ` key `, Ġor Ġnull Ġif Ġit Ġdoesn 't ĊĠĠĠĠ Ġ* Ġexist Ġis Ġnot Ġcurrently Ġreadable . ĠIf Ġa Ġvalue Ġis Ġreturned , Ġit Ġis Ġmoved Ġto ĊĠĠĠĠ Ġ* Ġthe Ġhead Ġof Ġthe ĠL RU Ġqueue . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġoperator Ġfun Ġget ( key : ĠString ): ĠSnapshot ? Ġ{ ĊĠĠĠĠĠĠĠ Ġensure Not Closed () ĊĠĠĠĠĠĠĠ Ġvalidate Key ( key ) ĊĊĠĠĠĠĠĠĠ Ġval Ġentry Ġ= Ġl ru Entries [ key ]?. take If Ġ{ Ġit . readable Ġ} Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠ Ġ// ĠOpen Ġall Ġstreams Ġeager ly Ġto Ġguarantee Ġthat Ġwe Ġsee Ġa Ġsingle Ġpublished ĊĠĠĠĠĠĠĠ Ġ// Ġsnapshot . ĠIf Ġwe Ġopened Ġstreams Ġl az ily Ġthen Ġthe Ġstreams Ġcould Ġcome ĊĠĠĠĠĠĠĠ Ġ// Ġfrom Ġdifferent Ġedits . ĊĠĠĠĠĠĠĠ Ġval Ġinputs Ġ= ĠarrayOf Null s < Source >( value Count ) ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( index Ġin Ġ 0 Ġuntil Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinputs [ index ] Ġ= Ġentry . get Clean File ( index ). source () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠFileNotFoundException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠA Ġfile Ġmust Ġhave Ġbeen Ġdeleted Ġmanually ! ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( input Ġin Ġinputs ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinput ?. close Quiet ly () Ġ?: Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġredundant Op Count ++ ĊĠĠĠĠĠĠĠ Ġjournal Writer ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( READ ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( journal Rebuild Required ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠexecutorService . submit ( this :: cleanup Journal ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Suppress (" UN CHECK ED _ CAST ") ĊĠĠĠĠĠĠĠ Ġreturn ĠSnapshot ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkey Ġ= Ġkey , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsequence Number Ġ= Ġentry . sequence Number , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinputs Ġ= Ġinputs Ġas ĠArray < Source >, ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlengths Ġ= Ġentry . lengths ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġfun Ġedit ( key : ĠString ): ĠEditor ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġedit ( key , ĠANY _ SEQUENCE _ NUMBER ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġan Ġeditor Ġfor Ġthe Ġentry Ġnamed Ġ` key `, Ġor Ġnull Ġif Ġanother ĊĠĠĠĠ Ġ* Ġedit Ġis Ġin Ġprogress . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġedit ( key : ĠString , Ġexpected SequenceNumber : ĠLong ): ĠEditor ? Ġ{ ĊĠĠĠĠĠĠĠ Ġensure Not Closed () ĊĠĠĠĠĠĠĠ Ġvalidate Key ( key ) ĊĊĠĠĠĠĠĠĠ Ġvar Ġentry : ĠEntry ? Ġ= Ġl ru Entries [ key ] ĊĠĠĠĠĠĠĠ Ġif Ġ( expected SequenceNumber Ġ!= ĠANY _ SEQUENCE _ NUMBER Ġ&& Ġ( entry Ġ== Ġnull Ġ|| Ġentry . sequence Number Ġ!= Ġexpected SequenceNumber )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull Ġ// ĠSnapshot Ġis Ġstale . ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( entry Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry Ġ= ĠEntry ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġl ru Entries [ key ] Ġ= Ġentry ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( entry . current Editor Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull Ġ// ĠAnother Ġedit Ġis Ġin Ġprogress . ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġeditor Ġ= ĠEditor ( entry ) ĊĠĠĠĠĠĠĠ Ġentry . current Editor Ġ= Ġeditor ĊĊĠĠĠĠĠĠĠ Ġ// ĠFlush Ġthe Ġjournal Ġbefore Ġcreating Ġfiles Ġto Ġprevent Ġfile Ġle aks . ĊĠĠĠĠĠĠĠ Ġjournal Writer ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( DIR TY ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġflush () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġeditor ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġthe Ġmaximum Ġnumber Ġof Ġbytes Ġthat Ġthis Ġcache Ġshould Ġuse Ġto Ġstore ĊĠĠĠĠ Ġ* Ġits Ġdata . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġget MaxSize (): ĠLong Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠmaxSize ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠChanges Ġthe Ġmaximum Ġnumber Ġof Ġbytes Ġthe Ġcache Ġcan Ġstore Ġand Ġqueues Ġa Ġjob ĊĠĠĠĠ Ġ* Ġto Ġtrim Ġthe Ġexisting Ġstore , Ġif Ġnecessary . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġset MaxSize ( maxSize : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . maxSize Ġ= ĠmaxSize ĊĠĠĠĠĠĠĠ ĠexecutorService . submit ( this :: cleanup Journal ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturns Ġthe Ġnumber Ġof Ġbytes Ġcurrently Ġbeing Ġused Ġto Ġstore Ġthe Ġvalues Ġin ĊĠĠĠĠ Ġ* Ġthis Ġcache . ĠThis Ġmay Ġbe Ġgreater Ġthan Ġthe Ġmax Ġsize Ġif Ġa Ġbackground ĊĠĠĠĠ Ġ* Ġdeletion Ġis Ġpending . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġsize (): ĠLong Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġsize ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠReturns Ġtrue Ġif Ġthis Ġcache Ġhas Ġbeen Ġclosed . Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġfun Ġis Closed (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġjournal Writer Ġ== Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġcomplete Edit ( editor : ĠEditor , Ġsuccess : ĠBoolean ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġentry Ġ= Ġeditor . entry ĊĠĠĠĠĠĠĠ Ġif Ġ( entry . current Editor Ġ!= Ġeditor ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠIf Ġthis Ġedit Ġis Ġcreating Ġthe Ġentry Ġfor Ġthe Ġfirst Ġtime , Ġevery Ġindex Ġmust Ġhave Ġa Ġvalue . ĊĠĠĠĠĠĠĠ Ġif Ġ( success Ġ&& Ġ! entry . readable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( editor . written ?. get ( i ) Ġ!= Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġeditor . abort () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException (" New ly Ġcreated Ġentry Ġdidn 't Ġcreate Ġvalue Ġfor Ġindex Ġ$ i .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! entry . get Dirty File ( i ). exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġeditor . abort () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdirty Ġ= Ġentry . get Dirty File ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( success ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( dirty . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġclean Ġ= Ġentry . get Clean File ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdirty . rename To ( clean ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġold Length Ġ= Ġentry . lengths [ i ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Length Ġ= Ġclean . length () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . lengths [ i ] Ġ= Ġnew Length ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsize Ġ= Ġsize Ġ- Ġold Length Ġ+ Ġnew Length ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdirty . delete IfExists () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġredundant Op Count ++ ĊĠĠĠĠĠĠĠ Ġentry . current Editor Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġif Ġ( entry . readable Ġor Ġsuccess ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . readable Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġjournal Writer ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( CLEAN ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( entry . key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( entry . getLength s String ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( success ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . sequence Number Ġ= Ġnext SequenceNumber ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġl ru Entries . remove ( entry . key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġjournal Writer ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( REMOVE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( entry . key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġjournal Writer ?. flush () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( size Ġ> ĠmaxSize Ġ|| Ġjournal Rebuild Required ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠexecutorService . submit ( this :: cleanup Journal ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠD rops Ġthe Ġentry Ġfor Ġ` key ` Ġif Ġit Ġexists Ġand Ġcan Ġbe Ġremoved . ĠEnt ries ĊĠĠĠĠ Ġ* Ġactively Ġbeing Ġedited Ġcannot Ġbe Ġremoved . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ return Ġtrue Ġif Ġan Ġentry Ġwas Ġremoved . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġfun Ġremove ( key : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġensure Not Closed () ĊĠĠĠĠĠĠĠ Ġvalidate Key ( key ) ĊĊĠĠĠĠĠĠĠ Ġval Ġentry Ġ= Ġl ru Entries [ key ] ĊĠĠĠĠĠĠĠ Ġif Ġ( entry Ġ== Ġnull Ġ|| Ġentry . current Editor Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= Ġentry . get Clean File ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( file . exists () Ġ&& Ġ! file . delete ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException (" Failed Ġto Ġdelete Ġ$ file !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġsize Ġ-= Ġentry . lengths [ i ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . lengths [ i ] Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġredundant Op Count ++ ĊĠĠĠĠĠĠĠ Ġjournal Writer ?. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( REMOVE ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 (" Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite Utf 8 ("\ n ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġl ru Entries . remove ( key ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( journal Rebuild Required ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠexecutorService . submit ( this :: cleanup Journal ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠForce Ġbuffered Ġoperations Ġto Ġthe Ġfilesystem . Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġfun Ġflush () Ġ{ ĊĠĠĠĠĠĠĠ Ġensure Not Closed () ĊĠĠĠĠĠĠĠ Ġtrim To Size () ĊĠĠĠĠĠĠĠ Ġjournal Writer ?. flush () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠCloses Ġthis Ġcache . ĠStored Ġvalues Ġwill Ġremain Ġon Ġthe Ġfilesystem . Ġ*/ ĊĠĠĠ Ġ@ Synchron ized ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġoverride Ġfun Ġclose () Ġ{ ĊĠĠĠĠĠĠĠ Ġjournal Writer Ġ?: Ġreturn Ġ// ĠAlready Ġclosed . ĊĠĠĠĠĠĠĠ Ġl ru Entries . values . forEach Ġ{ Ġentry Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentry . current Editor ?. abort () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġtrim To Size () ĊĠĠĠĠĠĠĠ Ġjournal Writer ?. close () ĊĠĠĠĠĠĠĠ Ġjournal Writer Ġ= Ġnull ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCloses Ġthe Ġcache Ġand Ġdeletes Ġall Ġof Ġits Ġstored Ġvalues . ĠThis Ġwill Ġdelete ĊĠĠĠĠ Ġ* Ġall Ġfiles Ġin Ġthe Ġcache Ġdirectory Ġincluding Ġfiles Ġthat Ġweren 't Ġcreated Ġby ĊĠĠĠĠ Ġ* Ġthe Ġcache . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġfun Ġdelete () Ġ{ ĊĠĠĠĠĠĠĠ Ġclose () ĊĠĠĠĠĠĠĠ Ġdirectory . delete Directory () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġensure Not Closed () Ġ{ ĊĠĠĠĠĠĠĠ Ġjournal Writer Ġ?: Ġthrow ĠIllegalStateException (" Cache Ġis Ġclosed !") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġtrim To Size () Ġ{ ĊĠĠĠĠĠĠĠ Ġwhile Ġ( size Ġ> ĠmaxSize ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremove ( lru Entries . entries . iterator (). next (). key ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWe Ġonly Ġrebuild Ġthe Ġjournal Ġwhen Ġit Ġwill Ġhal ve Ġthe Ġsize Ġof Ġthe Ġjournal ĊĠĠĠĠ Ġ* Ġand Ġeliminate Ġat Ġleast Ġ 2 0 0 0 Ġops . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġjournal Rebuild Required (): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġredundant Op Count Ġ>= Ġ 2 0 0 0 Ġ&& Ġredundant Op Count Ġ>= Ġl ru Entries . count () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Key ( key : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! LEG AL _ KEY _ PATTERN . matches ( key )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" Keys Ġmust Ġmatch Ġregex Ġ$ STRING _ KEY _ PATTERN : Ġ\"$ key \" ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠA Ġsnapshot Ġof Ġthe Ġvalues Ġfor Ġan Ġentry . Ġ*/ ĊĠĠĠ Ġinner Ġclass ĠSnapshot ( ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġkey : ĠString , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġsequence Number : ĠLong , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġinputs : ĠArray < Source >, ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġlengths : ĠLong Array ĊĠĠĠ Ġ) Ġ: ĠClose able Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġan Ġeditor Ġfor Ġthis Ġsnapshot 's Ġentry , Ġor Ġnull Ġif Ġeither Ġthe ĊĠĠĠĠĠĠĠĠ Ġ* Ġentry Ġhas Ġchanged Ġsince Ġthis Ġsnapshot Ġwas Ġcreated Ġor Ġif Ġanother Ġedit ĊĠĠĠĠĠĠĠĠ Ġ* Ġis Ġin Ġprogress . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġedit (): ĠEditor ? Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis @ Disk LR U Cache . edit ( key , Ġsequence Number ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĠReturns Ġthe Ġun buffered Ġstream Ġwith Ġthe Ġvalue Ġfor Ġ` index `. Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġget Source ( index : ĠInt ): ĠSource Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġinputs [ index ] ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĠReturns Ġthe Ġstring Ġvalue Ġfor Ġ` index `. Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun ĠgetString ( index : ĠInt ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġget Source ( index ). buffer (). readString ( Charsets . UTF _ 8 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĠReturns Ġthe Ġbyte Ġlength Ġof Ġthe Ġvalue Ġfor Ġ` index `. Ġ*/ ĊĠĠĠĠĠĠĠ Ġfun Ġget Length ( index : ĠInt ): ĠLong Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġlengths [ index ] ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġclose () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinputs . forEach Ġ{ Ġit . close Quiet ly () Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠEd its Ġthe Ġvalues Ġfor Ġan Ġentry . Ġ*/ ĊĠĠĠ Ġinner Ġclass ĠEditor Ġinternal Ġconstructor ( ĊĠĠĠĠĠĠĠ Ġinternal Ġval Ġentry : ĠEntry ĊĠĠĠ Ġ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġwritten Ġ= Ġif Ġ( entry . readable ) Ġnull Ġelse ĠBoolean Array ( value Count ) ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġhas Errors Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġcommitted Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġthe Ġlast Ġcommitted Ġvalue Ġas Ġa Ġstring , Ġor Ġnull Ġif Ġno Ġvalue ĊĠĠĠĠĠĠĠĠ Ġ* Ġhas Ġbeen Ġcommitted . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun ĠgetString ( index : ĠInt ): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnew Source ( index )?. buffer ()?. readString ( Charsets . UTF _ 8 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĠSets Ġthe Ġvalue Ġat Ġ` index ` Ġto Ġ` value `. Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġset String ( index : ĠInt , Ġvalue : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnew Sink ( index ). buffer (). use Ġ{ Ġit . write Utf 8 ( value ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġan Ġun buffered Ġinput Ġstream Ġto Ġread Ġthe Ġlast Ġcommitted Ġvalue , ĊĠĠĠĠĠĠĠĠ Ġ* Ġor Ġnull Ġif Ġno Ġvalue Ġhas Ġbeen Ġcommitted . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġnew Source ( index : ĠInt ): ĠSource ? Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalidate Index ( index ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġsynchronized ( this @ Disk LR U Cache ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry . current Editor Ġ!= Ġthis ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! entry . readable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġentry . get Clean File ( index ). source () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠFileNotFoundException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠReturns Ġa Ġnew Ġun buffered Ġoutput Ġstream Ġto Ġwrite Ġthe Ġvalue Ġat ĊĠĠĠĠĠĠĠĠ Ġ* Ġ` index `. ĠIf Ġthe Ġunderlying Ġoutput Ġstream Ġencounter s Ġerrors ĊĠĠĠĠĠĠĠĠ Ġ* Ġwhen Ġwriting Ġto Ġthe Ġfilesystem , Ġthis Ġedit Ġwill Ġbe Ġaborted Ġwhen ĊĠĠĠĠĠĠĠĠ Ġ* Ġ[. commit ] Ġis Ġcalled . ĠThe Ġreturned Ġoutput Ġstream Ġdoes Ġnot Ġthrow ĊĠĠĠĠĠĠĠĠ Ġ* ĠIOException s . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġnew Sink ( index : ĠInt ): ĠS ink Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalidate Index ( index ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġsynchronized ( this @ Disk LR U Cache ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( entry . current Editor Ġ!= Ġthis ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalStateException () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! entry . readable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwritten ?. set ( index , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdirty File Ġ= Ġentry . get Dirty File ( index ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsink Ġ= Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdirty File . sink () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignored : ĠFileNotFoundException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAttempt Ġto Ġrecreate Ġthe Ġcache Ġdirectory . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdirectory . mkdir s () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdirty File . sink () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignored : ĠFileNotFoundException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġare Ġunable Ġto Ġrecover . ĠSil ently Ġeat Ġthe Ġwrites . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġblack hole Sink () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠFault H iding Sink ( sink ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠCommit s Ġthis Ġedit Ġso Ġit Ġis Ġvisible Ġto Ġreaders . Ġ ĠThis Ġreleases Ġthe ĊĠĠĠĠĠĠĠĠ Ġ* Ġedit Ġlock Ġso Ġanother Ġedit Ġmay Ġbe Ġstarted Ġon Ġthe Ġsame Ġkey . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġcommit () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( has Errors ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomplete Edit ( this , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremove ( entry . key ) Ġ// ĠThe Ġprevious Ġentry Ġis Ġstale . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomplete Edit ( this , Ġtrue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcommitted Ġ= Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠAbort s Ġthis Ġedit . ĠThis Ġreleases Ġthe Ġedit Ġlock Ġso Ġanother Ġedit Ġmay Ġbe ĊĠĠĠĠĠĠĠĠ Ġ* Ġstarted Ġon Ġthe Ġsame Ġkey . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġabort () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcomplete Edit ( this , Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġabort Unless Commit ted () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! committed ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġabort () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( ignored : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġvalidate Index ( index : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( index Ġ< Ġ 0 Ġ|| Ġindex Ġ>= Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" Expected Ġindex Ġ$ index Ġto Ġbe Ġgreater Ġthan Ġ 0 Ġand Ġless Ġthan Ġthe Ġmaximum Ġvalue Ġcount Ġof Ġ$ value Count .") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġinner Ġclass ĠFault H iding Sink ( private Ġval Ġoutput : ĠS ink ) Ġ: ĠS ink Ġby Ġoutput Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġwrite ( source : ĠBuffer , Ġbyte Count : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput . write ( source , Ġbyte Count ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhas Errors Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġflush () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput . flush () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhas Errors Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġclose () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhas Errors Ġ= Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinternal Ġinner Ġclass ĠEntry ( val Ġkey : ĠString ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġ/** ĠLength s Ġof Ġthis Ġentry 's Ġfiles . Ġ*/ ĊĠĠĠĠĠĠĠ Ġval Ġlengths Ġ= ĠLong Array ( value Count ) ĊĊĠĠĠĠĠĠĠ Ġ/** ĠTrue Ġif Ġthis Ġentry Ġhas Ġever Ġbeen Ġpublished . Ġ*/ ĊĠĠĠĠĠĠĠ Ġvar Ġreadable Ġ= Ġfalse ĊĊĠĠĠĠĠĠĠ Ġ/** ĠThe Ġongoing Ġedit Ġor Ġnull Ġif Ġthis Ġentry Ġis Ġnot Ġbeing Ġedited . Ġ*/ ĊĠĠĠĠĠĠĠ Ġvar Ġcurrent Editor : ĠEditor ? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġ/** ĠThe Ġsequence Ġnumber Ġof Ġthe Ġmost Ġrecently Ġcommitted Ġedit Ġto Ġthis Ġentry . Ġ*/ ĊĠĠĠĠĠĠĠ Ġvar Ġsequence Number Ġ= Ġ 0 L ĊĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġget Lengths String (): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġlengths . join ToString (" Ġ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ/** ĠSet Ġlengths Ġusing Ġdecimal Ġnumbers Ġlike Ġ" 1 0 1 2 3 ". Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġset Lengths ( strings : ĠList < String >) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( strings . count () Ġ!= Ġvalue Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġinvalid Lengths ( strings ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstrings . forEach Indexed Ġ{ Ġindex , Ġvalue Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlengths [ index ] Ġ= Ġvalue . to Long () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠNumber FormatException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġinvalid Lengths ( strings ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġget Clean File ( index : ĠInt ): ĠFile Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠFile ( directory , Ġ"$ key .$ index ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġget Dirty File ( index : ĠInt ): ĠFile Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠFile ( directory , Ġ"$ key .$ index . tmp ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġinvalid Lengths ( strings : ĠList < String >): ĠIOException Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIOException ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Unexpected Ġjournal Ġline : Ġ${ strings . to Typed Array (). content ToString () }" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠC LEAN Ġ= Ġ" CLEAN " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠDIR TY Ġ= Ġ" DIR TY " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠREMOVE Ġ= Ġ" REMOVE " ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠREAD Ġ= Ġ" READ " ĊĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠJ O URN AL _ FILE Ġ= Ġ" journal " ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠJ O URN AL _ FILE _ TEMP Ġ= Ġ" journal . tmp " ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠJ O URN AL _ FILE _ BACKUP Ġ= Ġ" journal . bk p " ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠMAG IC Ġ= Ġ" lib core . io . Disk L ru Cache " ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠVERSION _ 1 Ġ= Ġ" 1 " ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠANY _ SEQUENCE _ NUMBER Ġ= Ġ- 1 L ĊĠĠĠĠĠĠĠ Ġinternal Ġconst Ġval ĠSTRING _ KEY _ PATTERN Ġ= Ġ"[ a - z 0 - 9 _- ]{ 1 , 1 2 0 }" ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠLE G AL _ KEY _ PATTERN Ġ= ĠSTRING _ KEY _ PATTERN . to Regex () ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠOpen s Ġthe Ġcache Ġin Ġ` directory `, Ġcreating Ġa Ġcache Ġif Ġnone Ġexists ĊĠĠĠĠĠĠĠĠ Ġ* Ġthere . ĊĠĠĠĠĠĠĠĠ Ġ* ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġdirectory Ġa Ġwritable Ġdirectory ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param Ġvalue Count Ġthe Ġnumber Ġof Ġvalues Ġper Ġcache Ġentry . ĠMust Ġbe Ġpositive . ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ param ĠmaxSize Ġthe Ġmaximum Ġnumber Ġof Ġbytes Ġthis Ġcache Ġshould Ġuse Ġto Ġstore ĊĠĠĠĠĠĠĠĠ Ġ* Ġ@ throws ĠIOException Ġif Ġreading Ġor Ġwriting Ġthe Ġcache Ġdirectory Ġfails ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠĠĠĠĠ Ġfun Ġopen ( directory : ĠFile , Ġapp Version : ĠInt , Ġvalue Count : ĠInt , ĠmaxSize : ĠLong ): ĠDisk LR U Cache Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( maxSize Ġ<= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" maxSize Ġ<= Ġ 0 ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( value Count Ġ<= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException (" value Count Ġ<= Ġ 0 ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġa Ġb kp Ġfile Ġexists , Ġuse Ġit Ġinstead . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbackup File Ġ= ĠFile ( directory , ĠJ O URN AL _ FILE _ BACKUP ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( backup File . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġjournal File Ġ= ĠFile ( directory , ĠJ O URN AL _ FILE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġjournal Ġfile Ġalso Ġexists Ġjust Ġdelete Ġbackup Ġfile . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( journal File . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbackup File . delete () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbackup File . rename To ( journal File , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠP refer Ġto Ġpick Ġup Ġwhere Ġwe Ġleft Ġoff . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġcache Ġ= ĠDisk LR U Cache ( directory , Ġapp Version , Ġvalue Count , ĠmaxSize ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( cache . journal File . exists ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcache . read Journal () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcache . process Journal () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcache ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( journal Is Cor rupt : ĠIOException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Disk L ru Cache Ġ$ directory Ġis Ġcorrupt : Ġ${ journal Is Cor rupt . message }, Ġremoving .") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcache . delete () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠCreate Ġa Ġnew Ġempty Ġcache . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdirectory . mkdir s () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcache Ġ= ĠDisk LR U Cache ( directory , Ġapp Version , Ġvalue Count , ĠmaxSize ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcache . rebuild Journal () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcache ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ