]> gitweb @ CieloNegro.org - Rakka.git/commitdiff
The experiment has succeeded
authorpho <pho@cielonegro.org>
Fri, 26 Oct 2007 23:12:42 +0000 (08:12 +0900)
committerpho <pho@cielonegro.org>
Fri, 26 Oct 2007 23:12:42 +0000 (08:12 +0900)
darcs-hash:20071026231242-62b54-443a561407cc36917c3a7b87d5dd6e57934473ca.gz

Rakka.cabal
Rakka/Resource.hs
Rakka/Resource/Render.hs
Rakka/Storage.hs
Rakka/Storage/Impl.hs [new file with mode: 0644]
Rakka/Storage/Types.hs [new file with mode: 0644]

index 60b1ca82e96de08ef152621daaf381993cc3e5d7..2fe7ff5f3142730d1857d13880f46de59cec78c2 100644 (file)
@@ -49,6 +49,7 @@ Other-Modules:
     Rakka.Resource.Render
     Rakka.Storage
     Rakka.Storage.DefaultPage
+    Rakka.Storage.Impl
     Rakka.SystemConfig
     Rakka.Utils
     Rakka.Wiki
index e1166b4d33079b0096d81a63f2d8c00af1d8b396..ec143733d5173f0645471c03bdbb0a498eb81aef 100644 (file)
@@ -17,11 +17,11 @@ import           Text.XML.HXT.DOM.TypeDefs
 import           Text.XML.HXT.DOM.XmlKeywords
 
 
--- /         ==> /
--- /foo      ==> /foo.html
--- /foo/     ==> /foo.html
--- /foo.bar/ ==> /foo.bar
--- /foo.bar  ==> /foo.bar
+-- "/"         ==> "/"
+-- "/foo"      ==> "/foo.html"
+-- "/foo/"     ==> "/foo.html"
+-- "/foo.bar/" ==> "/foo.bar"
+-- "/foo.bar"  ==> "/foo.bar"
 canonicalizeURI :: Resource ()
 canonicalizeURI 
     = do uri <- getRequestURI
index 213b0757c000c067d6664fb1ee08a960bce3aac3..66a1516df6f8b1ef2a09ba58dcac441c036baefd 100644 (file)
@@ -25,9 +25,9 @@ import           Text.XML.HXT.DOM.TypeDefs
 
 fallbackRender :: Environment -> [String] -> IO (Maybe ResourceDef)
 fallbackRender env path
-    | null path                        = return Nothing
-    | null $ head path                 = return Nothing
-    | not $ isUpper $ head $ head path = return Nothing -- /Foo/bar のような形式でない。
+    | null path                  = return Nothing
+    | null $ head path           = return Nothing
+    | isLower $ head $ head path = return Nothing -- 先頭の文字が小文字であってはならない
     | otherwise
         = return $ Just $ ResourceDef {
             resUsesNativeThread = False
index 078feda64bee90ee43379b181c867b77a5bed008..56b42da0ae57f8668685f86d1cd9bca08ebe0f60 100644 (file)
@@ -14,44 +14,21 @@ module Rakka.Storage
     where
 
 import           Control.Arrow.ArrowIO
-import           Control.Concurrent
 import           Control.Concurrent.STM
-import           Control.Exception
 import           Control.Monad
 import           Control.Monad.Trans
 import           Data.Maybe
-import           Data.Set (Set)
-import qualified Data.Set as S
-import           Network.URI
 import           Rakka.Page
-import           Rakka.Storage.DefaultPage
+import           Rakka.Storage.Impl
+import           Rakka.Storage.Types
 import           Subversion.Types
-import           System.Directory
-import           System.FilePath
 import           System.IO
-import           System.Log.Logger
-import           System.Posix.Files
-import           System.Posix.Types
-import           System.Posix.IO
-import           Subversion.FileSystem
 import           Subversion.Repository
 import           Text.HyperEstraier hiding (WriteLock)
 
 logger = "Rakka.Storage"
 
 
-data Storage
-    = Storage {
-        stoRepository :: !Repository
-      , stoIndexChan  :: !(TChan IndexReq)
-      }
-
-
-data IndexReq
-    = SyncIndex
-    | SearchIndex !Condition !(TMVar [(PageName, RevNum)])
-
-
 mkStorage :: FilePath -> Repository -> (Page -> IO Document) -> IO Storage
 mkStorage lsdir repos mkDraft
     = do chan <- startIndexManager lsdir repos mkDraft
@@ -67,11 +44,6 @@ getPage :: MonadIO m => Storage -> PageName -> Maybe RevNum -> m (Maybe Page)
 getPage = ((liftIO .) .) . getPage' . stoRepository
 
 
-getPage' :: Repository -> PageName -> Maybe RevNum -> IO (Maybe Page)
-getPage' repos name rev
-    = loadDefaultPage name -- FIXME
-
-
 putPage :: MonadIO m => Storage -> Page -> RevNum -> m ()
 putPage sto page oldRev
     = error "FIXME: not implemented"
@@ -97,159 +69,3 @@ syncIndex :: Storage -> IO ()
 syncIndex sto
     = atomically $ writeTChan (stoIndexChan sto) SyncIndex
 
-
-findAllPages :: Repository -> RevNum -> IO (Set PageName)
-findAllPages _     0   = findAllDefaultPages
-findAllPages repos rev
-    = findAllDefaultPages -- FIXME
-
-
-findChangedPages :: Repository -> RevNum -> RevNum -> IO (Set PageName)
-findChangedPages repos 0      newRev = findAllPages repos newRev
-findChangedPages repos oldRev newRev
-    = fail "FIXME: not impl"
-
-
-getCurrentRevNum :: Repository -> IO RevNum
-getCurrentRevNum repos
-    = getRepositoryFS repos >>= getYoungestRev
-
-
-startIndexManager :: FilePath -> Repository -> (Page -> IO Document) -> IO (TChan IndexReq)
-startIndexManager lsdir repos mkDraft
-    = do chan  <- newTChanIO
-         index <- openIndex indexDir revFile
-         forkIO (loop chan index)
-         return chan
-    where
-      indexDir = lsdir </> "index"
-      revFile  = lsdir </> "indexRev"
-
-      loop :: TChan IndexReq -> Database -> IO ()
-      loop chan index
-          = do req <- atomically $ readTChan chan
-               case req of
-                 SyncIndex
-                     -> syncIndex' index revFile repos mkDraft
-                 SearchIndex cond var
-                     -> do result <- searchIndex index cond
-                           atomically $ putTMVar var result
-               loop chan index
-
-
--- casket を R/W モードで開く。成功したらそのまま返し、失敗したら
--- indexDir と revFile を削除してから casket を R/W モードで開く。
-openIndex :: FilePath -> FilePath -> IO Database
-openIndex indexDir revFile
-    = do ret <- openDatabase indexDir (Writer [])
-         case ret of
-           Right index
-               -> do debugM logger ("Opened an H.E. index on " ++ indexDir)
-                     return index
-
-           Left err
-               -> do warningM logger ("Failed to open an H.E. index on "
-                                      ++ indexDir ++ ": " ++ show err)
-
-                     indexExists <- doesDirectoryExist indexDir
-                     when indexExists
-                              $ removeDirectoryRecursive indexDir
-
-                     revFileExists <- doesFileExist revFile
-                     when revFileExists
-                              $ removeFile revFile
-
-                     Right index <- openDatabase indexDir (Writer [Create []])
-                     addAttrIndex index "@uri"           SeqIndex
-                     addAttrIndex index "rakka:revision" SeqIndex
-                     noticeM logger ("Created an H.E. index on " ++ indexDir)
-
-                     return index
-
-
-syncIndex' :: Database -> FilePath -> Repository -> (Page -> IO Document) -> IO ()
-syncIndex' index revFile repos mkDraft
-    = updateIndexRev revFile $ \ oldRev ->
-      do debugM logger ("The index revision is currently " ++ show oldRev)
-         
-         newRev <- getCurrentRevNum repos
-         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 repos oldRev newRev
-               mapM_ (updateIndex index repos mkDraft newRev) (S.toList pages)
-
-
-searchIndex :: Database -> Condition -> IO [(PageName, RevNum)]
-searchIndex index cond
-    = searchDatabase index cond >>= mapM fromId
-    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)
-
-
-updateIndex :: Database
-            -> Repository
-            -> (Page -> IO Document)
-            -> RevNum
-            -> PageName
-            -> IO ()
-updateIndex index repos mkDraft rev name
-    = do pageM <- getPage' repos name (Just rev)
-         case pageM of
-           -- ページが削除された
-           Nothing
-               -> do docIdM <- getDocIdByURI index (mkRakkaURI name)
-                     case docIdM of
-                       Nothing    -> return ()
-                       Just docId -> do removeDocument index docId [CleaningRemove]
-                                        infoM logger ("Removed page " ++ name ++ " from the index")
-           Just page
-               -> do draft <- mkDraft page
-                     putDocument index draft [CleaningPut]
-                     infoM logger ("Indexed page " ++ name ++ " of revision " ++ show (pageRevision page))
-
-
-updateIndexRev :: FilePath -> (RevNum -> IO RevNum) -> IO ()
-updateIndexRev revFile f = bracket acquireLock releaseLock 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")
\ No newline at end of file
diff --git a/Rakka/Storage/Impl.hs b/Rakka/Storage/Impl.hs
new file mode 100644 (file)
index 0000000..dd8b7c4
--- /dev/null
@@ -0,0 +1,192 @@
+module Rakka.Storage.Impl
+    ( getPage'
+    , startIndexManager
+    )
+    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.URI
+import           Rakka.Page
+import           Rakka.Storage.DefaultPage
+import           Rakka.Storage.Types
+import           Subversion.Types
+import           System.Directory
+import           System.FilePath
+import           System.IO
+import           System.Log.Logger
+import           System.Posix.Files
+import           System.Posix.Types
+import           System.Posix.IO
+import           Subversion.FileSystem
+import           Subversion.Repository
+import           Text.HyperEstraier hiding (WriteLock)
+
+logger = "Rakka.Storage"
+
+
+getPage' :: Repository -> PageName -> Maybe RevNum -> IO (Maybe Page)
+getPage' repos name rev
+    = loadDefaultPage name -- FIXME
+
+
+findAllPages :: Repository -> RevNum -> IO (Set PageName)
+findAllPages _     0   = findAllDefaultPages
+findAllPages repos rev
+    = findAllDefaultPages -- FIXME
+
+
+findChangedPages :: Repository -> RevNum -> RevNum -> IO (Set PageName)
+findChangedPages repos 0      newRev = findAllPages repos newRev
+findChangedPages repos oldRev newRev
+    = fail "FIXME: not impl"
+
+
+getCurrentRevNum :: Repository -> IO RevNum
+getCurrentRevNum repos
+    = getRepositoryFS repos >>= getYoungestRev
+
+
+startIndexManager :: FilePath -> Repository -> (Page -> IO Document) -> IO (TChan IndexReq)
+startIndexManager lsdir repos mkDraft
+    = do chan  <- newTChanIO
+         index <- openIndex indexDir revFile
+         forkIO (loop chan index)
+         return chan
+    where
+      indexDir = lsdir </> "index"
+      revFile  = lsdir </> "indexRev"
+
+      loop :: TChan IndexReq -> Database -> IO ()
+      loop chan index
+          = do req <- atomically $ readTChan chan
+               case req of
+                 SyncIndex
+                     -> syncIndex' index revFile repos mkDraft
+                 SearchIndex cond var
+                     -> do result <- searchIndex index cond
+                           atomically $ putTMVar var result
+               loop chan index
+
+
+-- casket を R/W モードで開く。成功したらそのまま返し、失敗したら
+-- indexDir と revFile を削除してから casket を R/W モードで開く。
+openIndex :: FilePath -> FilePath -> IO Database
+openIndex indexDir revFile
+    = do ret <- openDatabase indexDir (Writer [])
+         case ret of
+           Right index
+               -> do debugM logger ("Opened an H.E. index on " ++ indexDir)
+                     return index
+
+           Left err
+               -> do warningM logger ("Failed to open an H.E. index on "
+                                      ++ indexDir ++ ": " ++ show err)
+
+                     indexExists <- doesDirectoryExist indexDir
+                     when indexExists
+                              $ removeDirectoryRecursive indexDir
+
+                     revFileExists <- doesFileExist revFile
+                     when revFileExists
+                              $ removeFile revFile
+
+                     Right index <- openDatabase indexDir (Writer [Create []])
+                     addAttrIndex index "@uri"           SeqIndex
+                     addAttrIndex index "rakka:revision" SeqIndex
+                     noticeM logger ("Created an H.E. index on " ++ indexDir)
+
+                     return index
+
+
+syncIndex' :: Database -> FilePath -> Repository -> (Page -> IO Document) -> IO ()
+syncIndex' index revFile repos mkDraft
+    = updateIndexRev revFile $ \ oldRev ->
+      do debugM logger ("The index revision is currently " ++ show oldRev)
+         
+         newRev <- getCurrentRevNum repos
+         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 repos oldRev newRev
+               mapM_ (updateIndex index repos mkDraft newRev) (S.toList pages)
+
+
+searchIndex :: Database -> Condition -> IO [(PageName, RevNum)]
+searchIndex index cond
+    = searchDatabase index cond >>= mapM fromId
+    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)
+
+
+updateIndex :: Database
+            -> Repository
+            -> (Page -> IO Document)
+            -> RevNum
+            -> PageName
+            -> IO ()
+updateIndex index repos mkDraft rev name
+    = do pageM <- getPage' repos name (Just rev)
+         case pageM of
+           -- ページが削除された
+           Nothing
+               -> do docIdM <- getDocIdByURI index (mkRakkaURI name)
+                     case docIdM of
+                       Nothing    -> return ()
+                       Just docId -> do removeDocument index docId [CleaningRemove]
+                                        infoM logger ("Removed page " ++ name ++ " from the index")
+           Just page
+               -> do draft <- mkDraft page
+                     putDocument index draft [CleaningPut]
+                     infoM logger ("Indexed page " ++ name ++ " of revision " ++ show (pageRevision page))
+
+
+updateIndexRev :: FilePath -> (RevNum -> IO RevNum) -> IO ()
+updateIndexRev revFile f = bracket acquireLock releaseLock 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")
diff --git a/Rakka/Storage/Types.hs b/Rakka/Storage/Types.hs
new file mode 100644 (file)
index 0000000..8a19041
--- /dev/null
@@ -0,0 +1,23 @@
+module Rakka.Storage.Types
+    ( Storage(..)
+    , IndexReq(..)
+    )
+    where
+
+import           Control.Concurrent.STM
+import           Rakka.Page
+import           Subversion.Repository
+import           Subversion.Types
+import           Text.HyperEstraier hiding (WriteLock)
+
+
+data Storage
+    = Storage {
+        stoRepository :: !Repository
+      , stoIndexChan  :: !(TChan IndexReq)
+      }
+
+
+data IndexReq
+    = SyncIndex
+    | SearchIndex !Condition !(TMVar [(PageName, RevNum)])