xref: /haiku/src/add-ons/kernel/file_systems/netfs/shared/AbstractConnection.cpp (revision 99d027cd0238c1d86da86d7c3f4200509ccc61a6)
1 // AbstractConnection.cpp
2 
3 #include "AbstractConnection.h"
4 
5 #include <AutoLocker.h>
6 
7 #include "Channel.h"
8 #include "DebugSupport.h"
9 
10 // constructor
11 AbstractConnection::AbstractConnection()
12 	: Connection(),
13 	  fInitStatus(B_NO_INIT),
14 	  fDownStreamChannels(),
15 	  fUpStreamChannelSemaphore(-1),
16 	  fUpStreamChannelLock(),
17 	  fUpStreamChannels(),
18 	  fFreeUpStreamChannels(0)
19 {
20 }
21 
22 // destructor
23 AbstractConnection::~AbstractConnection()
24 {
25 	// Danger: If derived classes implement Close(), this call will not reach
26 	// them. So, the caller should rather call Close() explicitely before
27 	// destroying the connection.
28 	Close();
29 	// delete all channels
30 	for (ChannelVector::Iterator it = fDownStreamChannels.Begin();
31 		 it != fDownStreamChannels.End();
32 		 it++) {
33 		delete *it;
34 	}
35 	fDownStreamChannels.MakeEmpty();
36 	AutoLocker<Locker> _(fUpStreamChannelLock);
37 	for (ChannelVector::Iterator it = fUpStreamChannels.Begin();
38 		 it != fUpStreamChannels.End();
39 		 it++) {
40 		delete *it;
41 	}
42 	fUpStreamChannels.MakeEmpty();
43 }
44 
45 // Init
46 status_t
47 AbstractConnection::Init()
48 {
49 	fInitStatus = B_OK;
50 	// create upstream channel semaphore
51 	fUpStreamChannelSemaphore = create_sem(0, "upstream channels");
52 	if (fUpStreamChannelSemaphore < 0)
53 		return (fInitStatus = fUpStreamChannelSemaphore);
54 	return fInitStatus;
55 }
56 
57 // Close
58 void
59 AbstractConnection::Close()
60 {
61 	// close all channels
62 	for (ChannelVector::Iterator it = fDownStreamChannels.Begin();
63 		 it != fDownStreamChannels.End();
64 		 it++) {
65 		(*it)->Close();
66 	}
67 	AutoLocker<Locker> _(fUpStreamChannelLock);
68 	for (ChannelVector::Iterator it = fUpStreamChannels.Begin();
69 		 it != fUpStreamChannels.End();
70 		 it++) {
71 		(*it)->Close();
72 	}
73 }
74 
75 //// GetAuthorizedUser
76 //User*
77 //AbstractConnection::GetAuthorizedUser()
78 //{
79 //	return NULL;
80 //}
81 
82 // AddDownStreamChannel
83 status_t
84 AbstractConnection::AddDownStreamChannel(Channel* channel)
85 {
86 	if (!channel)
87 		return B_BAD_VALUE;
88 	return fDownStreamChannels.PushBack(channel);
89 }
90 
91 // AddUpStreamChannel
92 status_t
93 AbstractConnection::AddUpStreamChannel(Channel* channel)
94 {
95 	if (!channel)
96 		return B_BAD_VALUE;
97 	AutoLocker<Locker> _(fUpStreamChannelLock);
98 	status_t error = fUpStreamChannels.PushBack(channel);
99 	if (error != B_OK)
100 		return error;
101 	PutUpStreamChannel(channel);
102 	return B_OK;
103 }
104 
105 // CountDownStreamChannels
106 int32
107 AbstractConnection::CountDownStreamChannels() const
108 {
109 	return fDownStreamChannels.Count();
110 }
111 
112 // GetDownStreamChannel
113 Channel*
114 AbstractConnection::DownStreamChannelAt(int32 index) const
115 {
116 	if (index < 0 || index >= fDownStreamChannels.Count())
117 		return NULL;
118 	return fDownStreamChannels.ElementAt(index);
119 }
120 
121 // GetUpStreamChannel
122 status_t
123 AbstractConnection::GetUpStreamChannel(Channel** channel, bigtime_t timeout)
124 {
125 	if (!channel)
126 		return B_BAD_VALUE;
127 	if (timeout < 0)
128 		timeout = 0;
129 	// acquire the semaphore
130 	status_t error = acquire_sem_etc(fUpStreamChannelSemaphore, 1,
131 		B_RELATIVE_TIMEOUT, timeout);
132 	if (error != B_OK)
133 		return error;
134 	// we've acquire the semaphore successfully, so a free channel must be
135 	// waiting for us
136 	AutoLocker<Locker> _(fUpStreamChannelLock);
137 	if (fFreeUpStreamChannels < 1) {
138 		ERROR(("AbstractConnection::GetUpStreamChannel(): Acquired the "
139 			"upstream semaphore successfully, but there's no free channel!\n"));
140 		return B_ERROR;
141 	}
142 	fFreeUpStreamChannels--;
143 	*channel = fUpStreamChannels.ElementAt(fFreeUpStreamChannels);
144 	return B_OK;
145 }
146 
147 // PutUpStreamChannel
148 status_t
149 AbstractConnection::PutUpStreamChannel(Channel* channel)
150 {
151 	if (!channel)
152 		return B_BAD_VALUE;
153 	// find the channel
154 	AutoLocker<Locker> _(fUpStreamChannelLock);
155 	int32 index = fUpStreamChannels.IndexOf(channel, fFreeUpStreamChannels);
156 	if (index < 0)
157 		return B_BAD_VALUE;
158 	// swap it with the first non-free channel, release the semaphore,
159 	// and bump the free channel count
160 	if (index != fFreeUpStreamChannels) {
161 		Channel*& target = fUpStreamChannels.ElementAt(fFreeUpStreamChannels);
162 		fUpStreamChannels.ElementAt(index) = target;
163 		target = channel;
164 	}
165 	status_t error = release_sem(fUpStreamChannelSemaphore);
166 	if (error == B_OK)
167 		fFreeUpStreamChannels++;
168 	return error;
169 }
170 
171