on master help sign in
WIP Client.hs partially implemented with remote action

- I need to remove local usage of the disconnectedTransaction and transactionGraph which should remain local to the server

commit6518e14876c7f2eac9687ce4434f5f796136d5fb authorAgentM <agentm@themactionfaction.com> dateSat 14 Nov 2015, 09:15 (11 years ago) parent5577809
6 files changed+139−25
ProjectM36/Client.hs+64−11 ProjectM36/Daemon/EndPoints.hs → ProjectM36/Daemon/EntryPoints.hs+5−2 ProjectM36/Daemon/Main.hs+5−2 ProjectM36/Daemon/RemoteCallTypes.hs+9 TutorialD/Interpreter.hs+9−8 project-m36.cabal+47−2
ProjectM36/Client.hs+64−11
@@ -7,8 +7,8 @@ module ProjectM36.Client
77 DatabaseName,
88 ConnectionError,
99 connectProjectM36,
10− disconnectedTransaction,
11− transactionGraph,
10+-- disconnectedTransaction,
11+-- transactionGraph,
1212 close,
1313 executeRelationalExpr,
1414 executeDatabaseContextExpr,
@@ -34,25 +34,48 @@ import ProjectM36.TransactionGraph
3434import ProjectM36.TransactionGraph.Persist
3535import ProjectM36.Attribute
3636import ProjectM36.Persist (DiskSync(..))
37+import ProjectM36.Daemon.RemoteCallTypes (RemoteExecution(..))
38+import Network.Transport.TCP (createTransport, defaultTCPParameters)
39+import Control.Distributed.Process.Node (newLocalNode, initRemoteTable, runProcess, LocalNode)
40+import Control.Distributed.Process.Extras.Internal.Types (whereisRemote)
41+import Control.Distributed.Process.ManagedProcess.Client (call)
42+import Control.Distributed.Process (NodeId(..))
43+
3744import Data.UUID.V4 (nextRandom)
3845import Control.Concurrent.STM
3946import Data.Word
40−
41−type DatabaseName = StringType
47+import Control.Distributed.Process (ProcessId)
48+import Control.Exception (IOException)
49+import Control.Concurrent.MVar
4250
4351type Hostname = StringType
4452
4553type Port = Word16
4654
47−data ConnectionInfo = InProcessConnectionInfo PersistenceStrategy
48− --TCPRemoteConnectionInfo HeadName DatabaseName Hostname Port
55+type DatabaseName = String
56+
57+data ConnectionInfo = InProcessConnectionInfo PersistenceStrategy |
58+ RemoteProcessConnectionInfo DatabaseName NodeId
4959
50−data Connection = InProcessConnection PersistenceStrategy (TVar (DisconnectedTransaction, TransactionGraph))
51− -- TCPRemoteConnection
60+data Connection = InProcessConnection PersistenceStrategy (TVar (DisconnectedTransaction, TransactionGraph)) |
61+ RemoteProcessConnection ProcessId
5262
53−data ConnectionError = SetupDatabaseDirectoryError PersistenceError
54− deriving (Show, Eq)
63+data ConnectionError = SetupDatabaseDirectoryError PersistenceError |
64+ IOExceptionError IOException |
65+ NoSuchDatabaseByNameError DatabaseName |
66+ LoginError
67+ deriving (Show, Eq)
5568
69+remoteDBLookupName :: DatabaseName -> String
70+remoteDBLookupName = (++) "db-"
71+
72+commonLocalNode :: IO (Either ConnectionError LocalNode)
73+commonLocalNode = do
74+ eLocalTransport <- createTransport "127.0.0.1" "0" defaultTCPParameters
75+ case eLocalTransport of
76+ Left err -> pure (Left $ IOExceptionError err)
77+ Right localTransport -> newLocalNode localTransport initRemoteTable >>= pure . Right
78+
5679-- connect to an in-process database
5780connectProjectM36 :: ConnectionInfo -> IO (Either ConnectionError Connection)
5881--create a new in-memory database/transaction graph
@@ -68,6 +91,25 @@ connectProjectM36 (InProcessConnectionInfo strat) = do
6891 return $ Right $ InProcessConnection strat tvar
6992 MinimalPersistence dbdir -> connectPersistentProjectM36 strat NoDiskSync dbdir freshDiscon freshGraph
7093 CrashSafePersistence dbdir -> connectPersistentProjectM36 strat FsyncDiskSync dbdir freshDiscon freshGraph
94+
95+connectProjectM36 (RemoteProcessConnectionInfo databaseName serverNodeId) = do
96+ connStatus <- newEmptyMVar
97+ eLocalNode <- commonLocalNode
98+ case eLocalNode of
99+ Left err -> pure (Left err)
100+ Right localNode -> do
101+ runProcess localNode $ do
102+ mServerProcessId <- whereisRemote serverNodeId (remoteDBLookupName databaseName)
103+ case mServerProcessId of
104+ Nothing -> liftIO $ putMVar connStatus $ Left (NoSuchDatabaseByNameError databaseName)
105+ Just serverProcessId -> do
106+ loginConfirmation <- call serverProcessId Login
107+ if not loginConfirmation then
108+ liftIO $ putMVar connStatus (Left LoginError)
109+ else do
110+ liftIO $ putMVar connStatus (Right $ RemoteProcessConnection serverProcessId)
111+ status <- takeMVar connStatus
112+ pure status
71113
72114connectPersistentProjectM36 :: PersistenceStrategy ->
73115 DiskSync ->
@@ -87,14 +129,25 @@ connectPersistentProjectM36 strat sync dbdir freshDiscon freshGraph = do
87129 tvar <- newTVarIO (freshDiscon, graph')
88130 return $ Right $ InProcessConnection strat tvar
89131
132+{-
133+-- if these are operated remotely, they are too expensive- keep the working space (discon) on the server
90134disconnectedTransaction :: Connection -> IO (DisconnectedTransaction)
91135disconnectedTransaction (InProcessConnection _ tvar) = liftM fst (readTVarIO tvar)
92136
93137transactionGraph :: Connection -> IO (TransactionGraph)
94138transactionGraph (InProcessConnection _ tvar) = liftM snd (readTVarIO tvar)
139+-}
95140
96141close :: Connection -> IO ()
97−close (InProcessConnection _ _) = return ()
142+close (InProcessConnection _ _) = pure ()
143+close (RemoteProcessConnection serverProcessId) = do
144+ eLocalNode <- commonLocalNode
145+ case eLocalNode of
146+ Left _ -> pure () --consider returning an error or exception
147+ Right localNode -> do
148+ runProcess localNode $ do
149+ call serverProcessId Logout
150+ pure ()
98151
99152executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
100153executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do
ProjectM36/Daemon/EndPoints.hs → ProjectM36/Daemon/EntryPoints.hsrenamed+5−2
@@ -1,8 +1,8 @@
1−module ProjectM36.Daemon.EndPoints where
1+module ProjectM36.Daemon.EntryPoints where
22import ProjectM36.Base
33import ProjectM36.Client
44import ProjectM36.Error
5−
5+import ProjectM36.Daemon.RemoteCallTypes
66import Control.Distributed.Process (Process)
77import Control.Distributed.Process.ManagedProcess (ProcessReply)
88import Control.Distributed.Process.ManagedProcess.Server (reply)
@@ -12,4 +12,7 @@ handleExecuteRelationalExpr :: Connection -> RelationalExpr -> Process (ProcessR
1212handleExecuteRelationalExpr conn expr = do
1313 ret <- liftIO $ executeRelationalExpr conn expr
1414 reply ret conn
15+
16+handleLogin :: Connection -> Process (ProcessReply Bool Connection)
17+handleLogin conn = reply True conn
1518
ProjectM36/Daemon/Main.hs+5−2
@@ -1,7 +1,8 @@
11{-# LANGUAGE ScopedTypeVariables #-}
22import ProjectM36.Client
33import ProjectM36.Daemon.ParseArgs (parseConfig, persistenceStrategy)
4−import ProjectM36.Daemon.EndPoints (handleExecuteRelationalExpr)
4+import ProjectM36.Daemon.EntryPoints (handleExecuteRelationalExpr, handleLogin)
5+import ProjectM36.Daemon.RemoteCallTypes (RemoteExecution(..))
56
67import System.Exit (exitFailure, exitSuccess)
78import Control.Concurrent (threadDelay)
@@ -17,7 +18,9 @@ import qualified Control.Distributed.Process.Extras.Internal.Types as DIT
1718
1819serverDefinition :: ProcessDefinition Connection
1920serverDefinition = defaultProcess {
20− apiHandlers = [handleCall (\conn (expr :: RelationalExpr) -> handleExecuteRelationalExpr conn expr)],
21+ apiHandlers = [handleCall (\conn Login -> handleLogin conn),
22+ handleCall (\conn (ExecuteRelationalExpr expr) -> handleExecuteRelationalExpr conn expr)
23+ ],
2124 unhandledMessagePolicy = Drop
2225 }
2326
ProjectM36/Daemon/RemoteCallTypes.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE DeriveAnyClass, DeriveGeneric #-}
2+module ProjectM36.Daemon.RemoteCallTypes where
3+import ProjectM36.Base
4+import GHC.Generics
5+import Data.Binary
6+
7+data RemoteExecution = Login |
8+ Logout |
9+ ExecuteRelationalExpr RelationalExpr deriving (Binary, Generic)
TutorialD/Interpreter.hs+9−8
@@ -22,6 +22,7 @@ import Control.Monad.State
2222import System.Console.Haskeline
2323import System.Directory (getHomeDirectory)
2424import qualified Data.Text as T
25+import Data.UUID (UUID)
2526
2627{-
2728context ops are read-only operations which only operate on the database context (relvars and constraints)
@@ -43,8 +44,8 @@ interpreterParserP = liftM RODatabaseContextOp (roDatabaseContextOperatorP <* eo
4344 liftM ImportOp ((importCSVP <|> tutdImportP) <* eof) <|>
4445 liftM ExportOp (exportCSVP <* eof)
4546
46−promptText :: DisconnectedTransaction -> TransactionGraph -> StringType
47−promptText (DisconnectedTransaction parentUUID _) graph = "TutorialD (" `T.append` transInfo `T.append` "): "
47+promptText :: UUID -> TransactionGraph -> StringType
48+promptText parentUUID graph = "TutorialD (" `T.append` transInfo `T.append` "): "
4849 where
4950 transInfo = case transactionForUUID parentUUID graph of
5051 Left _ -> "unknown"
@@ -62,7 +63,7 @@ evalTutorialD conn expr = case expr of
6263 --this does not pass through the ProjectM36.Client library because the operations
6364 --are specific to the interpreter, though some operations may be of general use in the future
6465 (RODatabaseContextOp execOp) -> do
65− (DisconnectedTransaction _ context) <- disconnectedTransaction conn
66+ (DisconnectedTransaction _ context) <- disconnectedTransaction conn -- !
6667 return $ evalRODatabaseContextOp context execOp
6768
6869 (DatabaseExprOp execOp) -> do
@@ -78,21 +79,21 @@ evalTutorialD conn expr = case expr of
7879 Nothing -> return QuietSuccessResult
7980
8081 (ROGraphOp execOp) -> do
81− discon <- disconnectedTransaction conn
82+ discon <- disconnectedTransaction conn -- !
8283 graph <- transactionGraph conn
8384 case evalROGraphOp discon graph execOp of
8485 Left err -> barf err
8586 Right rel -> return $ DisplayResult $ showRelation rel
8687
8788 (ImportOp execOp) -> do
88− (DisconnectedTransaction _ context) <- disconnectedTransaction conn
89+ (DisconnectedTransaction _ context) <- disconnectedTransaction conn -- !
8990 exprErr <- evalDataImportOperator execOp context
9091 case exprErr of
9192 Left err -> barf err
9293 Right dbexpr -> evalTutorialD conn (DatabaseExprOp dbexpr)
9394
9495 (ExportOp execOp) -> do
95− (DisconnectedTransaction _ context) <- disconnectedTransaction conn
96+ (DisconnectedTransaction _ context) <- disconnectedTransaction conn -- !
9697 exprErr <- evalDataExportOperator execOp context
9798 case exprErr of
9899 Just err -> barf err
@@ -109,9 +110,9 @@ reprLoop :: InterpreterConfig -> Connection -> IO ()
109110reprLoop config conn = do
110111 homeDirectory <- getHomeDirectory
111112 let settings = defaultSettings {historyFile = Just (homeDirectory ++ "/.tutd_history")}
112− discon <- disconnectedTransaction conn
113+ (DisconnectedTransaction parentUUID _) <- disconnectedTransaction conn
113114 graph <- transactionGraph conn
114− maybeLine <- runInputT settings $ getInputLine (T.unpack (promptText discon graph))
115+ maybeLine <- runInputT settings $ getInputLine (T.unpack (promptText parentUUID graph))
115116 case maybeLine of
116117 Nothing -> return ()
117118 Just line -> do
project-m36.cabal+47−2
@@ -46,6 +46,7 @@ Library
4646 ,base64-bytestring
4747 ,data-interval
4848 ,extended-reals
49+ ,network-transport
4950--required for persistent db driver
5051 ,persistent
5152 ,persistent-template
@@ -53,6 +54,14 @@ Library
5354 ,path-pieces
5455 ,conduit
5556 ,resourcet
57+--needed for remote access
58+ ,distributed-process-client-server
59+ ,distributed-process-extras
60+ ,distributed-process-async
61+ ,distributed-process
62+ ,network-transport-tcp
63+ ,network-transport
64+ ,distributed-process
5665 Exposed-Modules: ProjectM36.Error,
5766 ProjectM36.Transaction,
5867 ProjectM36.TransactionGraph,
@@ -82,7 +91,43 @@ Library
8291 Default-Language: Haskell2010
8392
8493Executable tutd
85− Build-Depends: base, project-m36
94+ Build-Depends: base >=4.8 && <4.9,
95+ project-m36,
96+ containers,
97+ unordered-containers,
98+ hashable,
99+ mtl,
100+ uuid,
101+ deepseq-generics,
102+ vector,
103+ text,
104+ vector-binary-instances,
105+ time,
106+ hashable-time,
107+ bytestring,
108+ distributed-process-client-server,
109+ distributed-process-extras,
110+ distributed-process-async,
111+ distributed-process,
112+ network-transport-tcp,
113+ network-transport,
114+ distributed-process,
115+ stm,
116+ deepseq,
117+ binary,
118+ data-interval,
119+ unix,
120+ parallel,
121+ cassava,
122+ gnuplot,
123+ directory,
124+ filepath,
125+ temporary,
126+ parsec,
127+ haskeline,
128+ base64-bytestring,
129+ optparse-applicative,
130+ attoparsec
86131 Other-Modules: ProjectM36.Error,
87132 ProjectM36.Base,
88133 ProjectM36.RelationalExpression,
@@ -101,12 +146,12 @@ Executable tutd
101146
102147Executable daemon
103148 Build-Depends: project-m36,
104− base >=4.8 && <4.9,
105149 distributed-process-client-server,
106150 distributed-process-extras,
107151 distributed-process-async,
108152 distributed-process,
109153 network-transport-tcp,
154+ network-transport,
110155 distributed-process,
111156 binary,
112157 transformers,