import Control.Concurrent
import Control.Concurrent.STM
+import Control.Exception
import Control.Monad
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as S
+import Data.Time
import Network.HTTP.Lucu
import Network.HTTP.Lucu.Utils
import Network.URI
import Rakka.Storage.DefaultPage
import Rakka.Storage.Repos
import Rakka.Storage.Types
+import Rakka.W3CDateTime
import Subversion.Types
import Subversion.FileSystem
import Subversion.Repository
findChangedPages :: Repository -> RevNum -> RevNum -> IO (Set PageName)
findChangedPages repos 0 newRev = findAllPages repos newRev
findChangedPages repos oldRev newRev
- = mapM (findChangedPagesAtRevision repos) [oldRev + 1 .. newRev]
- >>=
- return . S.unions
+ = liftM S.unions (mapM (findChangedPagesAtRevision repos) [oldRev + 1 .. newRev])
getDirContents' :: Repository -> PageName -> Maybe RevNum -> IO [PageName]
startIndexManager lsdir repos mkDraft
= do chan <- newTChanIO
index <- openIndex indexDir revFile
- forkIO (loop chan index)
+ _ <- forkIO (loop chan index `finally` closeDatabase index)
return chan
where
indexDir = lsdir </> "index"
$ removeFile revFile
Right index <- openDatabase indexDir (Writer [Create []])
+ addAttrIndex index "@mdate" SeqIndex
addAttrIndex index "@type" StrIndex
addAttrIndex index "@uri" SeqIndex
addAttrIndex index "rakka:revision" SeqIndex
mapM_ (updateIndex index repos mkDraft newRev) (S.toList pages)
-searchIndex :: Database -> Condition -> IO [SearchResult]
+searchIndex :: Database -> Condition -> IO SearchResult
searchIndex index cond
= do (ids, hint) <- searchDatabase' index cond
- mapM (fromId $ map fst hint) ids
+ let (total, words) = parseHint hint
+ pages <- mapM (fromId words) ids
+ return SearchResult {
+ srTotal = total
+ , srPages = pages
+ }
where
- fromId :: [String] -> DocumentID -> IO SearchResult
+ parseHint :: [(String, Int)] -> (Int, [String])
+ parseHint xs
+ = let total = fromJust $ lookup "" xs
+ words = filter (/= "") $ map fst xs
+ in
+ (total, words)
+
+ fromId :: [String] -> DocumentID -> IO HitPage
fromId words docId
= do uri <- getDocURI index docId
- rev <- getDocAttr index docId "rakka:revision"
- >>= return . read . fromJust
+ rev <- unsafeInterleaveIO $
+ liftM (read . fromJust)
+ (getDocAttr index docId "rakka:revision")
+ lastMod <- unsafeInterleaveIO $
+ liftM (zonedTimeToUTC . fromJust . parseW3CDateTime . fromJust)
+ (getDocAttr index docId "@mdate")
+ summary <- unsafeInterleaveIO $
+ getDocAttr index docId "rakka:summary"
snippet <- unsafeInterleaveIO $
do doc <- getDocument index docId [NoAttributes, NoKeywords]
sn <- makeSnippet doc words 300 80 80
return (trim (== Boundary) $ map toFragment sn)
- return SearchResult {
- srPageName = decodePageName $ uriPath uri
- , srPageRev = rev
- , srSnippet = snippet
+ return HitPage {
+ hpPageName = decodePageName $ uriPath uri
+ , hpPageRev = rev
+ , hpLastMod = lastMod
+ , hpSummary = summary
+ , hpSnippet = snippet
}
toFragment :: Either String (String, String) -> SnippetFragment
rev <- if eof then
return 0
else
- hGetLine h >>= return . read
+ liftM read (hGetLine h)
rev' <- f rev
hSeek h AbsoluteSeek 0
hSetFileSize h 0