void thread_connect() {
		connected.store(false);

		do {
			struct sockaddr_in addr;
			int      r;
			hostent* h;

			memset((void*)&addr, 0, sizeof(addr));
			addr.sin_addr.s_addr = inet_addr(ip.c_str());
			if(INADDR_NONE == addr.sin_addr.s_addr) {
				h = gethostbyname(ip.c_str());
				if(NULL == h) {
					perror("Could not get host by name");
					break;;
				}
			} else {
				h = gethostbyaddr((const char*)&addr.sin_addr, sizeof(struct sockaddr_in), AF_INET);
				if(NULL == h) {
					perror("Could not get host by address");
					break;;
				}
			}

			sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
			if(INVALID_SOCKET == sock) {
				perror("Could not create socket");
				break;
			}

			BOOL bDontLinger = TRUE;
			setsockopt( sock, SOL_SOCKET, SO_DONTLINGER, ( const char* )&bDontLinger, sizeof( BOOL ) );

			addr.sin_family = AF_INET;
			addr.sin_addr   = *((in_addr*)*h->h_addr_list);
			addr.sin_port   = htons(port);

			printf("Connecting... ");
			r = connect(sock, (sockaddr*)&addr, sizeof(struct sockaddr));
			if(SOCKET_ERROR == r) {
				printf("Cannot connect to server%d\n", get_errno());
				break;
			}
			printf("connected.\n");

			connected.store(true);
			connecting.store(false);
			sender.swap(std::thread(std::bind(&transport_t::thread_send, this)));
			recver.swap(std::thread(std::bind(&transport_t::thread_recv, this)));
			return;
		} while (0);

		connecting.store(false);
	}
void StartLogging(std::thread& thread) {
  auto& log_manager = logging::LogManager::GetInstance();
  if (peloton_logging_mode != LOGGING_TYPE_INVALID) {
    // Launching a thread for logging
    if (!log_manager.IsInLoggingMode()) {
      // Wait for standby mode
      auto local_thread = std::thread(
          &peloton::logging::LogManager::StartStandbyMode, &log_manager);
      thread.swap(local_thread);
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_STANDBY,
                                        true);

      // Clean up database tile state before recovery from checkpoint
      log_manager.PrepareRecovery();

      // Do any recovery
      log_manager.StartRecoveryMode();

      // Wait for logging mode
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_LOGGING,
                                        true);

      // Done recovery
      log_manager.DoneRecovery();
    }
  }
}
	void try_connect() {
		bool f = false;
		if (!connecting.compare_exchange_strong(f, true))
			return;
		
		connector.swap(std::thread(std::bind(&transport_t::thread_connect, this)));
		connector.detach();
		return;
	}
PLUGIN_EXPORT void Initialize(void** data, void* rm)
{
    if (g_measuresCnt == 0) // first time initialization
    {
        // start WMI query thread
        // waits for main thread to put Measures on g_queue for processing
        g_worker.swap(std::thread(QueryWorker));
    }

    Measure* measure = new Measure;
    *data = measure;
    ++g_measuresCnt;
}
/**
	@brief Signals that something very bad has happend
	@param msg Error description
	@isClient true, if this error has been issued by the client read-thread, and not the main thread
*/
void Die(const std::string msg)
{
	SOCKET old = sock;
	sock = INVALID_SOCKET;
	if (old)
		closesocket(old);
	std::cerr <<std::endl << msg<<std::endl;
	netThread.join();
	//netThread.detach();
	netThread.swap(std::thread());
	#ifdef _WIN32
		WSACleanup(); //Clean up Winsock
	#endif
	system("PAUSE");
	exit(-1);
}
int main(int argc, const char* argv[])
{
	#ifdef _WIN32
		//Start up Winsock…
		WSADATA wsadata;

		int error = WSAStartup(0x0202, &wsadata);
		if (error)	//Did something happen?
		{
			std::cerr<<"Unable to start winsock"<<std::endl;
			return -1;
		}

		if (wsadata.wVersion != 0x0202)//Did we get the right Winsock version?
		{
			Die("version mismatch");
		}
	#endif


	std::cout << "Enter Server URL: ";
	char url[0x100];
	std::cin.getline(url,sizeof(url));

	std::cout << "Enter your Nickname: ";
	char nickname[0x100] = ":";
	std::cin.getline(nickname+1,sizeof(nickname)-1);

	char*colon = strchr(url,':');
	std::string surl,sport;
	
	if (colon != NULL)
	{
		*colon = 0;
		sport = colon+1;
	}
	else
	{
		sport = ToString(DEFAULT_PORT);
	}
	surl = url;
	
	PrintLine("Attempting to connect to "+surl);

	ADDRINFOA hints;
	memset(&hints,0,sizeof(hints));
	hints.ai_protocol = IPPROTO_TCP;
    hints.ai_family = AF_UNSPEC;
	//hints.
	ADDRINFOA*result;
	if (getaddrinfo(surl.c_str(),sport.c_str(),&hints,&result) != 0)
	{
		Die("Call to getaddrinfo() failed");
	}

	bool connected = false;
	while (result)		//search through all available results until one allows connection. 
						//Chances are we get IPv4 and IPv6 results here but the server will only answer to one of those
	{
		sock = socket(result->ai_family,result->ai_socktype,result->ai_protocol);
		if (sock != INVALID_SOCKET)	//if we can create a socket then we can attempt a connection. It would be rather unusual for this not to work but...
		{
			if (!connect(sock,result->ai_addr,result->ai_addrlen))	//attempt connnection
			{
				//connected
				PrintLine("Connected to "+ToString(*result));	//yay, it worked
				connected = true;
				break;
			}
			else
			{
				closesocket(sock);		//these aren't the droids we're looking for.
				sock = INVALID_SOCKET;
			}

		}
		
		result = result->ai_next;	//moving on.
	}
	if (!connected)
		Die("Failed to connect to "+surl+":"+sport);	//so, yeah, none of them worked.

	Submit(nickname);	//includes leading ':', so that the server knows this is a name, not a message

	netThread = std::thread(NetLoop);	//start read-thread
	
	while (sock != INVALID_SOCKET)
	{
		char c = _getch();	//keep reading characters
		{
			if (c == 3)	//this only works on windows, but ctrl-c is handled better on linux anyway
			{
				Die("Ctrl+C");
				break;
			}
			consoleLock.lock();
			if (c == '\n' || c == '\r')							//user pressed enter/return:
			{
				std::string submit = inputBuffer;				//copy buffer to string
				std::cout << '\r';								//move cursor to line beginning
				for (size_t i = 0; i < inputBufferUsage+1; i++)	//overwrite line with as many blanks as there were characters
					std::cout << ' ';
				std::cout << '\r';								//move cursor to line beginning again
				inputBufferUsage = 0;							//reset character pointer
				inputBuffer[0] = 0;								//write terminating zero to first char
				consoleLock.unlock();							//release console lock
			
				Submit(submit);									//process input
			}
			else
			{
				if (c == Backspace)										//user pressed backspace
				{
					if (inputBufferUsage > 0)
					{
						inputBuffer[--inputBufferUsage] = 0;	//decrement character pointer and overwrite with 0
						std::cout << '\r'<<':'<<inputBuffer<<" \r"<<':'<<inputBuffer;
					}
				}
				else
				{
					if (c == '!' || c == '?' || ( c != -32 && (isalnum(c) || c == ' ')))	//ordinary character
					{
						if (inputBufferUsage+1 < maxInputBufferUsage)	//only allow up to 255 characters though
						{
							inputBuffer[inputBufferUsage++] = c;	//write to the end of the buffer
							inputBuffer[inputBufferUsage] = 0;		//and terminate properly
						}
						std::cout << c;		//update console
					}
				}
				consoleLock.unlock();
			}
		}
	}
	netThread.join();
	netThread.detach();
	netThread.swap(std::thread());
	#ifdef _WIN32
		WSACleanup();
	#endif
	return 0;
}