| 140 | |
| 141 | |
| 142 | void TCPServerDispatcher::enqueue(const StreamSocket& socket) |
| 143 | { |
| 144 | FastMutex::ScopedLock lock(_mutex); |
| 145 | |
| 146 | ErrorHandler::logMessage(Message::PRIO_TEST, "Queue size: " + std::to_string(_queue.size()) + |
| 147 | ", current threads: " + std::to_string(_currentThreads) + |
| 148 | ", threads in pool: " + std::to_string(_threadPool.allocated()) + |
| 149 | ", current connections: " + std::to_string(_currentConnections)); |
| 150 | |
| 151 | |
| 152 | if (_queue.size() < _pParams->getMaxQueued()) |
| 153 | { |
| 154 | /// NOTE: the condition below is wrong. |
| 155 | /// Since the thread pool is shared between multiple servers/TCPServerDispatchers, |
| 156 | /// _currentThreads < _pParams->getMaxThreads() will be true when the pool is actually saturated. |
| 157 | /// As a result, queue is useless and connections never wait in queue. |
| 158 | /// Instead, we (mistakenly) think that we can create a thread for this connection, but we fail to create it |
| 159 | /// and the connection get rejected. |
| 160 | /// We could check _currentThreads < _threadPool.allocated() to make it work, |
| 161 | /// but it's not clear if we want to make it work |
| 162 | /// because it may be better to reject connection immediately if we don't have resources to handle it. |
| 163 | if (!_queue.hasIdleThreads() && _currentThreads < _pParams->getMaxThreads()) |
| 164 | { |
| 165 | try |
| 166 | { |
| 167 | this->duplicate(); |
| 168 | _threadPool.startWithPriority(_pParams->getThreadPriority(), *this, threadName); |
| 169 | ++_currentThreads; |
| 170 | } |
| 171 | catch (Poco::Exception& exc) |
| 172 | { |
| 173 | ErrorHandler::logMessage(Message::PRIO_WARNING, "Got an exception while starting thread for connection from " + |
| 174 | socket.peerAddress().toString()); |
| 175 | ErrorHandler::handle(exc); |
| 176 | this->release(); |
| 177 | ++_refusedConnections; |
| 178 | return; |
| 179 | } |
| 180 | } |
| 181 | else if (!_queue.hasIdleThreads()) |
| 182 | { |
| 183 | ErrorHandler::logMessage(Message::PRIO_TRACE, "Don't have idle threads, adding connection from " + |
| 184 | socket.peerAddress().toString() + " to the queue, size: " + std::to_string(_queue.size())); |
| 185 | } |
| 186 | _queue.enqueueNotification(new TCPConnectionNotification(socket)); |
| 187 | } |
| 188 | else |
| 189 | { |
| 190 | ErrorHandler::logMessage(Message::PRIO_WARNING, "Refusing connection from " + socket.peerAddress().toString() + |
| 191 | ", reached max queue size " + std::to_string(_pParams->getMaxQueued())); |
| 192 | ++_refusedConnections; |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | |
| 197 | void TCPServerDispatcher::stop() |
no test coverage detected