Guest User

Untitled

a guest
Jul 16th, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.24 KB | None | 0 0
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE TemplateHaskell #-}
  3.  
  4. module Main where
  5.  
  6. import Control.Concurrent.MVar
  7. import Control.Concurrent.STM (TMVar, putTMVar, newEmptyTMVarIO, atomically)
  8. import System.Win32.SystemServices.Services
  9. import System.Win32.Types
  10. import System.Win32.Registry (hKEY_LOCAL_MACHINE, regOpenKey, regCloseKey, regQueryValue
  11. ,regQueryValueEx, rEG_DWORD)
  12. import System.IO.Error (catchIOError)
  13. import Foreign.Storable (peek)
  14. import Foreign.Ptr (Ptr, castPtr)
  15. import Foreign.Marshal.Alloc (alloca)
  16. import Control.Exception (bracket)
  17. import System.Log.FastLogger
  18. import Control.Monad.Logger
  19. import qualified Data.Text as T
  20.  
  21. import System.Environment (getArgs)
  22.  
  23. import Network (withSocketsDo)
  24.  
  25. import Settings
  26. import Supervisor
  27.  
  28. main :: IO ()
  29. main = do
  30. args <- getArgs
  31. gState <- newMVar (1, SERVICE_STATUS WIN32_OWN_PROCESS
  32. START_PENDING [] nO_ERROR 0 0 3000)
  33. mStop <- newEmptyTMVarIO
  34. if (length args == 1) && (head args == "-d")
  35. then
  36. readParamsAndRunSupervisor mStop
  37. else
  38. startServiceCtrlDispatcher "NGP_Supervisor" 3000 (svcCtrlHandler mStop gState) $ svcMain mStop gState
  39.  
  40. hive :: HKEY
  41. hive = hKEY_LOCAL_MACHINE
  42.  
  43. path :: String
  44. path = "SOFTWARE\\Supervisor"
  45.  
  46. getConfigPathFromRegistry :: IO FilePath
  47. getConfigPathFromRegistry =
  48. bracket (regOpenKey hive path) regCloseKey $ \hkey ->
  49. regQueryValue hkey (Just "ConfigPath")
  50.  
  51. getClusterConfigPathFromRegistry :: IO FilePath
  52. getClusterConfigPathFromRegistry =
  53. bracket (regOpenKey hive path) regCloseKey $ \hkey ->
  54. regQueryValue hkey (Just "ClusterConfigPath")
  55.  
  56. getLogPathFromRegistry :: IO FilePath
  57. getLogPathFromRegistry =
  58. bracket (regOpenKey hive path) regCloseKey $ \hkey ->
  59. regQueryValue hkey (Just "LogPath")
  60.  
  61. getIsProdLogFromRegistry :: IO Bool
  62. getIsProdLogFromRegistry = fmap (toEnum . fromIntegral) $
  63. (bracket (regOpenKey hive path) regCloseKey $ \hkey ->
  64. alloca $ \p_val -> do
  65. ty <- regQueryValueEx hkey "IsProductionLogLevel" (castPtr p_val) 4
  66. if ty == rEG_DWORD
  67. then peekDWORD p_val
  68. else ioError (userError "Invalid registry value type"))
  69. `catchIOError` (const $ return 0)
  70. where
  71. peekDWORD :: Ptr DWORD -> IO DWORD
  72. peekDWORD = peek
  73.  
  74. getWebUIPathFromRegistry :: IO FilePath
  75. getWebUIPathFromRegistry =
  76. bracket (regOpenKey hive path) regCloseKey $ \hkey ->
  77. regQueryValue hkey (Just "WebUIPath")
  78.  
  79. readParamsAndRunSupervisor :: TMVar () -> IO ()
  80. readParamsAndRunSupervisor mStop = do
  81. settingsPath <- getConfigPathFromRegistry
  82. clusterConfigPath <- getClusterConfigPathFromRegistry
  83. webUIPath <- getWebUIPathFromRegistry
  84.  
  85. logPath <- getLogPathFromRegistry
  86. productionLog <- getIsProdLogFromRegistry
  87.  
  88. loggerSet <- newFileLoggerSet 4096 logPath
  89.  
  90. tgetter <- getTimeCache
  91.  
  92. let productionFilter = if productionLog
  93. then filterLogger (\_ l -> l > LevelDebug)
  94. else id
  95.  
  96. withSocketsDo $ runLogger tgetter loggerSet $ productionFilter $ do
  97. settings <- loadSettingsXml settingsPath
  98. dynConfig <- loadClusterConfig clusterConfigPath
  99.  
  100. $(logInfo) $ T.pack $ show settings
  101. $(logInfo) $ T.pack $ show dynConfig
  102.  
  103. runSupervisor webUIPath
  104. settings
  105. dynConfig
  106. (saveClusterCfg clusterConfigPath)
  107. (renewLog loggerSet)
  108. (Just mStop)
  109.  
  110. rmLoggerSet loggerSet
  111.  
  112. svcMain :: TMVar () -> MVar (DWORD, SERVICE_STATUS) -> ServiceMainFunction
  113. svcMain mStop gState _ _ h = do
  114. reportSvcStatus h RUNNING nO_ERROR 0 gState
  115.  
  116. readParamsAndRunSupervisor mStop
  117.  
  118. reportSvcStatus h STOPPED nO_ERROR 0 gState
  119.  
  120. reportSvcStatus :: HANDLE -> SERVICE_STATE -> DWORD -> DWORD -> MVar (DWORD, SERVICE_STATUS) -> IO ()
  121. reportSvcStatus hStatus state exitCode waitHint' mState =
  122. modifyMVar_ mState $ \(checkPoint', svcStatus) -> do
  123. let state' = nextState (checkPoint', svcStatus
  124. { win32ExitCode = exitCode
  125. , waitHint = waitHint'
  126. , currentState = state })
  127. setServiceStatus hStatus (snd state')
  128. return state'
  129.  
  130. nextState :: (DWORD, SERVICE_STATUS) -> (DWORD, SERVICE_STATUS)
  131. nextState (checkPoint', svcStatus) = case currentState svcStatus of
  132. START_PENDING -> (checkPoint' + 1, svcStatus
  133. { controlsAccepted = [], checkPoint = checkPoint' + 1 })
  134. RUNNING -> (checkPoint', svcStatus
  135. { controlsAccepted = [ACCEPT_STOP], checkPoint = 0 })
  136. STOPPED -> (checkPoint', svcStatus
  137. { controlsAccepted = [], checkPoint = 0 })
  138. _ -> (checkPoint' + 1, svcStatus
  139. { controlsAccepted = [], checkPoint = checkPoint' + 1 })
  140.  
  141. svcCtrlHandler :: TMVar () -> MVar (DWORD, SERVICE_STATUS) -> HandlerFunction
  142. svcCtrlHandler mStop mState hStatus STOP = do
  143. reportSvcStatus hStatus STOP_PENDING nO_ERROR 3000 mState
  144. atomically $ putTMVar mStop ()
  145. return True
  146. svcCtrlHandler _ _ _ INTERROGATE = return True
  147. svcCtrlHandler _ _ _ _ = return False
Add Comment
Please, Sign In to add comment