1// RequestThread.cpp
2
3#include <new>
4
5#include <TLS.h>
6
7#include "RequestThread.h"
8#include "ServerDefs.h"
9#include "UserlandRequestHandler.h"
10
11static const int32 sTLSVariable = tls_allocate();
12
13// constructor
14RequestThreadContext::RequestThreadContext(UserVolume* volume)
15	: fPreviousContext(NULL),
16	  fThread(NULL),
17	  fVolume(volume)
18{
19	fThread = RequestThread::GetCurrentThread();
20	if (fThread) {
21		fPreviousContext = fThread->GetContext();
22		fThread->SetContext(this);
23	}
24}
25
26// destructor
27RequestThreadContext::~RequestThreadContext()
28{
29	if (fThread)
30		fThread->SetContext(fPreviousContext);
31}
32
33// GetThread
34RequestThread*
35RequestThreadContext::GetThread() const
36{
37	return fThread;
38}
39
40// GetVolume
41UserlandFS::UserVolume*
42RequestThreadContext::GetVolume() const
43{
44	return fVolume;
45}
46
47
48// RequestThread
49
50// constructor
51RequestThread::RequestThread()
52	: fThread(-1),
53	  fFileSystem(NULL),
54	  fPort(NULL),
55	  fContext(NULL),
56	  fTerminating(false)
57{
58}
59
60// destructor
61RequestThread::~RequestThread()
62{
63	PrepareTermination();
64	Terminate();
65	delete fPort;
66}
67
68// Init
69status_t
70RequestThread::Init(UserFileSystem* fileSystem)
71{
72	if (!fileSystem)
73		return B_BAD_VALUE;
74	// create the port
75	fPort = new(nothrow) RequestPort(kRequestPortSize);
76	if (!fPort)
77		return B_NO_MEMORY;
78	status_t error = fPort->InitCheck();
79	if (error != B_OK)
80		return error;
81	// spawn the thread
82	fThread = spawn_thread(_ThreadEntry, "request thread", B_NORMAL_PRIORITY,
83		this);
84	if (fThread < 0)
85		return fThread;
86	fFileSystem = fileSystem;
87	return B_OK;
88}
89
90// Run
91void
92RequestThread::Run()
93{
94	resume_thread(fThread);
95}
96
97// PrepareTermination
98void
99RequestThread::PrepareTermination()
100{
101	if (fTerminating)
102		return;
103	fTerminating = true;
104	if (fPort)
105		fPort->Close();
106}
107
108// Terminate
109void
110RequestThread::Terminate()
111{
112	if (fThread >= 0) {
113		int32 result;
114		wait_for_thread(fThread, &result);
115		fThread = -1;
116	}
117}
118
119// GetPortInfo
120const Port::Info*
121RequestThread::GetPortInfo() const
122{
123	return (fPort ? fPort->GetPortInfo() : NULL);
124}
125
126// GetFileSystem
127UserlandFS::UserFileSystem*
128RequestThread::GetFileSystem() const
129{
130	return fFileSystem;
131}
132
133// GetPort
134RequestPort*
135RequestThread::GetPort() const
136{
137	return fPort;
138}
139
140// GetContext
141RequestThreadContext*
142RequestThread::GetContext() const
143{
144	return fContext;
145}
146
147// GetCurrentThread
148RequestThread*
149RequestThread::GetCurrentThread()
150{
151	return (RequestThread*)tls_get(sTLSVariable);
152}
153
154// SetContext
155void
156RequestThread::SetContext(RequestThreadContext* context)
157{
158	fContext = context;
159}
160
161// _ThreadEntry
162int32
163RequestThread::_ThreadEntry(void* data)
164{
165	return ((RequestThread*)data)->_ThreadLoop();
166}
167
168// _ThreadLoop
169int32
170RequestThread::_ThreadLoop()
171{
172	tls_set(sTLSVariable, this);
173	if (!fTerminating) {
174		UserlandRequestHandler handler(fFileSystem, false);
175		return fPort->HandleRequests(&handler);
176	}
177	return B_OK;
178}
179
180