]> gitweb @ CieloNegro.org - Rakka.git/blobdiff - Rakka/Storage/Impl.hs
continue working on page search
[Rakka.git] / Rakka / Storage / Impl.hs
index 20208bf2208a846b9f421d721465276280381e4a..c763a304f51f187b6625bcebcb6478ae6dfd0032 100644 (file)
@@ -1,17 +1,25 @@
 module Rakka.Storage.Impl
     ( getPage'
+    , putPage'
+    , deletePage'
+    , getDirContents'
     , startIndexManager
+
+    , getAttachment'
+    , putAttachment'
     )
     where
 
 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           Network.HTTP.Lucu
 import           Network.URI
+import           Prelude hiding (words)
+import           Rakka.Attachment
 import           Rakka.Page
 import           Rakka.Storage.DefaultPage
 import           Rakka.Storage.Repos
@@ -22,10 +30,8 @@ import           Subversion.Repository
 import           System.Directory
 import           System.FilePath
 import           System.IO
+import           System.IO.Unsafe
 import           System.Log.Logger
-import           System.Posix.Files
-import           System.Posix.Types
-import           System.Posix.IO
 import           Text.HyperEstraier hiding (WriteLock)
 
 
@@ -41,6 +47,14 @@ getPage' repos name rev
            p       -> return p
 
 
+putPage' :: Repository -> Maybe String -> Page -> IO StatusCode
+putPage' = putPageIntoRepository
+
+
+deletePage' :: Repository -> Maybe String -> PageName -> IO StatusCode
+deletePage' = deletePageFromRepository
+
+
 findAllPages :: Repository -> RevNum -> IO (Set PageName)
 findAllPages _     0   = findAllDefaultPages
 findAllPages repos rev = do reposPages   <- findAllPagesInRevision repos rev
@@ -56,11 +70,38 @@ findChangedPages repos oldRev newRev
       return . S.unions
 
 
+getDirContents' :: Repository -> PageName -> Maybe RevNum -> IO [PageName]
+getDirContents' repos name rev
+    = do reposPages   <- getDirContentsInRevision repos name rev
+         defaultPages <- getDefaultDirContents name
+         return $ S.toList (reposPages `S.union` defaultPages)
+
+
 getCurrentRevNum :: Repository -> IO RevNum
 getCurrentRevNum repos
     = getRepositoryFS repos >>= getYoungestRev
 
 
+getAttachment' :: Attachment a =>
+                  Repository
+               -> PageName
+               -> String
+               -> Maybe RevNum
+               -> IO (Maybe a)
+getAttachment' = loadAttachmentInRepository
+
+
+putAttachment' :: Attachment a =>
+                  Repository
+               -> Maybe String
+               -> Maybe RevNum
+               -> PageName
+               -> String
+               -> a
+               -> IO StatusCode
+putAttachment' = putAttachmentIntoRepository
+
+
 startIndexManager :: FilePath -> Repository -> (Page -> IO Document) -> IO (TChan IndexReq)
 startIndexManager lsdir repos mkDraft
     = do chan  <- newTChanIO
@@ -116,8 +157,11 @@ openIndex indexDir revFile
                               $ removeFile revFile
 
                      Right index <- openDatabase indexDir (Writer [Create []])
+                     addAttrIndex index "@type"          StrIndex
                      addAttrIndex index "@uri"           SeqIndex
                      addAttrIndex index "rakka:revision" SeqIndex
+                     addAttrIndex index "rakka:isTheme"  StrIndex
+                     addAttrIndex index "rakka:isFeed"   StrIndex
                      noticeM logger ("Created an H.E. index on " ++ indexDir)
 
                      return index
@@ -141,16 +185,29 @@ syncIndex' index revFile repos mkDraft
                mapM_ (updateIndex index repos mkDraft newRev) (S.toList pages)
 
 
-searchIndex :: Database -> Condition -> IO [(PageName, RevNum)]
+searchIndex :: Database -> Condition -> IO [SearchResult]
 searchIndex index cond
-    = searchDatabase index cond >>= mapM fromId
+    = do (ids, hint) <- searchDatabase' index cond
+         mapM (fromId $ map fst hint) ids
     where
-      fromId :: DocumentID -> IO (PageName, RevNum)
-      fromId docId
-          = do uri <- getDocURI index docId
-               rev <- getDocAttr index docId "rakka:revision"
-                      >>= return . read . fromJust
-               return (decodePageName $ uriPath uri, rev)
+      fromId :: [String] -> DocumentID -> IO SearchResult
+      fromId words docId
+          = do uri     <- getDocURI index docId
+               rev     <- getDocAttr index docId "rakka:revision"
+                          >>= return . read . fromJust
+               snippet <- unsafeInterleaveIO $
+                          do doc <- getDocument index docId [NoAttributes, NoKeywords]
+                             sn  <- makeSnippet doc words 300 80 80
+                             return (map toFragment sn)
+               return SearchResult {
+                            srPageName = decodePageName $ uriPath uri
+                          , srPageRev  = rev
+                          , srSnippet  = snippet
+                          }
+
+      toFragment :: Either String (String, String) -> SnippetFragment
+      toFragment (Left t)       = NormalText t
+      toFragment (Right (w, _)) = HighlightedWord w
 
 
 updateIndex :: Database
@@ -176,37 +233,15 @@ updateIndex index repos mkDraft rev name
 
 
 updateIndexRev :: FilePath -> (RevNum -> IO RevNum) -> IO ()
-updateIndexRev revFile f = bracket acquireLock releaseLock update
+updateIndexRev revFile f = withFile revFile ReadWriteMode update
     where
-      acquireLock :: IO Fd
-      acquireLock
-          = do fd <- openFd revFile ReadWrite (Just stdFileMode) defaultFileFlags
-               waitToSetLock fd (WriteLock, AbsoluteSeek, 0, 0)
-               return fd
-
-      releaseLock :: Fd -> IO ()
-      releaseLock fd
-          = setLock fd (Unlock, AbsoluteSeek, 0, 0)
-
-      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")
+      update :: Handle -> IO ()
+      update h = do eof  <- hIsEOF h
+                    rev  <- if eof then
+                                return 0
+                            else
+                                hGetLine h >>= return . read
+                    rev' <- f rev
+                    hSeek h AbsoluteSeek 0
+                    hSetFileSize h 0
+                    hPutStrLn h (show rev')