xref: /haiku/src/add-ons/kernel/file_systems/netfs/client/ServerConnection.cpp (revision 88e38c178a96634d52920e2de8bb3cbd49869f93)
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