예제 #1
0
			virtual void OnThreadExecute(void)
			{
				SetThreadName("CaptureServer");

				FileOutStream outStream(m_file);

				// Technically any Labels that get initialized on another thread bettween the barrier and loop
				// will get recorded twice, but OVRMonitor will handle that scenario gracefully.
				g_labelLock.Lock();
				for(Label *l=Label::GetHead(); l; l=l->GetNext())
				{
					SendLabelPacket(*l);
				}
				g_labelLock.Unlock();

				// Start CPU/GPU/Thermal sensors...
				StandardSensors stdsensors;
				if(CheckConnectionFlag(Enable_CPU_Clocks) || CheckConnectionFlag(Enable_GPU_Clocks) || CheckConnectionFlag(Enable_Thermal_Sensors))
				{
					stdsensors.Start();
				}

				// as long as we are running, continuously flush the latest stream data to disk...
				while(!QuitSignaled())
				{
					const UInt64 flushBeginTime = GetNanoseconds();
					if(!AsyncStream::FlushAll(outStream))
					{
						break;
					}
					const UInt64 flushEndTime   = GetNanoseconds();
					const UInt64 flushDeltaTime = flushEndTime - flushBeginTime;
					const UInt64 sleepTime      = 4000000; // 4ms
					if(flushDeltaTime < sleepTime)
					{
						// Sleep just a bit to keep the thread from killing a core and to let a good chunk of data build up
						ThreadSleepNanoseconds((UInt32)(sleepTime - flushDeltaTime));
					}
				}

				// Clear the connection flags...
				AtomicExchange(g_connectionFlags, (UInt32)0);

				// Close down our sensor thread...
				stdsensors.QuitAndWait();
			}
예제 #2
0
            virtual void OnThreadExecute(void)
            {
                SetThreadName("OVR::Capture");
                while(m_listenSocket && !QuitSignaled())
                {
                    // try and accept a new socket connection...
                    SocketAddress streamAddr;
                    m_streamSocket = m_listenSocket->Accept(streamAddr);

                    // If no connection was established, something went totally wrong and we should just abort...
                    if(!m_streamSocket)
                        break;
                    
                    // Before we start sending capture data... first must exchange connection headers...
                    // First attempt to read in the request header from the Client...
                    ConnectionHeaderPacket clientHeader = {0};
                    if(!m_streamSocket->Receive(&clientHeader, sizeof(clientHeader)))
                    {
                        m_streamSocket->Release();
                        m_streamSocket = NULL;
                        continue;
                    }

                    // Load our connection flags...
                    const UInt32 connectionFlags = clientHeader.flags & g_initFlags;
                    
                    // Build and send return header... We *always* send the return header so that if we don't
                    // like something (like version number or feature flags), the client has some hint as to
                    // what we didn't like.
                    ConnectionHeaderPacket serverHeader = {0};
                    serverHeader.size    = sizeof(serverHeader);
                    serverHeader.version = ConnectionHeaderPacket::s_version;
                    serverHeader.flags   = connectionFlags;
                    if(!m_streamSocket->Send(&serverHeader, sizeof(serverHeader)))
                    {
                        m_streamSocket->Release();
                        m_streamSocket = NULL;
                        continue;
                    }

                    // Check version number...
                    if(clientHeader.version != serverHeader.version)
                    {
                        m_streamSocket->Release();
                        m_streamSocket = NULL;
                        continue;
                    }

                    // Check that we have any capture features even turned on...
                    if(!connectionFlags)
                    {
                        m_streamSocket->Release();
                        m_streamSocket = NULL;
                        continue;
                    }

                    // Finally, send our packet descriptors...
                    const PacketDescriptorPacket packetDescs[] =
                    {
                        BuildPacketDescriptorPacket<ThreadNamePacket>(),
                        BuildPacketDescriptorPacket<LabelPacket>(),
                        BuildPacketDescriptorPacket<FramePacket>(),
                        BuildPacketDescriptorPacket<VSyncPacket>(),
                        BuildPacketDescriptorPacket<CPUZoneEnterPacket>(),
                        BuildPacketDescriptorPacket<CPUZoneLeavePacket>(),
                        BuildPacketDescriptorPacket<GPUZoneEnterPacket>(),
                        BuildPacketDescriptorPacket<GPUZoneLeavePacket>(),
                        BuildPacketDescriptorPacket<GPUClockSyncPacket>(),
                        BuildPacketDescriptorPacket<SensorRangePacket>(),
                        BuildPacketDescriptorPacket<SensorPacket>(),
                        BuildPacketDescriptorPacket<FrameBufferPacket>(),
                        BuildPacketDescriptorPacket<LogPacket>(),
                    };
                    const PacketDescriptorHeaderPacket packetDescHeader = { sizeof(packetDescs) / sizeof(packetDescs[0]) };
                    if(!m_streamSocket->Send(&packetDescHeader, sizeof(packetDescHeader)))
                    {
                        m_streamSocket->Release();
                        m_streamSocket = NULL;
                        continue;
                    }
                    if(!m_streamSocket->Send(&packetDescs, sizeof(packetDescs)))
                    {
                        m_streamSocket->Release();
                        m_streamSocket = NULL;
                        continue;
                    }
                    
                    // Connection established!

                    // Signal that we are connected!
                    AtomicExchange(g_connectionFlags, connectionFlags);

                    // Technically any Labels that get initialized on another thread bettween the barrier and loop
                    // will get sent over the network twice, but OVRMonitor will handle that.
                    SpinLock(g_labelLock);
                    for(Label *l=Label::GetHead(); l; l=l->GetNext())
                    {
                        SendLabelPacket(*l);
                    }
                    SpinUnlock(g_labelLock);

                    // Start CPU/GPU/Thermal sensors...
                    StandardSensors stdsensors;
                    if(CheckConnectionFlag(Enable_CPU_Clocks) || CheckConnectionFlag(Enable_GPU_Clocks) || CheckConnectionFlag(Enable_Thermal_Sensors))
                    {
                        stdsensors.Start();
                    }

                    // Spin as long as we are connected flushing data from our data stream...
                    while(!QuitSignaled())
                    {
                        const UInt64 flushBeginTime = GetNanoseconds();
                        if(!AsyncStream::FlushAll(*m_streamSocket))
                        {
                            // Error occured... shutdown the connection.
                            AtomicExchange(g_connectionFlags, (UInt32)0);
                            m_streamSocket->Shutdown();
                            break;
                        }
                        const UInt64 flushEndTime   = GetNanoseconds();
                        const UInt64 flushDeltaTime = flushEndTime - flushBeginTime;
                        const UInt64 sleepTime      = 5000000; // 5ms
                        if(flushDeltaTime < sleepTime)
                        {
                            // Sleep just a bit to keep the thread from killing a core and to let a good chunk of data build up
                            ThreadSleepNanoseconds(sleepTime - flushDeltaTime);
                        }
                    }

                    // TODO: should we call AsyncStream::Shutdown() here???

                    // Close down our sensor thread...
                    stdsensors.QuitAndWait();

                    // Connection was closed at some point, lets clean up our socket...
                    m_streamSocket->Release();
                    m_streamSocket = NULL;

                } // while(m_listenSocket && !QuitSignaled())
            }
예제 #3
0
			virtual void OnThreadExecute(void)
			{
				SetThreadName("CaptureServer");

				// Acquire the process name...
			#if defined(OVR_CAPTURE_WINDOWS)
				char packageName[64] = {0};
				GetModuleFileNameA(NULL, packageName, sizeof(packageName));
				if(!packageName[0])
				{
					StringCopy(packageName, "Unknown", sizeof(packageName));
				}
			#else
				char packageName[64] = {0};
				char cmdlinepath[64] = {0};
				FormatString(cmdlinepath, sizeof(cmdlinepath), "/proc/%u/cmdline", (unsigned)getpid());
				if(ReadFileLine(cmdlinepath, packageName, sizeof(packageName)) <= 0)
				{
					StringCopy(packageName, "Unknown", sizeof(packageName));
				}
			#endif

				while(m_listenSocket && !QuitSignaled())
				{
					// Start auto-discovery thread...
					ZeroConfigHost *zeroconfig = ZeroConfigHost::Create(g_zeroConfigPort, m_listenPort, packageName);
					zeroconfig->Start();

					// try and accept a new socket connection...
					SocketAddress streamAddr;
					m_streamSocket = m_listenSocket->Accept(streamAddr);

					// Once connected, shut the auto-discovery thread down.
					zeroconfig->Release();

					// If no connection was established, something went totally wrong and we should just abort...
					if(!m_streamSocket)
						break;

					// Before we start sending capture data... first must exchange connection headers...
					// First attempt to read in the request header from the Client...
					ConnectionHeaderPacket clientHeader = {0};
					if(!m_streamSocket->Receive(&clientHeader, sizeof(clientHeader)))
					{
						m_streamSocket->Release();
						m_streamSocket = NULL;
						continue;
					}

					// Load our connection flags...
					const UInt32 connectionFlags = clientHeader.flags & g_initFlags;

					// Build and send return header... We *always* send the return header so that if we don't
					// like something (like version number or feature flags), the client has some hint as to
					// what we didn't like.
					ConnectionHeaderPacket serverHeader = {0};
					serverHeader.size    = sizeof(serverHeader);
					serverHeader.version = ConnectionHeaderPacket::s_version;
					serverHeader.flags   = connectionFlags;
					if(!m_streamSocket->Send(&serverHeader, sizeof(serverHeader)))
					{
						m_streamSocket->Release();
						m_streamSocket = NULL;
						continue;
					}

					// Check version number...
					if(clientHeader.version != serverHeader.version)
					{
						m_streamSocket->Release();
						m_streamSocket = NULL;
						continue;
					}

					// Check that we have any capture features even turned on...
					if(!connectionFlags)
					{
						m_streamSocket->Release();
						m_streamSocket = NULL;
						continue;
					}

					// Finally, send our packet descriptors...
					const PacketDescriptorHeaderPacket packetDescHeader = { g_numPacketDescs };
					if(!m_streamSocket->Send(&packetDescHeader, sizeof(packetDescHeader)))
					{
						m_streamSocket->Release();
						m_streamSocket = NULL;
						continue;
					}
					if(!m_streamSocket->Send(&g_packetDescs, sizeof(g_packetDescs)))
					{
						m_streamSocket->Release();
						m_streamSocket = NULL;
						continue;
					}

					// Connection established!

					// Initialize the per-thread stream system before flipping on g_connectionFlags...
					AsyncStream::Init();

					if(g_onConnect)
					{
						// Call back into the app to notify a connection is being established.
						// We intentionally do this before enabling the connection flags.
						g_onConnect(connectionFlags);
					}

					// Signal that we are connected!
					AtomicExchange(g_connectionFlags, connectionFlags);

					// Technically any Labels that get initialized on another thread bettween the barrier and loop
					// will get sent over the network twice, but OVRMonitor will handle that.
					g_labelLock.Lock();
					for(Label *l=Label::GetHead(); l; l=l->GetNext())
					{
						SendLabelPacket(*l);
					}
					g_labelLock.Unlock();

					// Start CPU/GPU/Thermal sensors...
					StandardSensors stdsensors;
					if(CheckConnectionFlag(Enable_CPU_Clocks) || CheckConnectionFlag(Enable_GPU_Clocks) || CheckConnectionFlag(Enable_Thermal_Sensors))
					{
						stdsensors.Start();
					}

					// Spin as long as we are connected flushing data from our data stream...
					while(!QuitSignaled())
					{
						const UInt64 flushBeginTime = GetNanoseconds();
						const UInt32 waitflags = m_streamSocket->WaitFor(Socket::WaitFlag_Read | Socket::WaitFlag_Write | Socket::WaitFlag_Timeout, 2);
						if(waitflags & Socket::WaitFlag_Timeout)
						{
							// Connection likely failed somehow...
							break;
						}
						if(waitflags & Socket::WaitFlag_Read)
						{
							PacketHeader header;
							VarSetPacket packet;
							m_streamSocket->Receive((char*)&header, sizeof(header));
							if (header.packetID == Packet_Var_Set)
							{
								m_streamSocket->Receive((char*)&packet, sizeof(packet));
								g_varStore.Set(packet.labelID, packet.value, true);
							}
							else
							{
								Logf(Log_Warning, "OVR::Capture::RemoteServer; Received Invalid Capture Packet");
							}
						}
						if(waitflags & Socket::WaitFlag_Write)
						{
							// Socket is ready to write data... so now is a good time to flush pending capture data.
							SocketOutStream outStream(*m_streamSocket);
							if(!AsyncStream::FlushAll(outStream))
							{
								// Error occured... shutdown the connection.
								break;
							}
						}
						const UInt64 flushEndTime   = GetNanoseconds();
						const UInt64 flushDeltaTime = flushEndTime - flushBeginTime;
						const UInt64 sleepTime      = 4000000; // 4ms
						if(flushDeltaTime < sleepTime)
						{
							// Sleep just a bit to keep the thread from killing a core and to let a good chunk of data build up
							ThreadSleepNanoseconds((UInt32)(sleepTime - flushDeltaTime));
						}
					}

					// Clear the connection flags...
					AtomicExchange(g_connectionFlags, (UInt32)0);

					// Close down our sensor thread...
					stdsensors.QuitAndWait();

					// Connection was closed at some point, lets clean up our socket...
					m_streamSocket->Shutdown();
					m_streamSocket->Release();
					m_streamSocket = NULL;

					if(g_onDisconnect)
					{
						// After the connection is fully shut down, notify the app.
						g_onDisconnect();
					}

					// Clear the buffers for all AsyncStreams to guarantee that no event is 
					// stalled waiting for room on a buffer. Then we wait until there there
					// are no events still writing out.
					AsyncStream::ClearAll();
					while(AtomicGet(g_refcount) > 0)
					{
						ThreadSleepMilliseconds(1);
					}

					// Finally, release any AsyncStreams that were created during this session
					// now that we can safely assume there are no events actively trying to
					// write out to a stream.
					AsyncStream::Shutdown();

					g_varStore.Clear();
				} // while(m_listenSocket && !QuitSignaled())
			}