@@ -20,14 +20,18 @@ module ProjectM36.Client
20 processPersistence,
20 processPersistence,
21 transactionGraphAsRelation,
21 transactionGraphAsRelation,
23 headTransactionUUID,
25 headTransactionUUID,
24 PersistenceStrategy(..),
26 PersistenceStrategy(..),
25 RelationalExpr(..),
27 RelationalExpr(..),
26 DatabaseExpr(..),
28 DatabaseExpr(..),
27 Attribute(..),
29 Attribute(..),
28 attributesFromList,
30 attributesFromList,
29 TransactionGraphOperator(..),
32 TransactionGraphOperator(..),
32 AtomType(..)) where
36 AtomType(..)) where
33import ProjectM36.Base hiding (inclusionDependencies) --defined in this module as well
37import ProjectM36.Base hiding (inclusionDependencies) --defined in this module as well
@@ -43,7 +47,7 @@ import ProjectM36.TransactionGraph.Persist
43import ProjectM36.Attribute
47import ProjectM36.Attribute
44import ProjectM36.Persist (DiskSync(..))
48import ProjectM36.Persist (DiskSync(..))
45import ProjectM36.Daemon.RemoteCallTypes (RemoteExecution(..))
49import ProjectM36.Daemon.RemoteCallTypes (RemoteExecution(..))
46−import Network.Transport.TCP (createTransport, defaultTCPParameters)
50+import Network.Transport.TCP (createTransport, defaultTCPParameters, encodeEndPointAddress)
47import Control.Distributed.Process.Node (newLocalNode, initRemoteTable, runProcess, LocalNode)
51import Control.Distributed.Process.Node (newLocalNode, initRemoteTable, runProcess, LocalNode)
48import Control.Distributed.Process.Extras.Internal.Types (whereisRemote)
52import Control.Distributed.Process.Extras.Internal.Types (whereisRemote)
49import Control.Distributed.Process.ManagedProcess.Client (call)
53import Control.Distributed.Process.ManagedProcess.Client (call)
@@ -53,12 +57,12 @@ import Data.UUID (UUID)
53import Data.UUID.V4 (nextRandom)
57import Data.UUID.V4 (nextRandom)
54import Control.Concurrent.STM
58import Control.Concurrent.STM
55import Data.Word
59import Data.Word
56−import Control.Distributed.Process (ProcessId)
60+import Control.Distributed.Process (ProcessId, Process)
57import Control.Exception (IOException)
61import Control.Exception (IOException)
58import Control.Concurrent.MVar
62import Control.Concurrent.MVar
59import qualified Data.Map as M
63import qualified Data.Map as M
61−type Hostname = StringType
65+type Hostname = String
63type Port = Word16
67type Port = Word16
@@ -67,8 +71,14 @@ type DatabaseName = String
67data ConnectionInfo = InProcessConnectionInfo PersistenceStrategy |
71data ConnectionInfo = InProcessConnectionInfo PersistenceStrategy |
68 RemoteProcessConnectionInfo DatabaseName NodeId
72 RemoteProcessConnectionInfo DatabaseName NodeId
74+createNodeId :: Hostname -> Port -> NodeId
75+createNodeId host port = NodeId $ encodeEndPointAddress host (show port) 0
77+defaultServerPort :: Port
78+defaultServerPort = 6543
70data Connection = InProcessConnection PersistenceStrategy (TVar (DisconnectedTransaction, TransactionGraph)) |
80data Connection = InProcessConnection PersistenceStrategy (TVar (DisconnectedTransaction, TransactionGraph)) |
71− RemoteProcessConnection ProcessId
81+ RemoteProcessConnection LocalNode ProcessId -- perhaps should reference the local node as well
73data ConnectionError = SetupDatabaseDirectoryError PersistenceError |
83data ConnectionError = SetupDatabaseDirectoryError PersistenceError |
74 IOExceptionError IOException |
84 IOExceptionError IOException |
@@ -105,11 +115,13 @@ connectProjectM36 (InProcessConnectionInfo strat) = do
105connectProjectM36 (RemoteProcessConnectionInfo databaseName serverNodeId) = do
115connectProjectM36 (RemoteProcessConnectionInfo databaseName serverNodeId) = do
106 connStatus <- newEmptyMVar
116 connStatus <- newEmptyMVar
107 eLocalNode <- commonLocalNode
117 eLocalNode <- commonLocalNode
118+ let dbName = remoteDBLookupName databaseName
119+ putStrLn $ show serverNodeId ++ " " ++ dbName
108 case eLocalNode of
120 case eLocalNode of
109 Left err -> pure (Left err)
121 Left err -> pure (Left err)
110 Right localNode -> do
122 Right localNode -> do
111 runProcess localNode $ do
123 runProcess localNode $ do
112− mServerProcessId <- whereisRemote serverNodeId (remoteDBLookupName databaseName)
124+ mServerProcessId <- whereisRemote serverNodeId dbName
113 case mServerProcessId of
125 case mServerProcessId of
114 Nothing -> liftIO $ putMVar connStatus $ Left (NoSuchDatabaseByNameError databaseName)
126 Nothing -> liftIO $ putMVar connStatus $ Left (NoSuchDatabaseByNameError databaseName)
115 Just serverProcessId -> do
127 Just serverProcessId -> do
@@ -117,7 +129,7 @@ connectProjectM36 (RemoteProcessConnectionInfo databaseName serverNodeId) = do
117 if not loginConfirmation then
129 if not loginConfirmation then
118 liftIO $ putMVar connStatus (Left LoginError)
130 liftIO $ putMVar connStatus (Left LoginError)
120− liftIO $ putMVar connStatus (Right $ RemoteProcessConnection serverProcessId)
132+ liftIO $ putMVar connStatus (Right $ RemoteProcessConnection localNode serverProcessId)
121 status <- takeMVar connStatus
133 status <- takeMVar connStatus
122 pure status
134 pure status
@@ -141,19 +153,25 @@ connectPersistentProjectM36 strat sync dbdir freshDiscon freshGraph = do
142close :: Connection -> IO ()
154close :: Connection -> IO ()
143close (InProcessConnection _ _) = pure ()
155close (InProcessConnection _ _) = pure ()
144−close (RemoteProcessConnection serverProcessId) = do
156+close (RemoteProcessConnection localNode serverProcessId) = do
145− eLocalNode <- commonLocalNode
147− Left _ -> pure () --consider returning an error or exception
148− Right localNode -> do
157+ runProcessResult localNode $ do
149− runProcess localNode $ do
150− call serverProcessId Logout
158+ call serverProcessId Logout
160+runProcessResult :: LocalNode -> Process a -> IO a
161+runProcessResult localNode proc = do
163+ runProcess localNode $ do
165+ liftIO $ putMVar ret val
153executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
168executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
154executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do
169executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do
155 ((DisconnectedTransaction _ context), _) <- readTVar tvar
170 ((DisconnectedTransaction _ context), _) <- readTVar tvar
156 return $ evalState (RE.evalRelationalExpr expr) context
171 return $ evalState (RE.evalRelationalExpr expr) context
172+executeRelationalExpr (RemoteProcessConnection localNode serverProcessId) relExpr = do
173+ runProcessResult localNode $ do
174+ call serverProcessId (ExecuteRelationalExpr relExpr)
158executeDatabaseContextExpr :: Connection -> DatabaseExpr -> IO (Maybe RelationalError)
176executeDatabaseContextExpr :: Connection -> DatabaseExpr -> IO (Maybe RelationalError)
159executeDatabaseContextExpr (InProcessConnection _ tvar) expr = atomically $ do
177executeDatabaseContextExpr (InProcessConnection _ tvar) expr = atomically $ do
@@ -164,6 +182,8 @@ executeDatabaseContextExpr (InProcessConnection _ tvar) expr = atomically $ do
164 let newDiscon = DisconnectedTransaction parentUUID context'
182 let newDiscon = DisconnectedTransaction parentUUID context'
165 writeTVar tvar (newDiscon, graph)
183 writeTVar tvar (newDiscon, graph)
166 return Nothing
184 return Nothing
185+executeDatabaseContextExpr (RemoteProcessConnection localNode serverProcessId) dbExpr = do
186+ runProcessResult localNode $ call serverProcessId (ExecuteDatabaseContextExpr dbExpr)
168executeGraphExpr :: Connection -> TransactionGraphOperator -> IO (Maybe RelationalError)
188executeGraphExpr :: Connection -> TransactionGraphOperator -> IO (Maybe RelationalError)
169executeGraphExpr (InProcessConnection strat tvar) graphExpr = do
189executeGraphExpr (InProcessConnection strat tvar) graphExpr = do
@@ -242,6 +262,10 @@ headName (InProcessConnection _ tvar) = do
242 pure $ case transactionForUUID parentUUID graph of
262 pure $ case transactionForUUID parentUUID graph of
243 Left _ -> Nothing
263 Left _ -> Nothing
244 Right parentTrans -> headNameForTransaction parentTrans graph
264 Right parentTrans -> headNameForTransaction parentTrans graph
245−
265+headName (RemoteProcessConnection localNode serverProcessId) = do
266+ runProcessResult localNode $ do
267+ ret <- call serverProcessId ExecuteHeadName