package Ġcom . pr 0 gram m . app . services Ċ Ċ import Ġandroid . content . Context Ċ import Ġcom . pr 0 gram m . app . Logger Ċ import Ġcom . pr 0 gram m . app . time Ċ import Ġcom . pr 0 gram m . app . util . do In Background Ċ import Ġcom . pr 0 gram m . app . util . read Stream Ċ import Ġcom . pr 0 gram m . app . util . unsigned Ċ import Ġjava . io . ByteArray InputStream Ċ import Ġjava . io . ByteArray OutputStream Ċ import Ġjava . io . File Ċ import Ġjava . io . Random Access File Ċ import Ġjava . nio . ByteBuffer Ċ import Ġjava . nio . channels . Channels Ċ import Ġjava . nio . channels . File Channel Ċ import Ġjava . util . concurrent . atomic . Atomic Reference Ċ import Ġjava . util . zip . De flater Ċ import Ġjava . util . zip . De flater OutputStream Ċ import Ġjava . util . zip . Inflater InputStream Ċ import Ġkotlin . experimental . or ĊĊ Ċ /** Ċ Ġ* ĠVery Ġsimple Ġservice Ġto Ġcheck Ġif Ġan Ġitem Ġwas Ġalready Ġvisited Ġor Ġnot . Ċ Ġ*/ Ċ Ċ class ĠSe en Service ( context : ĠContext ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġlock Ġ= ĠAny () ĊĠĠĠ Ġprivate Ġval Ġbuffer Ġ= ĠAtomic Reference < ByteBuffer >() ĊĊĠĠĠ Ġprivate Ġval Ġlogger Ġ= ĠLogger (" Seen Service ") ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġdo In Background Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ( context . files Dir , Ġ" seen - posts . bits ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer . set ( map ByteBuffer ( file )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( error : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn (" Could Ġnot Ġload Ġthe Ġseen - Cache ", Ġerror ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġis Seen ( id : ĠLong ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= Ġthis . buffer . get () Ġ?: Ġreturn Ġfalse ĊĊĠĠĠĠĠĠĠ Ġval Ġidx Ġ= Ġid . toInt () Ġ/ Ġ 8 ĊĠĠĠĠĠĠĠ Ġif Ġ( idx Ġ< Ġ 0 Ġ|| Ġidx Ġ>= Ġbuffer . limit ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn Ġ{ Ġ" Id Ġis Ġtoo Ġlarge " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmask Ġ= Ġ 1 Ġshl Ġ( 7 Ġ- Ġid Ġ% Ġ 8 ). toInt () ĊĠĠĠĠĠĠĠ Ġreturn Ġ( buffer . get ( idx ). unsigned Ġand Ġmask ) Ġ!= Ġ 0 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġmark As Seen ( id : ĠLong ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= Ġbuffer . get () Ġ?: Ġreturn ĊĊĠĠĠĠĠĠĠ Ġval Ġidx Ġ= Ġid . toInt () Ġ/ Ġ 8 ĊĠĠĠĠĠĠĠ Ġif Ġ( idx Ġ< Ġ 0 Ġ|| Ġidx Ġ>= Ġbuffer . limit ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn Ġ{ Ġ" Id Ġis Ġtoo Ġlarge " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// Ġonly Ġone Ġthread Ġcan Ġwrite Ġthe Ġbuffer Ġat Ġa Ġtime . ĊĠĠĠĠĠĠĠ Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalue Ġ= Ġbuffer . get ( idx ). unsigned ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġupdated Value Ġ= Ġvalue Ġor Ġ( 1 Ġshl Ġ( 7 Ġ- Ġid . toInt () Ġ% Ġ 8 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer . put ( idx , Ġupdated Value . to Byte ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠRemoves Ġthe Ġ" marked Ġas Ġseen " Ġstatus Ġfrom Ġall Ġitems . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġclear () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= Ġthis . buffer . get () Ġ?: Ġreturn ĊĊĠĠĠĠĠĠĠ Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Removing Ġall Ġthe Ġitems " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( idx Ġin Ġ 0 Ġuntil Ġbuffer . limit ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer . put ( idx , Ġ 0 . to Byte ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠMerge s Ġthe Ġother Ġvalue Ġinto Ġthis Ġone . ĠReturns Ġtrue , Ġif Ġthe ĊĠĠĠ Ġ// Ġother Ġvalue Ġequals Ġthe Ġcurrent Ġstate Ġand Ġno Ġmerging ĊĠĠĠ Ġ// Ġwas Ġneeded Ġat Ġall . ĊĠĠĠ Ġfun Ġcheck Equal And Merge ( other : ĠByteArray ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= Ġthis . buffer . get () Ġ?: Ġreturn Ġfalse ĊĊĠĠĠĠĠĠĠ Ġvar Ġtotal Count Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġvar Ġdiff Count Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . time (" Mer ging Ġvalues ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByteArrayInputStream ( other ). use Ġ{ Ġbi Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠIn flater InputStream ( bi ). use Ġ{ Ġinput Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsource Ġ= Ġbuffer . duplicate () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtarget Ġ= Ġbuffer . duplicate () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġread Stream ( input ) Ġ{ Ġbytes , Ġread Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstep Size Ġ= Ġread . coerce At Most ( source . remaining ()) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġupdated In Step Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( idx Ġin Ġ 0 Ġuntil Ġstep Size ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġother Value Ġ= Ġbytes [ idx ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprevious Value Ġ= Ġsource . get () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmerged Value Ġ= Ġother Value Ġor Ġprevious Value ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( previous Value Ġ!= Ġmerged Value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbytes [ idx ] Ġ= Ġmerged Value ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġupdated In Step ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( previous Value Ġ!= Ġother Value ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġcould Ġalso Ġbe Ġa Ġlocal Ġchange ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdiff Count ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( updated In Step Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget . put ( bytes , Ġ 0 , Ġstep Size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget . position ( target . position () Ġ+ Ġstep Size ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtotal Count Ġ+= Ġstep Size ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Changes Ġin Ġ$ diff Count Ġout Ġof Ġ$ total Count Ġbytes Ġin Ġseen Ġcache " Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġdiff Count Ġ== Ġ 0 Ġ&& Ġtotal Count Ġ== Ġbuffer . limit () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWork around Ġto Ġreset Ġthe Ġlower Ġn Ġbytes . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġclear Up To ( n : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= Ġthis . buffer . get () Ġ?: Ġreturn ĊĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Setting Ġthe Ġfirst Ġ$ n Ġbits Ġto Ġzero ." Ġ} ĊĊĠĠĠĠĠĠĠ Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( idx Ġin Ġ 0 Ġuntil Ġn . coerce At Most ( buffer . limit ())) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer . put ( idx , Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġexport (): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= Ġthis . buffer . get () Ġ?: Ġreturn Ġbyte ArrayOf () ĊĊĠĠĠĠĠĠĠ Ġreturn Ġsynchronized ( lock ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . time (" Export Ġvalues ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠByteArrayOutputStream (). use Ġ{ Ġbo Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDe flater ( De flater . BEST _ COMPRESS ION ). let Ġ{ Ġdef Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDe flater OutputStream ( bo , Ġdef ). use Ġ{ Ġout Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwrite Ġthe Ġbuffer Ġto Ġthe Ġstream ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠChannels . new Channel ( out ). write ( buffer . as ReadOnly Buffer ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdef . end () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbo . toByteArray () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠMaps Ġthe Ġcache Ġinto Ġa Ġbyte Ġbuffer . ĠThe Ġbuffer Ġis Ġbacked Ġby Ġthe Ġfile , Ġso ĊĠĠĠĠ Ġ* Ġall Ġchanges Ġto Ġthe Ġbuffer Ġare Ġwritten Ġback Ġto Ġthe Ġfile . ĊĊĠĠĠĠ Ġ* Ġ@ param Ġfile ĠThe Ġfile Ġto Ġmap Ġinto Ġmemory ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġmap ByteBuffer ( file : ĠFile ): ĠByteBuffer Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġspace Ġfor Ġup Ġto Ġa Ġfew Ġmillion Ġposts ĊĠĠĠĠĠĠĠ Ġval Ġsize Ġ= Ġ( 6 0 0 0 0 0 0 Ġ/ Ġ 8 ). to Long () ĊĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Mapping Ġcache : Ġ$ file " Ġ} ĊĠĠĠĠĠĠĠ ĠRandom Access File ( file , Ġ" rw "). use Ġ{ Ġr af Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġr af . set Length ( size ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġr af . channel . map ( File Channel . Map Mode . READ _ WRITE , Ġ 0 , Ġsize ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ