+ indexExists <- doesDirectoryExist indexDir
+ when indexExists
+ $ removeDirectoryRecursive indexDir
+
+ revFileExists <- doesFileExist revFile
+ when revFileExists
+ $ removeFile revFile
+
+ Right db <- openDatabase indexDir (Writer [Create []])
+ noticeM logger ("Created an H.E. database on " ++ indexDir)
+
+ return db
+
+
+syncIndex :: Storage -> IO ()
+syncIndex sto
+ = updateIndexRev sto $ \ oldRev ->
+ do debugM logger ("The index revision is currently " ++ show oldRev)
+
+ newRev <- getCurrentRevNum sto
+ debugM logger ("The repository revision is currently " ++ show newRev)
+
+ when (newRev /= oldRev) (syncIndex' oldRev newRev)
+ return newRev
+ where
+ syncIndex' :: RevNum -> RevNum -> IO ()
+ syncIndex' oldRev newRev
+ = do pages <- findChangedPages sto oldRev newRev
+ mapM_ (updateIndex sto newRev) (S.toList pages)
+
+
+updateIndex :: Storage -> RevNum -> PageName -> IO ()
+updateIndex sto rev name
+ = do pageM <- getPage sto name (Just rev)
+ case pageM of
+ -- ページが削除された
+ Nothing
+ -> do docIdM <- getDocIdByURI (stoIndexDB sto) (mkRakkaURI name)
+ case docIdM of
+ Nothing -> return ()
+ Just docId -> do removeDocument (stoIndexDB sto) docId [CleaningRemove]
+ infoM logger ("Removed page " ++ name ++ " from the index")
+ Just page
+ -> do draft <- stoMakeDraft sto page
+ putDocument (stoIndexDB sto) draft [CleaningPut]
+ infoM logger ("Indexed page " ++ name ++ " of revision " ++ show (pageRevision page))
+
+
+updateIndexRev :: Storage -> (RevNum -> IO RevNum) -> IO ()
+updateIndexRev sto f = bracket acquireLock releaseLock update
+ where
+ acquireLock :: IO Fd
+ acquireLock
+ = do atomically $ do revLocked <- readTVar (stoIndexRevLocked sto)
+ if revLocked then
+ retry
+ else
+ writeTVar (stoIndexRevLocked sto) True
+ fd <- openFd (stoIndexRevFile sto) ReadWrite (Just stdFileMode) defaultFileFlags
+ waitToSetLock fd (WriteLock, AbsoluteSeek, 0, 0)
+ return fd
+
+ releaseLock :: Fd -> IO ()
+ releaseLock fd
+ = do setLock fd (Unlock, AbsoluteSeek, 0, 0)
+ atomically $ writeTVar (stoIndexRevLocked sto) False
+
+ update :: Fd -> IO ()
+ update fd
+ = do fdSeek fd AbsoluteSeek 0
+ size <- return . fromIntegral . fileSize =<< getFdStatus fd
+ (revStr, gotSize) <- fdRead fd size
+ when (size /= gotSize) $ fail ("read " ++ show gotSize ++
+ " bytes but expected " ++ show size ++ " bytes")
+
+ let rev = case revStr of
+ "" -> 0
+ _ -> read revStr
+
+ rev' <- f rev
+
+ let revStr' = show rev' ++ "\n"
+ size' = fromIntegral $ length revStr'
+
+ fdSeek fd AbsoluteSeek 0
+ setFdSize fd 0
+ wroteSize <- fdWrite fd revStr'
+ when (size' /= wroteSize) $ fail ("wrote " ++ show wroteSize ++
+ " bytes but expected " ++ show size' ++ " bytes")
\ No newline at end of file