15a1d355fSStephan Aßmus // ServerConnection.cpp
25a1d355fSStephan Aßmus
35a1d355fSStephan Aßmus #include "ServerConnection.h"
45a1d355fSStephan Aßmus
55a1d355fSStephan Aßmus #include <AutoDeleter.h>
65a1d355fSStephan Aßmus #include <ByteOrder.h>
75a1d355fSStephan Aßmus #include <HashMap.h>
85a1d355fSStephan Aßmus
95a1d355fSStephan Aßmus #include "Connection.h"
105a1d355fSStephan Aßmus #include "ConnectionFactory.h"
115a1d355fSStephan Aßmus #include "DebugSupport.h"
125a1d355fSStephan Aßmus #include "ExtendedServerInfo.h"
135a1d355fSStephan Aßmus #include "RequestConnection.h"
145a1d355fSStephan Aßmus #include "ShareVolume.h"
155a1d355fSStephan Aßmus #include "VolumeEvent.h"
165a1d355fSStephan Aßmus #include "VolumeManager.h"
175a1d355fSStephan Aßmus
185a1d355fSStephan Aßmus // VolumeMap
195a1d355fSStephan Aßmus struct ServerConnection::VolumeMap : HashMap<HashKey32<int32>, ShareVolume*> {
205a1d355fSStephan Aßmus };
215a1d355fSStephan Aßmus
225a1d355fSStephan Aßmus
235a1d355fSStephan Aßmus // constructor
ServerConnection(VolumeManager * volumeManager,ExtendedServerInfo * serverInfo)245a1d355fSStephan Aßmus ServerConnection::ServerConnection(VolumeManager* volumeManager,
255a1d355fSStephan Aßmus ExtendedServerInfo* serverInfo)
265a1d355fSStephan Aßmus :
27*88e38c17SIngo Weinhold BReferenceable(),
285a1d355fSStephan Aßmus RequestHandler(),
295a1d355fSStephan Aßmus fLock("server connection"),
305a1d355fSStephan Aßmus fVolumeManager(volumeManager),
315a1d355fSStephan Aßmus fServerInfo(serverInfo),
325a1d355fSStephan Aßmus fConnection(NULL),
335a1d355fSStephan Aßmus fVolumes(NULL),
345a1d355fSStephan Aßmus fConnectionBrokenEvent(NULL),
355a1d355fSStephan Aßmus fConnected(false)
365a1d355fSStephan Aßmus {
375a1d355fSStephan Aßmus if (fServerInfo)
38*88e38c17SIngo Weinhold fServerInfo->AcquireReference();
395a1d355fSStephan Aßmus }
405a1d355fSStephan Aßmus
415a1d355fSStephan Aßmus // destructor
~ServerConnection()425a1d355fSStephan Aßmus ServerConnection::~ServerConnection()
435a1d355fSStephan Aßmus {
445a1d355fSStephan Aßmus PRINT(("ServerConnection::~ServerConnection()\n"))
455a1d355fSStephan Aßmus Close();
465a1d355fSStephan Aßmus delete fConnection;
475a1d355fSStephan Aßmus delete fVolumes;
485a1d355fSStephan Aßmus if (fConnectionBrokenEvent)
49*88e38c17SIngo Weinhold fConnectionBrokenEvent->ReleaseReference();
505a1d355fSStephan Aßmus if (fServerInfo)
51*88e38c17SIngo Weinhold fServerInfo->ReleaseReference();
525a1d355fSStephan Aßmus }
535a1d355fSStephan Aßmus
545a1d355fSStephan Aßmus // Init
555a1d355fSStephan Aßmus status_t
Init(vnode_id connectionBrokenTarget)565a1d355fSStephan Aßmus ServerConnection::Init(vnode_id connectionBrokenTarget)
575a1d355fSStephan Aßmus {
585a1d355fSStephan Aßmus if (!fServerInfo)
595a1d355fSStephan Aßmus RETURN_ERROR(B_BAD_VALUE);
605a1d355fSStephan Aßmus
615a1d355fSStephan Aßmus // create a connection broken event
625a1d355fSStephan Aßmus fConnectionBrokenEvent
635a1d355fSStephan Aßmus = new(std::nothrow) ConnectionBrokenEvent(connectionBrokenTarget);
645a1d355fSStephan Aßmus if (!fConnectionBrokenEvent)
655a1d355fSStephan Aßmus return B_NO_MEMORY;
665a1d355fSStephan Aßmus
675a1d355fSStephan Aßmus // get the server address
685a1d355fSStephan Aßmus const char* connectionMethod = fServerInfo->GetConnectionMethod();
695a1d355fSStephan Aßmus HashString server;
705a1d355fSStephan Aßmus status_t error = fServerInfo->GetAddress().GetString(&server, false);
715a1d355fSStephan Aßmus if (error != B_OK)
725a1d355fSStephan Aßmus RETURN_ERROR(error);
735a1d355fSStephan Aßmus
745a1d355fSStephan Aßmus // create the volume map
755a1d355fSStephan Aßmus fVolumes = new(std::nothrow) VolumeMap;
765a1d355fSStephan Aßmus if (!fVolumes)
775a1d355fSStephan Aßmus RETURN_ERROR(B_NO_MEMORY);
785a1d355fSStephan Aßmus error = fVolumes->InitCheck();
795a1d355fSStephan Aßmus if (error != B_OK)
805a1d355fSStephan Aßmus RETURN_ERROR(error);
815a1d355fSStephan Aßmus
825a1d355fSStephan Aßmus // establish the connection
835a1d355fSStephan Aßmus Connection* connection;
845a1d355fSStephan Aßmus ConnectionFactory factory;
855a1d355fSStephan Aßmus error = factory.CreateConnection(connectionMethod, server.GetString(),
865a1d355fSStephan Aßmus &connection);
875a1d355fSStephan Aßmus if (error != B_OK)
885a1d355fSStephan Aßmus RETURN_ERROR(error);
895a1d355fSStephan Aßmus
905a1d355fSStephan Aßmus // create a request connection
915a1d355fSStephan Aßmus fConnection = new(std::nothrow) RequestConnection(connection, this);
925a1d355fSStephan Aßmus if (!fConnection) {
935a1d355fSStephan Aßmus delete connection;
945a1d355fSStephan Aßmus RETURN_ERROR(B_NO_MEMORY);
955a1d355fSStephan Aßmus }
965a1d355fSStephan Aßmus error = fConnection->Init();
975a1d355fSStephan Aßmus if (error != B_OK)
985a1d355fSStephan Aßmus return error;
995a1d355fSStephan Aßmus
1005a1d355fSStephan Aßmus // send an `init connection request'
1015a1d355fSStephan Aßmus
1025a1d355fSStephan Aßmus // prepare the request
1035a1d355fSStephan Aßmus InitConnectionRequest request;
1045a1d355fSStephan Aßmus request.bigEndian = B_HOST_IS_BENDIAN;
1055a1d355fSStephan Aßmus
1065a1d355fSStephan Aßmus // send the request
1075a1d355fSStephan Aßmus Request* _reply;
1085a1d355fSStephan Aßmus error = fConnection->SendRequest(&request, &_reply);
1095a1d355fSStephan Aßmus if (error != B_OK)
1105a1d355fSStephan Aßmus return error;
1115a1d355fSStephan Aßmus ObjectDeleter<Request> replyDeleter(_reply);
1125a1d355fSStephan Aßmus
1135a1d355fSStephan Aßmus // everything OK?
1145a1d355fSStephan Aßmus InitConnectionReply* reply = dynamic_cast<InitConnectionReply*>(_reply);
1155a1d355fSStephan Aßmus if (!reply)
1165a1d355fSStephan Aßmus return B_BAD_DATA;
1175a1d355fSStephan Aßmus if (reply->error != B_OK)
1185a1d355fSStephan Aßmus return reply->error;
1195a1d355fSStephan Aßmus
1205a1d355fSStephan Aßmus fConnected = true;
1215a1d355fSStephan Aßmus return B_OK;
1225a1d355fSStephan Aßmus }
1235a1d355fSStephan Aßmus
1245a1d355fSStephan Aßmus // Close
1255a1d355fSStephan Aßmus void
Close()1265a1d355fSStephan Aßmus ServerConnection::Close()
1275a1d355fSStephan Aßmus {
1285a1d355fSStephan Aßmus // mark the connection closed (events won't be delivered anymore)
1295a1d355fSStephan Aßmus {
1305a1d355fSStephan Aßmus AutoLocker<Locker> locker(fLock);
1315a1d355fSStephan Aßmus fConnected = false;
1325a1d355fSStephan Aßmus }
1335a1d355fSStephan Aßmus
1345a1d355fSStephan Aßmus if (fConnection)
1355a1d355fSStephan Aßmus fConnection->Close();
1365a1d355fSStephan Aßmus }
1375a1d355fSStephan Aßmus
1385a1d355fSStephan Aßmus // IsConnected
1395a1d355fSStephan Aßmus bool
IsConnected()1405a1d355fSStephan Aßmus ServerConnection::IsConnected()
1415a1d355fSStephan Aßmus {
1425a1d355fSStephan Aßmus return fConnected;
1435a1d355fSStephan Aßmus }
1445a1d355fSStephan Aßmus
1455a1d355fSStephan Aßmus // GetRequestConnection
1465a1d355fSStephan Aßmus RequestConnection*
GetRequestConnection() const1475a1d355fSStephan Aßmus ServerConnection::GetRequestConnection() const
1485a1d355fSStephan Aßmus {
1495a1d355fSStephan Aßmus return fConnection;
1505a1d355fSStephan Aßmus }
1515a1d355fSStephan Aßmus
1525a1d355fSStephan Aßmus // AddVolume
1535a1d355fSStephan Aßmus status_t
AddVolume(ShareVolume * volume)1545a1d355fSStephan Aßmus ServerConnection::AddVolume(ShareVolume* volume)
1555a1d355fSStephan Aßmus {
1565a1d355fSStephan Aßmus if (!volume)
1575a1d355fSStephan Aßmus return B_BAD_VALUE;
1585a1d355fSStephan Aßmus
1595a1d355fSStephan Aßmus AutoLocker<Locker> _(fLock);
1605a1d355fSStephan Aßmus return fVolumes->Put(volume->GetID(), volume);
1615a1d355fSStephan Aßmus }
1625a1d355fSStephan Aßmus
1635a1d355fSStephan Aßmus // RemoveVolume
1645a1d355fSStephan Aßmus void
RemoveVolume(ShareVolume * volume)1655a1d355fSStephan Aßmus ServerConnection::RemoveVolume(ShareVolume* volume)
1665a1d355fSStephan Aßmus {
1675a1d355fSStephan Aßmus if (!volume)
1685a1d355fSStephan Aßmus return;
1695a1d355fSStephan Aßmus
1705a1d355fSStephan Aßmus AutoLocker<Locker> _(fLock);
1715a1d355fSStephan Aßmus fVolumes->Remove(volume->GetID());
1725a1d355fSStephan Aßmus }
1735a1d355fSStephan Aßmus
1745a1d355fSStephan Aßmus // GetVolume
1755a1d355fSStephan Aßmus ShareVolume*
GetVolume(int32 volumeID)1765a1d355fSStephan Aßmus ServerConnection::GetVolume(int32 volumeID)
1775a1d355fSStephan Aßmus {
1785a1d355fSStephan Aßmus AutoLocker<Locker> _(fLock);
1795a1d355fSStephan Aßmus return fVolumes->Get(volumeID);
1805a1d355fSStephan Aßmus }
1815a1d355fSStephan Aßmus
1825a1d355fSStephan Aßmus // VisitConnectionBrokenRequest
1835a1d355fSStephan Aßmus status_t
VisitConnectionBrokenRequest(ConnectionBrokenRequest * request)1845a1d355fSStephan Aßmus ServerConnection::VisitConnectionBrokenRequest(ConnectionBrokenRequest* request)
1855a1d355fSStephan Aßmus {
1865a1d355fSStephan Aßmus AutoLocker<Locker> locker(fLock);
1875a1d355fSStephan Aßmus if (fConnected) {
1885a1d355fSStephan Aßmus fConnected = false;
1895a1d355fSStephan Aßmus fVolumeManager->SendVolumeEvent(fConnectionBrokenEvent);
1905a1d355fSStephan Aßmus }
1915a1d355fSStephan Aßmus return B_OK;
1925a1d355fSStephan Aßmus }
1935a1d355fSStephan Aßmus
1945a1d355fSStephan Aßmus // VisitNodeMonitoringRequest
1955a1d355fSStephan Aßmus status_t
VisitNodeMonitoringRequest(NodeMonitoringRequest * request)1965a1d355fSStephan Aßmus ServerConnection::VisitNodeMonitoringRequest(NodeMonitoringRequest* request)
1975a1d355fSStephan Aßmus {
1985a1d355fSStephan Aßmus AutoLocker<Locker> locker(fLock);
1995a1d355fSStephan Aßmus if (fConnected) {
2005a1d355fSStephan Aßmus if (ShareVolume* volume = GetVolume(request->volumeID)) {
2015a1d355fSStephan Aßmus if (fVolumeManager->GetVolume(volume->GetRootID())) {
2025a1d355fSStephan Aßmus locker.Unlock();
2035a1d355fSStephan Aßmus if (request->opcode == B_DEVICE_UNMOUNTED)
2045a1d355fSStephan Aßmus volume->SetUnmounting(true);
2055a1d355fSStephan Aßmus else
2065a1d355fSStephan Aßmus volume->ProcessNodeMonitoringRequest(request);
2075a1d355fSStephan Aßmus volume->PutVolume();
2085a1d355fSStephan Aßmus }
2095a1d355fSStephan Aßmus }
2105a1d355fSStephan Aßmus }
2115a1d355fSStephan Aßmus return B_OK;
2125a1d355fSStephan Aßmus }
2135a1d355fSStephan Aßmus
214