@@ -7,8 +7,8 @@ module ProjectM36.Client
7 DatabaseName,
7 DatabaseName,
8 ConnectionError,
8 ConnectionError,
9 connectProjectM36,
9 connectProjectM36,
10− disconnectedTransaction,
10+-- disconnectedTransaction,
11− transactionGraph,
11+-- transactionGraph,
13 executeRelationalExpr,
13 executeRelationalExpr,
14 executeDatabaseContextExpr,
14 executeDatabaseContextExpr,
@@ -34,25 +34,48 @@ import ProjectM36.TransactionGraph
34import ProjectM36.TransactionGraph.Persist
34import ProjectM36.TransactionGraph.Persist
35import ProjectM36.Attribute
35import ProjectM36.Attribute
36import ProjectM36.Persist (DiskSync(..))
36import 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(..))
37import Data.UUID.V4 (nextRandom)
44import Data.UUID.V4 (nextRandom)
38import Control.Concurrent.STM
45import Control.Concurrent.STM
39import Data.Word
46import Data.Word
40−
47+import Control.Distributed.Process (ProcessId)
41−type DatabaseName = StringType
48+import Control.Exception (IOException)
49+import Control.Concurrent.MVar
43type Hostname = StringType
51type Hostname = StringType
45type Port = Word16
53type Port = Word16
55+type DatabaseName = String
47−data ConnectionInfo = InProcessConnectionInfo PersistenceStrategy
57+data ConnectionInfo = InProcessConnectionInfo PersistenceStrategy |
48− --TCPRemoteConnectionInfo HeadName DatabaseName Hostname Port
58+ RemoteProcessConnectionInfo DatabaseName NodeId
50−data Connection = InProcessConnection PersistenceStrategy (TVar (DisconnectedTransaction, TransactionGraph))
60+data Connection = InProcessConnection PersistenceStrategy (TVar (DisconnectedTransaction, TransactionGraph)) |
51− -- TCPRemoteConnection
61+ RemoteProcessConnection ProcessId
53−data ConnectionError = SetupDatabaseDirectoryError PersistenceError
63+data ConnectionError = SetupDatabaseDirectoryError PersistenceError |
64+ IOExceptionError IOException |
65+ NoSuchDatabaseByNameError DatabaseName |
54− deriving (Show, Eq)
67+ deriving (Show, Eq)
69+remoteDBLookupName :: DatabaseName -> String
70+remoteDBLookupName = (++) "db-"
72+commonLocalNode :: IO (Either ConnectionError LocalNode)
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
56-- connect to an in-process database
79-- connect to an in-process database
57connectProjectM36 :: ConnectionInfo -> IO (Either ConnectionError Connection)
80connectProjectM36 :: ConnectionInfo -> IO (Either ConnectionError Connection)
58--create a new in-memory database/transaction graph
81--create a new in-memory database/transaction graph
@@ -68,6 +91,25 @@ connectProjectM36 (InProcessConnectionInfo strat) = do
68 return $ Right $ InProcessConnection strat tvar
91 return $ Right $ InProcessConnection strat tvar
69 MinimalPersistence dbdir -> connectPersistentProjectM36 strat NoDiskSync dbdir freshDiscon freshGraph
92 MinimalPersistence dbdir -> connectPersistentProjectM36 strat NoDiskSync dbdir freshDiscon freshGraph
70 CrashSafePersistence dbdir -> connectPersistentProjectM36 strat FsyncDiskSync dbdir freshDiscon freshGraph
93 CrashSafePersistence dbdir -> connectPersistentProjectM36 strat FsyncDiskSync dbdir freshDiscon freshGraph
95+connectProjectM36 (RemoteProcessConnectionInfo databaseName serverNodeId) = do
96+ connStatus <- newEmptyMVar
97+ eLocalNode <- commonLocalNode
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)
110+ liftIO $ putMVar connStatus (Right $ RemoteProcessConnection serverProcessId)
111+ status <- takeMVar connStatus
72connectPersistentProjectM36 :: PersistenceStrategy ->
114connectPersistentProjectM36 :: PersistenceStrategy ->
73 DiskSync ->
115 DiskSync ->
@@ -87,14 +129,25 @@ connectPersistentProjectM36 strat sync dbdir freshDiscon freshGraph = do
87 tvar <- newTVarIO (freshDiscon, graph')
129 tvar <- newTVarIO (freshDiscon, graph')
88 return $ Right $ InProcessConnection strat tvar
130 return $ Right $ InProcessConnection strat tvar
133+-- if these are operated remotely, they are too expensive- keep the working space (discon) on the server
90disconnectedTransaction :: Connection -> IO (DisconnectedTransaction)
134disconnectedTransaction :: Connection -> IO (DisconnectedTransaction)
91disconnectedTransaction (InProcessConnection _ tvar) = liftM fst (readTVarIO tvar)
135disconnectedTransaction (InProcessConnection _ tvar) = liftM fst (readTVarIO tvar)
93transactionGraph :: Connection -> IO (TransactionGraph)
137transactionGraph :: Connection -> IO (TransactionGraph)
94transactionGraph (InProcessConnection _ tvar) = liftM snd (readTVarIO tvar)
138transactionGraph (InProcessConnection _ tvar) = liftM snd (readTVarIO tvar)
96close :: Connection -> IO ()
141close :: Connection -> IO ()
97−close (InProcessConnection _ _) = return ()
142+close (InProcessConnection _ _) = pure ()
143+close (RemoteProcessConnection serverProcessId) = do
144+ eLocalNode <- commonLocalNode
146+ Left _ -> pure () --consider returning an error or exception
147+ Right localNode -> do
148+ runProcess localNode $ do
149+ call serverProcessId Logout
99executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
152executeRelationalExpr :: Connection -> RelationalExpr -> IO (Either RelationalError Relation)
100executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do
153executeRelationalExpr (InProcessConnection _ tvar) expr = atomically $ do