1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
module CASS.ServerFunctions where
import System.IO ( Handle(..), hClose, hFlush, hGetLine, hPutStrLn
, hWaitForInput, hWaitForInputs )
import System.Process ( system, sleep )
import System.Directory ( doesFileExist, getModificationTime )
import Data.Maybe ( fromMaybe )
import Data.List ( delete )
import Data.Time ( ClockTime )
import XML ( showXmlDoc, xml )
import FlatCurry.Types ( QName )
import FlatCurry.Goodies ( progImports )
import Analysis.Logging ( debugMessage )
import Analysis.Types
import Analysis.ProgInfo
import CASS.Dependencies
import CASS.Configuration ( CConfig, debugLevel, waitTime )
data WorkerMessage = Task String String | ChangePath String | StopWorker
deriving (Read, Show)
masterLoop :: CConfig -> [Handle] -> [Handle] -> String -> String
-> [(String,[String])] -> [String] -> IO (Maybe String)
masterLoop cc _ [] _ _ [] [] = do
debugMessage (debugLevel cc) 2 "Master loop: terminated"
return Nothing
masterLoop cc _ (b:busyWorker) ananame mainModule [] [] = do
debugMessage dl 2 "Master loop: waiting for worker result"
inputHandle <- hWaitForInputs (b:busyWorker) waitTime
if inputHandle/=0
then return (Just "No input from any worker received")
else do
let handle = b
input <- hGetLine handle
debugMessage dl 2 ("Master loop: got message: "++input)
let Task ananame2 moduleName2 = read input
if ananame == ananame2 && moduleName2 == mainModule
then return Nothing
else return (Just "Received analysis does not match requested analysis")
where dl = debugLevel cc
masterLoop cc idleWorker busyWorker ananame mainModule
modulesToDo@(_:_) [] = do
debugMessage dl 3 ("Master loop: modules to do: " ++ show modulesToDo)
let modulesToDo2 = filter ((not . null) . snd) modulesToDo
waitList = map fst (filter (null . snd) modulesToDo)
if null waitList
then do
debugMessage dl 2 "Master loop: waiting for workers to finish"
inputHandle <- hWaitForInputs busyWorker waitTime
if inputHandle<0
then return (Just "No input from any worker received")
else do
let handle = busyWorker !! inputHandle
input <- hGetLine handle
debugMessage dl 2 ("Master loop: got message: " ++ input)
let Task ananame2 moduleName2 = read input
if ananame==ananame2
then do
let modulesToDo3 = reduceDependencies modulesToDo2 [moduleName2]
busyWorker2= deleteIndex inputHandle busyWorker
masterLoop cc (handle:idleWorker) busyWorker2 ananame
mainModule modulesToDo3 waitList
else
return
(Just "Received analysis does not match requested analysis type")
else masterLoop cc idleWorker busyWorker ananame mainModule modulesToDo2
waitList
where dl = debugLevel cc
masterLoop cc (handle:idleWorker) busyWorker ananame mainModule modulesToDo
(modName:waitList) = do
debugMessage dl 2 "Master loop: worker available, send task to a worker..."
let newTask = show (Task ananame modName)
hPutStrLn handle newTask
hFlush handle
debugMessage dl 2 ("Master loop: send message: "++newTask)
masterLoop cc idleWorker (handle:busyWorker) ananame mainModule
modulesToDo waitList
where dl = debugLevel cc
masterLoop cc [] busyWorker ananame mainModule modulesToDo
waits@(modName:waitList) = do
debugMessage dl 2 $ "Waiting for worker to analyze modules: "++show waits
inputHandle <- hWaitForInputs busyWorker waitTime
if inputHandle < 0
then return (Just "No input from any worker received")
else do
let handle = busyWorker !! inputHandle
input <- hGetLine handle
debugMessage dl 2 ("Master loop: got message: "++input)
let Task _ finishedmodule = read input
newTask = show (Task ananame modName)
hPutStrLn handle newTask
hFlush handle
debugMessage dl 2 ("Master loop: send message: "++newTask)
let modulesToDo2 = reduceDependencies modulesToDo [finishedmodule]
masterLoop cc [] busyWorker ananame mainModule modulesToDo2 waitList
where dl = debugLevel cc
deleteIndex :: Int -> [a] -> [a]
deleteIndex _ [] = []
deleteIndex n (x:xs) | n==0 = xs
| otherwise = x : deleteIndex (n-1) xs
|