xref: /haiku/src/add-ons/kernel/file_systems/netfs/client/ServerVolume.cpp (revision 25a7b01d15612846f332751841da3579db313082)
15a1d355fSStephan Aßmus // ServerVolume.cpp
25a1d355fSStephan Aßmus 
35a1d355fSStephan Aßmus #include "ServerVolume.h"
45a1d355fSStephan Aßmus 
55a1d355fSStephan Aßmus #include <new>
65a1d355fSStephan Aßmus 
75a1d355fSStephan Aßmus #include <AutoDeleter.h>
85a1d355fSStephan Aßmus #include <AutoLocker.h>
95a1d355fSStephan Aßmus 
105a1d355fSStephan Aßmus #include "Compatibility.h"
115a1d355fSStephan Aßmus #include "DebugSupport.h"
125a1d355fSStephan Aßmus #include "ExtendedServerInfo.h"
135a1d355fSStephan Aßmus #include "QueryManager.h"
145a1d355fSStephan Aßmus #include "SendReceiveRequest.h"
155a1d355fSStephan Aßmus #include "ServerConnection.h"
165a1d355fSStephan Aßmus #include "ServerConnectionProvider.h"
175a1d355fSStephan Aßmus #include "ServerQueryIterator.h"
185a1d355fSStephan Aßmus #include "ShareVolume.h"
195a1d355fSStephan Aßmus #include "VolumeEvent.h"
205a1d355fSStephan Aßmus #include "VolumeManager.h"
215a1d355fSStephan Aßmus #include "VolumeSupport.h"
225a1d355fSStephan Aßmus 
235a1d355fSStephan Aßmus // constructor
ServerVolume(VolumeManager * volumeManager,ExtendedServerInfo * serverInfo)245a1d355fSStephan Aßmus ServerVolume::ServerVolume(VolumeManager* volumeManager,
255a1d355fSStephan Aßmus 	ExtendedServerInfo* serverInfo)
265a1d355fSStephan Aßmus 	: VirtualVolume(volumeManager),
275a1d355fSStephan Aßmus 	  fServerInfo(serverInfo),
285a1d355fSStephan Aßmus 	  fConnectionProvider(NULL)
295a1d355fSStephan Aßmus {
3088e38c17SIngo Weinhold 	fServerInfo->AcquireReference();
315a1d355fSStephan Aßmus }
325a1d355fSStephan Aßmus 
335a1d355fSStephan Aßmus // destructor
~ServerVolume()345a1d355fSStephan Aßmus ServerVolume::~ServerVolume()
355a1d355fSStephan Aßmus {
365a1d355fSStephan Aßmus 	if (fConnectionProvider)
3788e38c17SIngo Weinhold 		fConnectionProvider->ReleaseReference();
385a1d355fSStephan Aßmus 	if (fServerInfo)
3988e38c17SIngo Weinhold 		fServerInfo->ReleaseReference();
405a1d355fSStephan Aßmus }
415a1d355fSStephan Aßmus 
425a1d355fSStephan Aßmus // GetServerAddress
435a1d355fSStephan Aßmus NetAddress
GetServerAddress()445a1d355fSStephan Aßmus ServerVolume::GetServerAddress()
455a1d355fSStephan Aßmus {
465a1d355fSStephan Aßmus 	AutoLocker<Locker> _(fLock);
475a1d355fSStephan Aßmus 	return fServerInfo->GetAddress();
485a1d355fSStephan Aßmus }
495a1d355fSStephan Aßmus 
505a1d355fSStephan Aßmus // SetServerInfo
515a1d355fSStephan Aßmus void
SetServerInfo(ExtendedServerInfo * serverInfo)525a1d355fSStephan Aßmus ServerVolume::SetServerInfo(ExtendedServerInfo* serverInfo)
535a1d355fSStephan Aßmus {
545a1d355fSStephan Aßmus 	if (!serverInfo)
555a1d355fSStephan Aßmus 		return;
565a1d355fSStephan Aßmus 
575a1d355fSStephan Aßmus 	// set the new info
585a1d355fSStephan Aßmus 	fLock.Lock();
5988e38c17SIngo Weinhold 	fServerInfo->ReleaseReference();
605a1d355fSStephan Aßmus 	fServerInfo = serverInfo;
6188e38c17SIngo Weinhold 	fServerInfo->AcquireReference();
6288e38c17SIngo Weinhold 	BReference<ExtendedServerInfo> newReference(fServerInfo);
635a1d355fSStephan Aßmus 
645a1d355fSStephan Aßmus 	// remove shares, that are no longer there
655a1d355fSStephan Aßmus 
665a1d355fSStephan Aßmus 	// init a directory iterator
675a1d355fSStephan Aßmus 	VirtualDirIterator iterator;
685a1d355fSStephan Aßmus 	iterator.SetDirectory(fRootNode, true);
695a1d355fSStephan Aßmus 
705a1d355fSStephan Aßmus 	// iterate through the directory
715a1d355fSStephan Aßmus 	const char* name;
725a1d355fSStephan Aßmus 	Node* node;
735a1d355fSStephan Aßmus 	while (iterator.GetCurrentEntry(&name, &node)) {
745a1d355fSStephan Aßmus 		iterator.NextEntry();
755a1d355fSStephan Aßmus 		// TODO: Searching by name is currently O(n).
765a1d355fSStephan Aßmus 		bool remove = (!serverInfo->GetShareInfo(name));
775a1d355fSStephan Aßmus 		fLock.Unlock();
785a1d355fSStephan Aßmus 
795a1d355fSStephan Aßmus 		if (remove) {
80*3c1afd35SPawel Dziepak 			PRINT("  removing share: %s\n", name);
815a1d355fSStephan Aßmus 			if (Volume* volume = GetChildVolume(name)) {
825a1d355fSStephan Aßmus 				volume->SetUnmounting(true);
835a1d355fSStephan Aßmus 				volume->PutVolume();
845a1d355fSStephan Aßmus 			}
855a1d355fSStephan Aßmus 		}
865a1d355fSStephan Aßmus 
875a1d355fSStephan Aßmus 		fLock.Lock();
885a1d355fSStephan Aßmus 	}
895a1d355fSStephan Aßmus 
905a1d355fSStephan Aßmus 	// uninit the directory iterator
915a1d355fSStephan Aßmus 	iterator.SetDirectory(NULL);
925a1d355fSStephan Aßmus 	fLock.Unlock();
935a1d355fSStephan Aßmus 
945a1d355fSStephan Aßmus 	// add new shares
955a1d355fSStephan Aßmus 	int32 count = serverInfo->CountShares();
965a1d355fSStephan Aßmus 	for (int32 i = 0; i < count; i++) {
975a1d355fSStephan Aßmus 		ExtendedShareInfo* shareInfo = serverInfo->ShareInfoAt(i);
985a1d355fSStephan Aßmus 		const char* shareName = shareInfo->GetShareName();
995a1d355fSStephan Aßmus 
1005a1d355fSStephan Aßmus 		Volume* volume = GetChildVolume(shareName);
1015a1d355fSStephan Aßmus 		if (volume) {
1025a1d355fSStephan Aßmus 			volume->PutVolume();
1035a1d355fSStephan Aßmus 		} else {
104*3c1afd35SPawel Dziepak 			PRINT("  adding share: %s\n",
105*3c1afd35SPawel Dziepak 				shareInfo->GetShareName());
1065a1d355fSStephan Aßmus 			status_t error = _AddShare(shareInfo);
1075a1d355fSStephan Aßmus 			if (error != B_OK) {
1085a1d355fSStephan Aßmus 				ERROR("ServerVolume::SetServerInfo(): ERROR: Failed to add "
1095a1d355fSStephan Aßmus 					"share `%s': %s\n", shareName, strerror(error));
1105a1d355fSStephan Aßmus 			}
1115a1d355fSStephan Aßmus 		}
1125a1d355fSStephan Aßmus 	}
1135a1d355fSStephan Aßmus }
1145a1d355fSStephan Aßmus 
1155a1d355fSStephan Aßmus // Init
1165a1d355fSStephan Aßmus status_t
Init(const char * name)1175a1d355fSStephan Aßmus ServerVolume::Init(const char* name)
1185a1d355fSStephan Aßmus {
1195a1d355fSStephan Aßmus 	status_t error = VirtualVolume::Init(name);
1205a1d355fSStephan Aßmus 	if (error != B_OK)
1215a1d355fSStephan Aßmus 		return error;
1225a1d355fSStephan Aßmus 
1235a1d355fSStephan Aßmus 	// create the server connection provider
1245a1d355fSStephan Aßmus 	fConnectionProvider = new ServerConnectionProvider(fVolumeManager,
1255a1d355fSStephan Aßmus 		fServerInfo, GetRootID());
1265a1d355fSStephan Aßmus 	if (!fConnectionProvider) {
1275a1d355fSStephan Aßmus 		Uninit();
1285a1d355fSStephan Aßmus 		return B_NO_MEMORY;
1295a1d355fSStephan Aßmus 	}
1305a1d355fSStephan Aßmus 	error = fConnectionProvider->Init();
1315a1d355fSStephan Aßmus 	if (error != B_OK) {
1325a1d355fSStephan Aßmus 		Uninit();
1335a1d355fSStephan Aßmus 		return error;
1345a1d355fSStephan Aßmus 	}
1355a1d355fSStephan Aßmus 
1365a1d355fSStephan Aßmus 	// add share volumes
1375a1d355fSStephan Aßmus 	int32 count = fServerInfo->CountShares();
1385a1d355fSStephan Aßmus 	for (int32 i = 0; i < count; i++) {
1395a1d355fSStephan Aßmus 		ExtendedShareInfo* shareInfo = fServerInfo->ShareInfoAt(i);
1405a1d355fSStephan Aßmus 
1415a1d355fSStephan Aßmus 		error = _AddShare(shareInfo);
1425a1d355fSStephan Aßmus 		if (error != B_OK) {
1435a1d355fSStephan Aßmus 			ERROR("ServerVolume::Init(): ERROR: Failed to add share `%s': "
1445a1d355fSStephan Aßmus 				"%s\n", shareInfo->GetShareName(), strerror(error));
1455a1d355fSStephan Aßmus 		}
1465a1d355fSStephan Aßmus 	}
1475a1d355fSStephan Aßmus 
1485a1d355fSStephan Aßmus 	return B_OK;
1495a1d355fSStephan Aßmus }
1505a1d355fSStephan Aßmus 
1515a1d355fSStephan Aßmus // Uninit
1525a1d355fSStephan Aßmus void
Uninit()1535a1d355fSStephan Aßmus ServerVolume::Uninit()
1545a1d355fSStephan Aßmus {
1555a1d355fSStephan Aßmus 	if (fConnectionProvider)
1565a1d355fSStephan Aßmus 		fConnectionProvider->CloseServerConnection();
1575a1d355fSStephan Aßmus 
1585a1d355fSStephan Aßmus 	VirtualVolume::Uninit();
1595a1d355fSStephan Aßmus }
1605a1d355fSStephan Aßmus 
1615a1d355fSStephan Aßmus // PrepareToUnmount
1625a1d355fSStephan Aßmus void
PrepareToUnmount()1635a1d355fSStephan Aßmus ServerVolume::PrepareToUnmount()
1645a1d355fSStephan Aßmus {
1655a1d355fSStephan Aßmus 	VirtualVolume::PrepareToUnmount();
1665a1d355fSStephan Aßmus }
1675a1d355fSStephan Aßmus 
1685a1d355fSStephan Aßmus // HandleEvent
1695a1d355fSStephan Aßmus void
HandleEvent(VolumeEvent * event)1705a1d355fSStephan Aßmus ServerVolume::HandleEvent(VolumeEvent* event)
1715a1d355fSStephan Aßmus {
1725a1d355fSStephan Aßmus 	if (event->GetType() == CONNECTION_BROKEN_EVENT) {
1735a1d355fSStephan Aßmus 		// tell all share volumes that they have been disconnected
1745a1d355fSStephan Aßmus 
1755a1d355fSStephan Aßmus 		// init a directory iterator
1765a1d355fSStephan Aßmus 		fLock.Lock();
1775a1d355fSStephan Aßmus 		VirtualDirIterator iterator;
1785a1d355fSStephan Aßmus 		iterator.SetDirectory(fRootNode, true);
1795a1d355fSStephan Aßmus 
1805a1d355fSStephan Aßmus 		// iterate through the directory
1815a1d355fSStephan Aßmus 		const char* name;
1825a1d355fSStephan Aßmus 		Node* node;
1835a1d355fSStephan Aßmus 		while (iterator.GetCurrentEntry(&name, &node)) {
1845a1d355fSStephan Aßmus 			iterator.NextEntry();
1855a1d355fSStephan Aßmus 			Volume* volume = fVolumeManager->GetVolume(node->GetID());
1865a1d355fSStephan Aßmus 			fLock.Unlock();
1875a1d355fSStephan Aßmus 			if (ShareVolume* shareVolume = dynamic_cast<ShareVolume*>(volume))
1885a1d355fSStephan Aßmus 				shareVolume->ConnectionClosed();
1895a1d355fSStephan Aßmus 			if (volume)
1905a1d355fSStephan Aßmus 				volume->PutVolume();
1915a1d355fSStephan Aßmus 			fLock.Lock();
1925a1d355fSStephan Aßmus 		}
1935a1d355fSStephan Aßmus 
1945a1d355fSStephan Aßmus 		// uninit the directory iterator
1955a1d355fSStephan Aßmus 		iterator.SetDirectory(NULL);
1965a1d355fSStephan Aßmus 
1975a1d355fSStephan Aßmus 		// mark ourselves unmounting
1985a1d355fSStephan Aßmus 		SetUnmounting(true);
1995a1d355fSStephan Aßmus 		fLock.Unlock();
2005a1d355fSStephan Aßmus 	}
2015a1d355fSStephan Aßmus }
2025a1d355fSStephan Aßmus 
2035a1d355fSStephan Aßmus 
2045a1d355fSStephan Aßmus // #pragma mark -
2055a1d355fSStephan Aßmus // #pragma mark ----- FS -----
2065a1d355fSStephan Aßmus 
2075a1d355fSStephan Aßmus // Unmount
2085a1d355fSStephan Aßmus status_t
Unmount()2095a1d355fSStephan Aßmus ServerVolume::Unmount()
2105a1d355fSStephan Aßmus {
2115a1d355fSStephan Aßmus 	return B_OK;
2125a1d355fSStephan Aßmus }
2135a1d355fSStephan Aßmus 
2145a1d355fSStephan Aßmus 
2155a1d355fSStephan Aßmus // #pragma mark -
2165a1d355fSStephan Aßmus // #pragma mark ----- queries -----
2175a1d355fSStephan Aßmus 
2185a1d355fSStephan Aßmus // OpenQuery
2195a1d355fSStephan Aßmus status_t
OpenQuery(const char * queryString,uint32 flags,port_id port,int32 token,QueryIterator ** _iterator)2205a1d355fSStephan Aßmus ServerVolume::OpenQuery(const char* queryString, uint32 flags, port_id port,
2215a1d355fSStephan Aßmus 	int32 token, QueryIterator** _iterator)
2225a1d355fSStephan Aßmus {
2235a1d355fSStephan Aßmus // TODO: Do nothing when there are no (mounted) shares.
2245a1d355fSStephan Aßmus 	// get connection
2255a1d355fSStephan Aßmus 	ServerConnection* serverConnection
2265a1d355fSStephan Aßmus 		= fConnectionProvider->GetExistingServerConnection();
2275a1d355fSStephan Aßmus 	if (!serverConnection)
2285a1d355fSStephan Aßmus 		return ERROR_NOT_CONNECTED;
2295a1d355fSStephan Aßmus 	RequestConnection* connection = serverConnection->GetRequestConnection();
2305a1d355fSStephan Aßmus 
2315a1d355fSStephan Aßmus 	// create a query iterator and add it to the query manager
2325a1d355fSStephan Aßmus 	ServerQueryIterator* iterator = new(std::nothrow) ServerQueryIterator(this);
2335a1d355fSStephan Aßmus 	if (!iterator)
2345a1d355fSStephan Aßmus 		return B_NO_MEMORY;
2355a1d355fSStephan Aßmus 	QueryManager* queryManager = fVolumeManager->GetQueryManager();
2365a1d355fSStephan Aßmus 	status_t error = queryManager->AddIterator(iterator);
2375a1d355fSStephan Aßmus 	if (error != B_OK) {
2385a1d355fSStephan Aßmus 		delete iterator;
2395a1d355fSStephan Aßmus 		return error;
2405a1d355fSStephan Aßmus 	}
2415a1d355fSStephan Aßmus 	QueryIteratorPutter iteratorPutter(queryManager, iterator);
2425a1d355fSStephan Aßmus 
2435a1d355fSStephan Aßmus 	// prepare the request
2445a1d355fSStephan Aßmus 	OpenQueryRequest request;
2455a1d355fSStephan Aßmus 	request.queryString.SetTo(queryString);
2465a1d355fSStephan Aßmus 	request.flags = flags;
2475a1d355fSStephan Aßmus 	request.port = port;
2485a1d355fSStephan Aßmus 	request.token = token;
2495a1d355fSStephan Aßmus 
2505a1d355fSStephan Aßmus 	// send the request
2515a1d355fSStephan Aßmus 	OpenQueryReply* reply;
2525a1d355fSStephan Aßmus 	error = SendRequest(connection, &request, &reply);
2535a1d355fSStephan Aßmus 	if (error != B_OK)
2545a1d355fSStephan Aßmus 		RETURN_ERROR(error);
2555a1d355fSStephan Aßmus 	ObjectDeleter<Request> replyDeleter(reply);
2565a1d355fSStephan Aßmus 	if (reply->error != B_OK)
2575a1d355fSStephan Aßmus 		RETURN_ERROR(reply->error);
2585a1d355fSStephan Aßmus 
2595a1d355fSStephan Aßmus 	// set the result
2605a1d355fSStephan Aßmus 	iterator->SetRemoteCookie(reply->cookie);
2615a1d355fSStephan Aßmus 	*_iterator = iterator;
2625a1d355fSStephan Aßmus 	iteratorPutter.Detach();
2635a1d355fSStephan Aßmus 	return B_OK;
2645a1d355fSStephan Aßmus }
2655a1d355fSStephan Aßmus 
2665a1d355fSStephan Aßmus // FreeQueryIterator
2675a1d355fSStephan Aßmus void
FreeQueryIterator(QueryIterator * _iterator)2685a1d355fSStephan Aßmus ServerVolume::FreeQueryIterator(QueryIterator* _iterator)
2695a1d355fSStephan Aßmus {
2705a1d355fSStephan Aßmus 	ServerQueryIterator* iterator
2715a1d355fSStephan Aßmus 		= dynamic_cast<ServerQueryIterator*>(_iterator);
2725a1d355fSStephan Aßmus 
2735a1d355fSStephan Aßmus 	int32 cookie = iterator->GetRemoteCookie();
2745a1d355fSStephan Aßmus 	if (cookie >= 0) {
2755a1d355fSStephan Aßmus 		// prepare the close request
2765a1d355fSStephan Aßmus 		CloseRequest request;
2775a1d355fSStephan Aßmus 		request.volumeID = -1;
2785a1d355fSStephan Aßmus 		request.cookie = cookie;
2795a1d355fSStephan Aßmus 
2805a1d355fSStephan Aßmus 		// send the request
2815a1d355fSStephan Aßmus 		ServerConnection* serverConnection
2825a1d355fSStephan Aßmus 			= fConnectionProvider->GetExistingServerConnection();
2835a1d355fSStephan Aßmus 		if (serverConnection && serverConnection->IsConnected()) {
2845a1d355fSStephan Aßmus 			CloseReply* reply;
2855a1d355fSStephan Aßmus 			status_t error = SendRequest(
2865a1d355fSStephan Aßmus 				serverConnection->GetRequestConnection(), &request, &reply);
2875a1d355fSStephan Aßmus 			if (error == B_OK)
2885a1d355fSStephan Aßmus 				delete reply;
2895a1d355fSStephan Aßmus 		}
2905a1d355fSStephan Aßmus 	}
2915a1d355fSStephan Aßmus 
2925a1d355fSStephan Aßmus 	delete iterator;
2935a1d355fSStephan Aßmus }
2945a1d355fSStephan Aßmus 
2955a1d355fSStephan Aßmus // ReadQuery
2965a1d355fSStephan Aßmus status_t
ReadQuery(QueryIterator * _iterator,struct dirent * buffer,size_t bufferSize,int32 count,int32 * countRead)2975a1d355fSStephan Aßmus ServerVolume::ReadQuery(QueryIterator* _iterator, struct dirent* buffer,
2985a1d355fSStephan Aßmus 	size_t bufferSize, int32 count, int32* countRead)
2995a1d355fSStephan Aßmus {
3005a1d355fSStephan Aßmus 	// get connection
3015a1d355fSStephan Aßmus 	ServerConnection* serverConnection
3025a1d355fSStephan Aßmus 		= fConnectionProvider->GetExistingServerConnection();
3035a1d355fSStephan Aßmus 	if (!serverConnection)
3045a1d355fSStephan Aßmus 		return ERROR_NOT_CONNECTED;
3055a1d355fSStephan Aßmus 	RequestConnection* connection = serverConnection->GetRequestConnection();
3065a1d355fSStephan Aßmus 
3075a1d355fSStephan Aßmus 	ServerQueryIterator* iterator
3085a1d355fSStephan Aßmus 		= dynamic_cast<ServerQueryIterator*>(_iterator);
3095a1d355fSStephan Aßmus 
3105a1d355fSStephan Aßmus 	*countRead = 0;
3115a1d355fSStephan Aßmus 
3125a1d355fSStephan Aßmus 	for (;;) {
3135a1d355fSStephan Aßmus 		// if the iterator hasn't cached any more share volume IDs, we need to
3145a1d355fSStephan Aßmus 		// ask the server for the next entry
3155a1d355fSStephan Aßmus 		if (!iterator->HasNextShareVolumeID()) {
3165a1d355fSStephan Aßmus 			// prepare the request
3175a1d355fSStephan Aßmus 			ReadQueryRequest request;
3185a1d355fSStephan Aßmus 			request.cookie = iterator->GetRemoteCookie();
3195a1d355fSStephan Aßmus 			request.count = 1;
3205a1d355fSStephan Aßmus 
3215a1d355fSStephan Aßmus 			// send the request
3225a1d355fSStephan Aßmus 			ReadQueryReply* reply;
3235a1d355fSStephan Aßmus 			status_t error = SendRequest(connection, &request, &reply);
3245a1d355fSStephan Aßmus 			if (error != B_OK)
3255a1d355fSStephan Aßmus 				RETURN_ERROR(error);
3265a1d355fSStephan Aßmus 			ObjectDeleter<Request> replyDeleter(reply);
3275a1d355fSStephan Aßmus 			if (reply->error != B_OK)
3285a1d355fSStephan Aßmus 				RETURN_ERROR(reply->error);
3295a1d355fSStephan Aßmus 
3305a1d355fSStephan Aßmus 			// check, if anything has been read at all
3315a1d355fSStephan Aßmus 			if (reply->count == 0) {
3325a1d355fSStephan Aßmus 				*countRead = 0;
3335a1d355fSStephan Aßmus 				return B_OK;
3345a1d355fSStephan Aßmus 			}
3355a1d355fSStephan Aßmus 
3365a1d355fSStephan Aßmus 			// update the iterator
3375a1d355fSStephan Aßmus 			error = iterator->SetEntry(reply->clientVolumeIDs.GetElements(),
3385a1d355fSStephan Aßmus 				reply->clientVolumeIDs.CountElements(), reply->dirInfo,
3395a1d355fSStephan Aßmus 				reply->entryInfo);
3405a1d355fSStephan Aßmus 			if (error != B_OK)
3415a1d355fSStephan Aßmus 				return error;
3425a1d355fSStephan Aßmus 		}
3435a1d355fSStephan Aßmus 
3445a1d355fSStephan Aßmus 		// get the next concerned share volume and delegate the rest of the work
3455a1d355fSStephan Aßmus 		int32 volumeID = iterator->NextShareVolumeID();
3465a1d355fSStephan Aßmus 		ShareVolume* shareVolume = _GetShareVolume(volumeID);
3475a1d355fSStephan Aßmus 		if (!shareVolume)
3485a1d355fSStephan Aßmus 			continue;
3495a1d355fSStephan Aßmus 		VolumePutter volumePutter(shareVolume);
3505a1d355fSStephan Aßmus 
3515a1d355fSStephan Aßmus 		return shareVolume->GetQueryEntry(iterator->GetEntryInfo(),
3525a1d355fSStephan Aßmus 			iterator->GetDirectoryInfo(), buffer, bufferSize, countRead);
3535a1d355fSStephan Aßmus 	}
3545a1d355fSStephan Aßmus }
3555a1d355fSStephan Aßmus 
3565a1d355fSStephan Aßmus 
3575a1d355fSStephan Aßmus // #pragma mark -
3585a1d355fSStephan Aßmus // #pragma mark ----- private -----
3595a1d355fSStephan Aßmus 
3605a1d355fSStephan Aßmus // _AddShare
3615a1d355fSStephan Aßmus status_t
_AddShare(ExtendedShareInfo * shareInfo)3625a1d355fSStephan Aßmus ServerVolume::_AddShare(ExtendedShareInfo* shareInfo)
3635a1d355fSStephan Aßmus {
3645a1d355fSStephan Aßmus 	// create the share volume
3655a1d355fSStephan Aßmus 	ShareVolume* shareVolume = new(std::nothrow) ShareVolume(fVolumeManager,
3665a1d355fSStephan Aßmus 		fConnectionProvider, fServerInfo, shareInfo);
3675a1d355fSStephan Aßmus 	if (!shareVolume)
3685a1d355fSStephan Aßmus 		return B_NO_MEMORY;
3695a1d355fSStephan Aßmus 	status_t error = shareVolume->Init(shareInfo->GetShareName());
3705a1d355fSStephan Aßmus 	if (error != B_OK) {
3715a1d355fSStephan Aßmus 		delete shareVolume;
3725a1d355fSStephan Aßmus 		return error;
3735a1d355fSStephan Aßmus 	}
3745a1d355fSStephan Aßmus 
3755a1d355fSStephan Aßmus 	// add the volume to the volume manager
3765a1d355fSStephan Aßmus 	error = fVolumeManager->AddVolume(shareVolume);
3775a1d355fSStephan Aßmus 	if (error != B_OK) {
3785a1d355fSStephan Aßmus 		delete shareVolume;
3795a1d355fSStephan Aßmus 		return error;
3805a1d355fSStephan Aßmus 	}
3815a1d355fSStephan Aßmus 	VolumePutter volumePutter(shareVolume);
3825a1d355fSStephan Aßmus 
3835a1d355fSStephan Aßmus 	// add the volume to us
3845a1d355fSStephan Aßmus 	error = AddChildVolume(shareVolume);
3855a1d355fSStephan Aßmus 	if (error != B_OK) {
3865a1d355fSStephan Aßmus 		shareVolume->SetUnmounting(true);
3875a1d355fSStephan Aßmus 		return error;
3885a1d355fSStephan Aßmus 	}
3895a1d355fSStephan Aßmus 
3905a1d355fSStephan Aßmus 	return B_OK;
3915a1d355fSStephan Aßmus }
3925a1d355fSStephan Aßmus 
3935a1d355fSStephan Aßmus // _GetShareVolume
3945a1d355fSStephan Aßmus ShareVolume*
_GetShareVolume(int32 volumeID)3955a1d355fSStephan Aßmus ServerVolume::_GetShareVolume(int32 volumeID)
3965a1d355fSStephan Aßmus {
3975a1d355fSStephan Aßmus 	AutoLocker<Locker> locker(fLock);
3985a1d355fSStephan Aßmus 	VirtualDirIterator dirIterator;
3995a1d355fSStephan Aßmus 	dirIterator.SetDirectory(fRootNode, true);
4005a1d355fSStephan Aßmus 
4015a1d355fSStephan Aßmus 	// iterate through the directory
4025a1d355fSStephan Aßmus 	const char* name;
4035a1d355fSStephan Aßmus 	Node* node;
4045a1d355fSStephan Aßmus 	while (dirIterator.GetCurrentEntry(&name, &node)) {
4055a1d355fSStephan Aßmus 		Volume* volume = fVolumeManager->GetVolume(node->GetID());
4065a1d355fSStephan Aßmus 		ShareVolume* shareVolume = dynamic_cast<ShareVolume*>(volume);
4075a1d355fSStephan Aßmus 		if (shareVolume && shareVolume->GetID() == volumeID)
4085a1d355fSStephan Aßmus 			return shareVolume;
4095a1d355fSStephan Aßmus 
4105a1d355fSStephan Aßmus 		volume->PutVolume();
4115a1d355fSStephan Aßmus 		dirIterator.NextEntry();
4125a1d355fSStephan Aßmus 	}
4135a1d355fSStephan Aßmus 
4145a1d355fSStephan Aßmus 	return NULL;
4155a1d355fSStephan Aßmus }
4165a1d355fSStephan Aßmus 
417