<commit_before>/*
  A hacky replacement for backtrace_symbols in glibc

  backtrace_symbols in glibc looks up symbols using dladdr which is limited in
  the symbols that it sees. libbacktracesymbols opens the executable and shared
  libraries using libbfd and will look up backtrace information using the symbol
  table and the dwarf line information.

  It may make more sense for this program to use libelf instead of libbfd.
  However, I have not investigated that yet.

  Derived from addr2line.c from GNU Binutils by Jeff Muizelaar

  Copyright 2007 Jeff Muizelaar
*/

/* addr2line.c -- convert addresses to line number and function name
   Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
   Contributed by Ulrich Lauther <Ulrich.Lauther@mchp.siemens.de>

   This file was part of GNU Binutils.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.  */

#ifdef HASBFD

#include "util/Result.h"
#include "FindFile.h" // GetBinaryFilename

/* 2 characters for each byte, plus 1 each for 0, x, and NULL */
#define PTRSTR_LEN (sizeof(void *) * 2 + 3)

#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#ifdef __APPLE__
#include <bfd.h>
#include <dlfcn.h>
#else
#include <bfd.h>
#include <libiberty.h>
#include <dlfcn.h>
#include <link.h>
#endif

#if 0

void (*dbfd_init)(void);
bfd_vma (*dbfd_scan_vma)(const char *string, const char **end, int base);
bfd* (*dbfd_openr)(const char *filename, const char *target);
bfd_boolean (*dbfd_check_format)(bfd *abfd, bfd_format format);
bfd_boolean (*dbfd_check_format_matches)(bfd *abfd, bfd_format format, char ***matching);
bfd_boolean (*dbfd_close)(bfd *abfd);
bfd_boolean (*dbfd_map_over_sections)(bfd *abfd, void (*func)(bfd *abfd, asection *sect, void *obj),
		void *obj);
#define bfd_init dbfd_init

static void load_funcs(void)
{
	void * handle = dlopen("libbfd.so", RTLD_NOW);
	dbfd_init = dlsym(handle, "bfd_init");
	dbfd_scan_vma = dlsym(handle, "bfd_scan_vma");
	dbfd_openr = dlsym(handle, "bfd_openr");
	dbfd_check_format = dlsym(handle, "bfd_check_format");
	dbfd_check_format_matches = dlsym(handle, "bfd_check_format_matches");
	dbfd_close = dlsym(handle, "bfd_close");
	dbfd_map_over_sections = dlsym(handle, "bfd_map_over_sections");
}

#endif

static asymbol **syms;		/* Symbol table.  */

static Result slurp_symtab(bfd * abfd);
static void find_address_in_section(bfd *abfd, asection *section, void *data);

/* Read in the symbol table.  */

static Result slurp_symtab(bfd * abfd)
{
	if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
		return true;

	unsigned int size = 0;
	long symcount = bfd_read_minisymbols(abfd, false, (void**) &syms, &size);
	if (symcount == 0)
		symcount = bfd_read_minisymbols(abfd, true /* dynamic */ ,
						(void**) &syms, &size);

	if (symcount < 0)
		return false; //bfd_get_filename(abfd));

	return true;
}

/* These global variables are used to pass information between
   translate_addresses and find_address_in_section.  */

static bfd_vma pc;
static const char *filename;
static const char *functionname;
static unsigned int line;
static bool found = false;
static bool sectionFound = false;

/* Look for an address in a section.  This is called via
   bfd_map_over_sections.  */

static void find_address_in_section(bfd *abfd, asection *section, void *data __attribute__ ((__unused__)) )
{
	bfd_vma vma;
	bfd_size_type size;

	if (found)
		return;

	if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
		return;

	vma = bfd_get_section_vma(abfd, section);
	if (pc < vma)
		return;

	size = bfd_section_size(abfd, section);
	if (pc >= vma + size)
		return;

	sectionFound = true;
	found = bfd_find_nearest_line(abfd, section, syms, pc - vma,
				      &filename, &functionname, &line);
}

static char** translate_addresses_buf(bfd * abfd, bfd_vma *addr, int naddr)
{
	int naddr_orig = naddr;
	char b;
	int total  = 0;
	enum State { Count, Print } state;
	char *buf = &b;
	int len = 0;
	char **ret_buf = NULL;
	/* iterate over the formating twice.
	 * the first time we count how much space we need
	 * the second time we do the actual printing */
	for (state=Count; state<=Print; state = State(int(state) + 1)) {
	if (state == Print) {
		ret_buf = (char**)malloc(total + sizeof(char*)*naddr);
		buf = (char*)(ret_buf + naddr);
		len = total;
	}
	while (naddr) {
		if (state == Print)
			ret_buf[naddr-1] = buf;
		pc = addr[naddr-1];

		sectionFound = false;
		found = false;
		bfd_map_over_sections(abfd, find_address_in_section, (PTR) NULL);

		if (!found) {
			std::string errMsg = "function not found";
			if(!sectionFound) errMsg = "section not found";
			total += snprintf(buf, len, "[0x%llx] <%s>", (long long unsigned int) addr[naddr-1], errMsg.c_str()) + 1;
		} else {
			const char *name;

			name = functionname;
			if (name == NULL || *name == '\0')
				name = "??";
			if (filename != NULL) {
				char *h;

				h = strrchr(filename, '/');
				if (h != NULL)
					filename = h + 1;
			}
			total += snprintf(buf, len, "%s:%u\t%s()", filename ? filename : "??",
			       line, name) + 1;

		}
		if (state == Print) {
			/* set buf just past the end of string */
			buf = buf + total + 1;
		}
		naddr--;
	}
	naddr = naddr_orig;
	}
	return ret_buf;
}
/* Process a file.  */

static Result process_file(const char *file_name, bfd_vma *addr, int naddr, char**& ret_buf)
{
	bfd *abfd;
	char **matching;

	abfd = bfd_openr(file_name, NULL);

	if (abfd == NULL)
		return "no abfd";

	if (bfd_check_format(abfd, bfd_archive))
		return "can not get addresses from archive";

	if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
		//bfd_nonfatal(bfd_get_filename(abfd));
		if (bfd_get_error() ==
		    bfd_error_file_ambiguously_recognized) {
			//list_matching_formats(matching);
			free(matching);
		}
		return "format does not match";
	}

	slurp_symtab(abfd);

	ret_buf = translate_addresses_buf(abfd, addr, naddr);

	free (syms);
	syms = NULL;

	bfd_close(abfd);
	return true;
}

#define MAX_DEPTH 16

struct file_match {
	const char *file;
	void *address;
	void *base;
	void *hdr;
};

#ifndef __APPLE__
static int find_matching_file(struct dl_phdr_info *info,
		size_t size, void *data)
{
	struct file_match *match = (struct file_match*) data;
	/* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
	long n;
	const ElfW(Phdr) *phdr;
	ElfW(Addr) load_base = info->dlpi_addr;
	phdr = info->dlpi_phdr;
	for (n = info->dlpi_phnum; --n >= 0; phdr++) {
		if (phdr->p_type == PT_LOAD) {
			ElfW(Addr) vaddr = phdr->p_vaddr + load_base;
			if (match->address >= vaddr && match->address < vaddr + phdr->p_memsz) {
				/* we found a match */
				match->file = info->dlpi_name;
				match->base = info->dlpi_addr;
			}
		}
	}
	return 0;
}
#endif

char **backtrace_symbols(void *const *buffer, int size)
{
	int stack_depth = size - 1;
	int x,y;
	/* discard calling function */
	int total = 0;

	char **final;
	char *f_strings;

	char*** locations = (char***)malloc(sizeof(char**) * (stack_depth+1));

	bfd_init();
	for(x=stack_depth, y=0; x>=0; x--, y++){
		char **ret_buf;
		bfd_vma addr = (bfd_vma)buffer[x];
		Result r = true;
#ifndef __APPLE__
		struct file_match match;
		match.address = buffer[x];
		dl_iterate_phdr(find_matching_file, &match);
		addr = buffer[x] - match.base;
		if (match.file && strlen(match.file))
			r = process_file(match.file, &addr, 1, ret_buf);
		else
#endif
			r = process_file(GetBinaryFilename(), &addr, 1, ret_buf);
		if(r)
			locations[x] = ret_buf;
		else {
			locations[x] = (char**)malloc(sizeof(char*));
			locations[x][0] = (char*)"<error>";
		}
		total += strlen(locations[x][0]) + 1;
	}

	/* allocate the array of char* we are going to return and extra space for
	 * all of the strings */
	final = (char**)malloc(total + (stack_depth + 1) * sizeof(char*));
	/* get a pointer to the extra space */
	f_strings = (char*)(final + stack_depth + 1);

	/* fill in all of strings and pointers */
	for(x=stack_depth; x>=0; x--){
		strcpy(f_strings, locations[x][0]);
		free(locations[x]);
		final[x] = f_strings;
		f_strings += strlen(f_strings) + 1;
	}

	free(locations);

	return final;
}

void
backtrace_symbols_fd(void *const *buffer, int size, int fd)
{
        int j;
        char **strings;

        strings = backtrace_symbols(buffer, size);
		if (strings == NULL) return;

        for (j = 0; j < size; j++)
		printf("%s\n", strings[j]);

        free(strings);
}

// Not sure on this. Linking failed on Mac.
// Found it here: http://www.mail-archive.com/uclinux-dev@uclinux.org/msg02347.html
#ifndef HAVE_LIBINTL_DGETTEXT
extern "C"
const char *libintl_dgettext (const char *domain, const char *msg)
{
  return msg;
}
#endif /* !HAVE_LIBINTL_DGETTEXT */

#endif // HASBFD
<commit_msg>cleanup<commit_after>/*
  A hacky replacement for backtrace_symbols in glibc

  backtrace_symbols in glibc looks up symbols using dladdr which is limited in
  the symbols that it sees. libbacktracesymbols opens the executable and shared
  libraries using libbfd and will look up backtrace information using the symbol
  table and the dwarf line information.

  It may make more sense for this program to use libelf instead of libbfd.
  However, I have not investigated that yet.

  Derived from addr2line.c from GNU Binutils by Jeff Muizelaar

  Copyright 2007 Jeff Muizelaar
*/

/* addr2line.c -- convert addresses to line number and function name
   Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
   Contributed by Ulrich Lauther <Ulrich.Lauther@mchp.siemens.de>

   This file was part of GNU Binutils.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.  */

#ifdef HASBFD

#include "util/Result.h"
#include "FindFile.h" // GetBinaryFilename
#include <iostream>
#include <sstream>
#include <vector>
#include <string>

/* 2 characters for each byte, plus 1 each for 0, x, and NULL */
#define PTRSTR_LEN (sizeof(void *) * 2 + 3)

#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#ifdef __APPLE__
#include <bfd.h>
#include <dlfcn.h>
#else
#include <bfd.h>
#include <libiberty.h>
#include <dlfcn.h>
#include <link.h>
#endif

#if 0

void (*dbfd_init)(void);
bfd_vma (*dbfd_scan_vma)(const char *string, const char **end, int base);
bfd* (*dbfd_openr)(const char *filename, const char *target);
bfd_boolean (*dbfd_check_format)(bfd *abfd, bfd_format format);
bfd_boolean (*dbfd_check_format_matches)(bfd *abfd, bfd_format format, char ***matching);
bfd_boolean (*dbfd_close)(bfd *abfd);
bfd_boolean (*dbfd_map_over_sections)(bfd *abfd, void (*func)(bfd *abfd, asection *sect, void *obj),
		void *obj);
#define bfd_init dbfd_init

static void load_funcs(void)
{
	void * handle = dlopen("libbfd.so", RTLD_NOW);
	dbfd_init = dlsym(handle, "bfd_init");
	dbfd_scan_vma = dlsym(handle, "bfd_scan_vma");
	dbfd_openr = dlsym(handle, "bfd_openr");
	dbfd_check_format = dlsym(handle, "bfd_check_format");
	dbfd_check_format_matches = dlsym(handle, "bfd_check_format_matches");
	dbfd_close = dlsym(handle, "bfd_close");
	dbfd_map_over_sections = dlsym(handle, "bfd_map_over_sections");
}

#endif

static asymbol **syms;		/* Symbol table.  */

static Result slurp_symtab(bfd * abfd);
static void find_address_in_section(bfd *abfd, asection *section, void *data);

/* Read in the symbol table.  */

static Result slurp_symtab(bfd * abfd)
{
	if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
		return true;

	unsigned int size = 0;
	long symcount = bfd_read_minisymbols(abfd, false, (void**) &syms, &size);
	if (symcount == 0)
		symcount = bfd_read_minisymbols(abfd, true /* dynamic */ ,
						(void**) &syms, &size);

	if (symcount < 0)
		return false; //bfd_get_filename(abfd));

	return true;
}

/* These global variables are used to pass information between
   translate_addresses and find_address_in_section.  */

static bfd_vma pc;
static const char *filename;
static const char *functionname;
static unsigned int line;
static bool found = false;
static bool sectionFound = false;

/* Look for an address in a section.  This is called via
   bfd_map_over_sections.  */

static void find_address_in_section(bfd *abfd, asection *section, void *data __attribute__ ((__unused__)) )
{
	bfd_vma vma;
	bfd_size_type size;

	if (found)
		return;

	if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
		return;

	vma = bfd_get_section_vma(abfd, section);
	if (pc < vma)
		return;

	size = bfd_section_size(abfd, section);
	if (pc >= vma + size)
		return;

	sectionFound = true;
	found = bfd_find_nearest_line(abfd, section, syms, pc - vma,
				      &filename, &functionname, &line);
}

static std::string translate_addresses_buf(bfd * abfd, bfd_vma addr)
{
	std::ostringstream ret;

	pc = addr;
	sectionFound = false;
	found = false;
	bfd_map_over_sections(abfd, find_address_in_section, (PTR) NULL);

	if (!found) {
		ret.setf( std::ios::hex, std::ios::basefield );
		ret.setf( std::ios::showbase );
		ret << "[" << (long long unsigned int) addr << "] ";
		if(sectionFound) ret << "<function not found>";
		else ret << "<section not found>";

	} else {
		if (filename != NULL) {
			char *h = strrchr(filename, '/');
			if (h != NULL)
				filename = h + 1;

			ret << filename;
		}
		else
			ret << "<unknown file>";

		ret << ":" << line << "\t";

		if (functionname == NULL || *functionname == '\0')
			ret << "<unknown function>";
		else
			ret << functionname << "()";
	}

	return ret.str();
}
/* Process a file.  */

static Result process_file(const char *file_name, bfd_vma addr, std::string& ret_buf)
{
	bfd *abfd;
	char **matching;

	abfd = bfd_openr(file_name, NULL);

	if (abfd == NULL)
		return "no abfd";

	if (bfd_check_format(abfd, bfd_archive))
		return "can not get addresses from archive";

	if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
		//bfd_nonfatal(bfd_get_filename(abfd));
		if (bfd_get_error() ==
		    bfd_error_file_ambiguously_recognized) {
			//list_matching_formats(matching);
			free(matching);
		}
		return "format does not match";
	}

	slurp_symtab(abfd);

	ret_buf = translate_addresses_buf(abfd, addr);

	free (syms);
	syms = NULL;

	bfd_close(abfd);
	return true;
}

#define MAX_DEPTH 16

struct file_match {
	const char *file;
	void *address;
	void *base;
	void *hdr;
};

#ifndef __APPLE__
static int find_matching_file(struct dl_phdr_info *info,
		size_t size, void *data)
{
	struct file_match *match = (struct file_match*) data;
	/* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
	long n;
	const ElfW(Phdr) *phdr;
	ElfW(Addr) load_base = info->dlpi_addr;
	phdr = info->dlpi_phdr;
	for (n = info->dlpi_phnum; --n >= 0; phdr++) {
		if (phdr->p_type == PT_LOAD) {
			ElfW(Addr) vaddr = phdr->p_vaddr + load_base;
			if (match->address >= vaddr && match->address < vaddr + phdr->p_memsz) {
				/* we found a match */
				match->file = info->dlpi_name;
				match->base = info->dlpi_addr;
			}
		}
	}
	return 0;
}
#endif

char **backtrace_symbols(void *const *buffer, int size)
{
	int stack_depth = size - 1;
	int x,y;
	/* discard calling function */
	int total = 0;

	char **final;
	char *f_strings;

	std::vector<std::string> locations(stack_depth + 1);

	bfd_init();
	for(x=stack_depth, y=0; x>=0; x--, y++){
		std::string ret_buf;
		bfd_vma addr = (bfd_vma)buffer[x];
		Result r = true;
#ifndef __APPLE__
		struct file_match match;
		match.address = buffer[x];
		dl_iterate_phdr(find_matching_file, &match);
		addr = buffer[x] - match.base;
		if (match.file && strlen(match.file))
			r = process_file(match.file, addr, ret_buf);
		else
#endif
			r = process_file(GetBinaryFilename(), addr, ret_buf);
		if(r)
			locations[x] = ret_buf;
		else
			locations[x] = "<error>";
		total += locations[x].size() + 1;
	}

	/* allocate the array of char* we are going to return and extra space for
	 * all of the strings */
	final = (char**)malloc(total + (stack_depth + 1) * sizeof(char*));
	/* get a pointer to the extra space */
	f_strings = (char*)(final + stack_depth + 1);

	/* fill in all of strings and pointers */
	for(x=stack_depth; x>=0; x--){
		strcpy(f_strings, locations[x].c_str());
		final[x] = f_strings;
		f_strings += strlen(f_strings) + 1;
	}

	return final;
}

void
backtrace_symbols_fd(void *const *buffer, int size, int fd)
{
        int j;
        char **strings;

        strings = backtrace_symbols(buffer, size);
		if (strings == NULL) return;

        for (j = 0; j < size; j++)
		printf("%s\n", strings[j]);

        free(strings);
}

// Not sure on this. Linking failed on Mac.
// Found it here: http://www.mail-archive.com/uclinux-dev@uclinux.org/msg02347.html
#ifndef HAVE_LIBINTL_DGETTEXT
extern "C"
const char *libintl_dgettext (const char *domain, const char *msg)
{
  return msg;
}
#endif /* !HAVE_LIBINTL_DGETTEXT */

#endif // HASBFD
<|endoftext|>


<commit_before>#include <stdio.h>
#include "ServerListener.h"
#include "TcpServer.h"

//------------------------------------------------------------------------------
ServerListener::ServerListener()
{
   m_pListenerThread = NULL;
   m_pBalancerThread = NULL;
   m_nMinNodeCount = 1;
}

//------------------------------------------------------------------------------
ServerListener::~ServerListener()
{
   if (m_pListenerThread)
   {
      delete m_pListenerThread;
      m_pListenerThread = NULL;
   }

   if (m_pBalancerThread)
   {
      delete m_pBalancerThread;
      m_pBalancerThread = NULL;
   }
}

//------------------------------------------------------------------------------
void  ServerListener::setPort(ui32 port)
{
   m_nServerPort = port;
}

//------------------------------------------------------------------------------
bool  ServerListener::start()
{
   m_pListenerThread = Thread::Create(listenThreadFunc, this);

   if (m_pListenerThread == NULL)
   {
      printf("ServerListener::start: Failed to create listener thread.\n");
      return false;
   }

   m_pBalancerThread = Thread::Create(distribThreadFunc, this);

   if (m_pBalancerThread == NULL)
   {
      printf("ServerListener::start: Failed to create listener thread.\n");
      return false;
   }

   return true;
}

//------------------------------------------------------------------------------
bool  ServerListener::stop()
{
   if (m_pListenerThread)
   {
      m_pListenerThread->stop();
      m_pListenerThread->join();
   }

   if (m_pBalancerThread)
   {
      m_pBalancerThread->stop();
      m_pBalancerThread->join();
   }

   printf("ServerListener::stop: Stopped server.\n");

   return true;
}

//------------------------------------------------------------------------------
void  ServerListener::listenThreadFunc(ThreadArg* pArg)
{
   ((ServerListener*)pArg->pUserData)->listenThread(pArg);
}

//------------------------------------------------------------------------------
void  ServerListener::listenThread(ThreadArg* pArg)
{
   TcpServer   l_TcpServer;
   TcpSocket*  l_pSocket = NULL;

   ServerWorker*  l_pWorker = NULL;

   // Start the server on the specified port
   printf("ServerListener: Starting server on port #%d\n", m_nServerPort);
   l_TcpServer.start(m_nServerPort);

   // Main thread loop
   while (!pArg->stopSignalled())
   {
      l_pSocket = l_TcpServer.acceptClient(500);

      if (l_pSocket == NULL)
      {
         continue;
      }

      // The inheriting class overrides the createWorker method to create
      // the appropiriate type of worker.
      printf("ServerListener: Received connection. Creating worker.\n");
      l_pWorker = createWorker(l_pSocket);

      // If the worker was successfully created pass the worker to the
      // distribution and load balancing thread.
      if (l_pWorker)
      {
         distributeWorker(l_pWorker);
      }

      // We're now done with the pointers, so reset them to NULL.
      l_pWorker = NULL;
      l_pSocket = NULL;
   }

   // Stop the TCP server
   l_TcpServer.stop();
}

//------------------------------------------------------------------------------
ServerWorker*  ServerListener::createWorker(TcpSocket* pSocket)
{
   return NULL;
}

//------------------------------------------------------------------------------
bool ServerListener::distributeWorker(ServerWorker* pWorker)
{
   return m_qWorkerQueue.push(pWorker, 500);
}

//------------------------------------------------------------------------------
void  ServerListener::distribThreadFunc(ThreadArg* pArg)
{
   ((ServerListener*)pArg->pUserData)->distribThread(pArg);
}

//------------------------------------------------------------------------------
void  ServerListener::distribThread(ThreadArg* pArg)
{
   ui32  l_nCurrentNode = 0;
   ServerWorker*  l_pWorker = NULL;

   // Add and start the minimum number of nodes
   while (m_vNodeList.size() < m_nMinNodeCount)
   {
      ServerNode* l_pNode = NULL;

      l_pNode = new ServerNode();
      if (l_pNode == NULL)
      {
         printf("ServerListener::listenThread: Failed to allocate node\n");
         break;
      }

      // Start the node
      l_pNode->start();

      // Add the node to the node list
      m_vNodeList.push_back(l_pNode);
   }

   // Main thread loop
   while (!pArg->stopSignalled())
   {
      // Wait briefly for a new worker
      m_qWorkerQueue.pop(l_pWorker, 500);

      // If the worker is not NULL then we can add it to a server node.
      // Currently, round-robin is the only assignment policy.
      if (m_vNodeList[l_nCurrentNode] != NULL)
      {
         m_vNodeList[l_nCurrentNode]->addWorker(l_pWorker);

         l_nCurrentNode++;
      }
   }
}
<commit_msg>Forgot to initialize the worker queue in ServerListener<commit_after>#include <stdio.h>
#include "ServerListener.h"
#include "TcpServer.h"

//------------------------------------------------------------------------------
ServerListener::ServerListener()
{
   m_pListenerThread = NULL;
   m_pBalancerThread = NULL;
   m_nMinNodeCount = 1;
}

//------------------------------------------------------------------------------
ServerListener::~ServerListener()
{
   if (m_pListenerThread)
   {
      delete m_pListenerThread;
      m_pListenerThread = NULL;
   }

   if (m_pBalancerThread)
   {
      delete m_pBalancerThread;
      m_pBalancerThread = NULL;
   }
}

//------------------------------------------------------------------------------
void  ServerListener::setPort(ui32 port)
{
   m_nServerPort = port;
}

//------------------------------------------------------------------------------
bool  ServerListener::start()
{
   // Initialize the accepted worker queue
   m_qWorkerQueue.initialize(10);

   m_pListenerThread = Thread::Create(listenThreadFunc, this);

   if (m_pListenerThread == NULL)
   {
      printf("ServerListener::start: Failed to create listener thread.\n");
      return false;
   }

   m_pBalancerThread = Thread::Create(distribThreadFunc, this);

   if (m_pBalancerThread == NULL)
   {
      printf("ServerListener::start: Failed to create listener thread.\n");
      return false;
   }

   return true;
}

//------------------------------------------------------------------------------
bool  ServerListener::stop()
{
   if (m_pListenerThread)
   {
      m_pListenerThread->stop();
      m_pListenerThread->join();
   }

   if (m_pBalancerThread)
   {
      m_pBalancerThread->stop();
      m_pBalancerThread->join();
   }

   printf("ServerListener::stop: Stopped server.\n");

   return true;
}

//------------------------------------------------------------------------------
void  ServerListener::listenThreadFunc(ThreadArg* pArg)
{
   ((ServerListener*)pArg->pUserData)->listenThread(pArg);
}

//------------------------------------------------------------------------------
void  ServerListener::listenThread(ThreadArg* pArg)
{
   TcpServer   l_TcpServer;
   TcpSocket*  l_pSocket = NULL;

   ServerWorker*  l_pWorker = NULL;

   // Start the server on the specified port
   printf("ServerListener: Starting server on port #%d\n", m_nServerPort);
   l_TcpServer.start(m_nServerPort);

   // Main thread loop
   while (!pArg->stopSignalled())
   {
      l_pSocket = l_TcpServer.acceptClient(500);

      if (l_pSocket == NULL)
      {
         continue;
      }

      // The inheriting class overrides the createWorker method to create
      // the appropiriate type of worker.
      printf("ServerListener: Received connection. Creating worker.\n");
      l_pWorker = createWorker(l_pSocket);

      // If the worker was successfully created pass the worker to the
      // distribution and load balancing thread.
      if (l_pWorker)
      {
         distributeWorker(l_pWorker);
      }

      // We're now done with the pointers, so reset them to NULL.
      l_pWorker = NULL;
      l_pSocket = NULL;
   }

   // Stop the TCP server
   l_TcpServer.stop();
}

//------------------------------------------------------------------------------
ServerWorker*  ServerListener::createWorker(TcpSocket* pSocket)
{
   return NULL;
}

//------------------------------------------------------------------------------
bool ServerListener::distributeWorker(ServerWorker* pWorker)
{
   return m_qWorkerQueue.push(pWorker, 500);
}

//------------------------------------------------------------------------------
void  ServerListener::distribThreadFunc(ThreadArg* pArg)
{
   ((ServerListener*)pArg->pUserData)->distribThread(pArg);
}

//------------------------------------------------------------------------------
void  ServerListener::distribThread(ThreadArg* pArg)
{
   ui32  l_nCurrentNode = 0;
   ServerWorker*  l_pWorker = NULL;

   // Add and start the minimum number of nodes
   while (m_vNodeList.size() < m_nMinNodeCount)
   {
      ServerNode* l_pNode = NULL;

      l_pNode = new ServerNode();
      if (l_pNode == NULL)
      {
         printf("ServerListener::listenThread: Failed to allocate node\n");
         break;
      }

      // Start the node
      l_pNode->start();

      // Add the node to the node list
      m_vNodeList.push_back(l_pNode);
   }

   // Main thread loop
   while (!pArg->stopSignalled())
   {
      // Wait briefly for a new worker
      m_qWorkerQueue.pop(l_pWorker, 500);

      // If the worker is not NULL then we can add it to a server node.
      // Currently, round-robin is the only assignment policy.
      if (m_vNodeList[l_nCurrentNode] != NULL)
      {
         m_vNodeList[l_nCurrentNode]->addWorker(l_pWorker);

         l_nCurrentNode++;
      }
   }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// UniformHLSL.cpp:
//   Methods for GLSL to HLSL translation for uniforms and interface blocks.
//

#include "OutputHLSL.h"
#include "common/blocklayout.h"
#include "common/utilities.h"
#include "compiler/translator/UniformHLSL.h"
#include "compiler/translator/StructureHLSL.h"
#include "compiler/translator/util.h"
#include "compiler/translator/UtilsHLSL.h"

namespace sh
{

static const char *UniformRegisterPrefix(const TType &type)
{
    if (IsSampler(type.getBasicType()))
    {
        return "s";
    }
    else
    {
        return "c";
    }
}

static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
{
    if (interfaceBlock.hasInstanceName())
    {
        return interfaceBlock.name() + "." + field.name();
    }
    else
    {
        return field.name();
    }
}

static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
{
    const TType &fieldType = *field.type();
    const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
    ASSERT(matrixPacking != EmpUnspecified);
    TStructure *structure = fieldType.getStruct();

    if (fieldType.isMatrix())
    {
        // Use HLSL row-major packing for GLSL column-major matrices
        const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
        return matrixPackString + " " + TypeString(fieldType);
    }
    else if (structure)
    {
        // Use HLSL row-major packing for GLSL column-major matrices
        return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
            blockStorage == EbsStd140);
    }
    else
    {
        return TypeString(fieldType);
    }
}

static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
{
    return DecoratePrivate(interfaceBlock.name()) + "_type";
}

UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType)
    : mUniformRegister(0),
      mInterfaceBlockRegister(0),
      mSamplerRegister(0),
      mStructureHLSL(structureHLSL),
      mOutputType(outputType)
{}

void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
{
    mUniformRegister = registerCount;
}

void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount)
{
    mInterfaceBlockRegister = registerCount;
}

unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
{
    unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);

    GetVariableTraverser<Uniform> traverser(&mActiveUniforms);
    traverser.traverse(type, name);

    const sh::Uniform &activeUniform = mActiveUniforms.back();
    mUniformRegisterMap[activeUniform.name] = registerIndex;

    unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType);
    if (IsSampler(type.getBasicType()))
    {
        mSamplerRegister += registerCount;
    }
    else
    {
        mUniformRegister += registerCount;
    }

    return registerIndex;
}

TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms)
{
    TString uniforms;

    for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin();
         uniformIt != referencedUniforms.end(); uniformIt++)
    {
        const TIntermSymbol &uniform = *uniformIt->second;
        const TType &type = uniform.getType();
        const TString &name = uniform.getSymbol();

        unsigned int registerIndex = declareUniformAndAssignRegister(type, name);

        if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
        {
            uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) +
                        " : register(s" + str(registerIndex) + ");\n";

            uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) +
                        " : register(t" + str(registerIndex) + ");\n";
        }
        else
        {
            const TStructure *structure = type.getStruct();
            // If this is a nameless struct, we need to use its full definition, rather than its (empty) name.
            // TypeString() will invoke defineNameless in this case, but layout qualifiers will not be taken into
            // account in this case.
            // TODO: handle nameless structs with layout qualifiers.
            const TString &typeName = ((structure && !structure->name().empty()) ?
                                        QualifiedStructNameString(*structure, false, false) : TypeString(type));

            const TString &registerString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";

            uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n";
        }
    }

    return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms));
}

TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
{
    TString interfaceBlocks;

    for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
         interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
    {
        const TType &nodeType = interfaceBlockIt->second->getType();
        const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
        const TFieldList &fieldList = interfaceBlock.fields();

        unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
        unsigned int activeRegister = mInterfaceBlockRegister;

        InterfaceBlock activeBlock;
        activeBlock.name = interfaceBlock.name().c_str();
        activeBlock.arraySize = arraySize;

        for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++)
        {
            const TField &field = *fieldList[typeIndex];
            const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field);

            bool isRowMajor = (field.type()->getLayoutQualifier().matrixPacking == EmpRowMajor);
            GetInterfaceBlockFieldTraverser traverser(&activeBlock.fields, isRowMajor);
            traverser.traverse(*field.type(), fullFieldName);
        }

        mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister;
        mInterfaceBlockRegister += std::max(1u, arraySize);

        activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage());

        if (interfaceBlock.matrixPacking() == EmpRowMajor)
        {
            activeBlock.isRowMajorLayout = true;
        }

        mActiveInterfaceBlocks.push_back(activeBlock);

        if (interfaceBlock.hasInstanceName())
        {
            interfaceBlocks += interfaceBlockStructString(interfaceBlock);
        }

        if (arraySize > 0)
        {
            for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
            {
                interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
            }
        }
        else
        {
            interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
        }
    }

    return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks));
}

TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
{
    const TString &arrayIndexString =  (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
    const TString &blockName = interfaceBlock.name() + arrayIndexString;
    TString hlsl;

    hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
            "{\n";

    if (interfaceBlock.hasInstanceName())
    {
        hlsl += "    " + InterfaceBlockStructName(interfaceBlock) + " " +
                interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
    }
    else
    {
        const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
        hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage);
    }

    hlsl += "};\n\n";

    return hlsl;
}

TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
{
    if (!interfaceBlock.hasInstanceName())
    {
        return "";
    }
    else if (interfaceBlock.isArray())
    {
        return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
    }
    else
    {
        return Decorate(interfaceBlock.instanceName());
    }
}

TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
{
    TString hlsl;

    Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();

    for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
    {
        const TField &field = *interfaceBlock.fields()[typeIndex];
        const TType &fieldType = *field.type();

        if (blockStorage == EbsStd140)
        {
            // 2 and 3 component vector types in some cases need pre-padding
            hlsl += padHelper.prePadding(fieldType);
        }

        hlsl += "    " + InterfaceBlockFieldTypeString(field, blockStorage) +
                " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n";

        // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
        if (blockStorage == EbsStd140)
        {
            const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
            hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
        }
    }

    return hlsl;
}

TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
{
    const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();

    return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n"
           "{\n" +
           interfaceBlockMembersString(interfaceBlock, blockStorage) +
           "};\n\n";
}

}
<commit_msg>Amend comment about nameless structs & layout qualifiers<commit_after>//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// UniformHLSL.cpp:
//   Methods for GLSL to HLSL translation for uniforms and interface blocks.
//

#include "OutputHLSL.h"
#include "common/blocklayout.h"
#include "common/utilities.h"
#include "compiler/translator/UniformHLSL.h"
#include "compiler/translator/StructureHLSL.h"
#include "compiler/translator/util.h"
#include "compiler/translator/UtilsHLSL.h"

namespace sh
{

static const char *UniformRegisterPrefix(const TType &type)
{
    if (IsSampler(type.getBasicType()))
    {
        return "s";
    }
    else
    {
        return "c";
    }
}

static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field)
{
    if (interfaceBlock.hasInstanceName())
    {
        return interfaceBlock.name() + "." + field.name();
    }
    else
    {
        return field.name();
    }
}

static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
{
    const TType &fieldType = *field.type();
    const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
    ASSERT(matrixPacking != EmpUnspecified);
    TStructure *structure = fieldType.getStruct();

    if (fieldType.isMatrix())
    {
        // Use HLSL row-major packing for GLSL column-major matrices
        const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
        return matrixPackString + " " + TypeString(fieldType);
    }
    else if (structure)
    {
        // Use HLSL row-major packing for GLSL column-major matrices
        return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor,
            blockStorage == EbsStd140);
    }
    else
    {
        return TypeString(fieldType);
    }
}

static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
{
    return DecoratePrivate(interfaceBlock.name()) + "_type";
}

UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType)
    : mUniformRegister(0),
      mInterfaceBlockRegister(0),
      mSamplerRegister(0),
      mStructureHLSL(structureHLSL),
      mOutputType(outputType)
{}

void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
{
    mUniformRegister = registerCount;
}

void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount)
{
    mInterfaceBlockRegister = registerCount;
}

unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name)
{
    unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister);

    GetVariableTraverser<Uniform> traverser(&mActiveUniforms);
    traverser.traverse(type, name);

    const sh::Uniform &activeUniform = mActiveUniforms.back();
    mUniformRegisterMap[activeUniform.name] = registerIndex;

    unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType);
    if (IsSampler(type.getBasicType()))
    {
        mSamplerRegister += registerCount;
    }
    else
    {
        mUniformRegister += registerCount;
    }

    return registerIndex;
}

TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms)
{
    TString uniforms;

    for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin();
         uniformIt != referencedUniforms.end(); uniformIt++)
    {
        const TIntermSymbol &uniform = *uniformIt->second;
        const TType &type = uniform.getType();
        const TString &name = uniform.getSymbol();

        unsigned int registerIndex = declareUniformAndAssignRegister(type, name);

        if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))   // Also declare the texture
        {
            uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) +
                        " : register(s" + str(registerIndex) + ");\n";

            uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) +
                        " : register(t" + str(registerIndex) + ");\n";
        }
        else
        {
            const TStructure *structure = type.getStruct();
            // If this is a nameless struct, we need to use its full definition, rather than its (empty) name.
            // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for
            // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are
            // permitted.
            const TString &typeName = ((structure && !structure->name().empty()) ?
                                        QualifiedStructNameString(*structure, false, false) : TypeString(type));

            const TString &registerString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")";

            uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n";
        }
    }

    return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms));
}

TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks)
{
    TString interfaceBlocks;

    for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin();
         interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++)
    {
        const TType &nodeType = interfaceBlockIt->second->getType();
        const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
        const TFieldList &fieldList = interfaceBlock.fields();

        unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
        unsigned int activeRegister = mInterfaceBlockRegister;

        InterfaceBlock activeBlock;
        activeBlock.name = interfaceBlock.name().c_str();
        activeBlock.arraySize = arraySize;

        for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++)
        {
            const TField &field = *fieldList[typeIndex];
            const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field);

            bool isRowMajor = (field.type()->getLayoutQualifier().matrixPacking == EmpRowMajor);
            GetInterfaceBlockFieldTraverser traverser(&activeBlock.fields, isRowMajor);
            traverser.traverse(*field.type(), fullFieldName);
        }

        mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister;
        mInterfaceBlockRegister += std::max(1u, arraySize);

        activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage());

        if (interfaceBlock.matrixPacking() == EmpRowMajor)
        {
            activeBlock.isRowMajorLayout = true;
        }

        mActiveInterfaceBlocks.push_back(activeBlock);

        if (interfaceBlock.hasInstanceName())
        {
            interfaceBlocks += interfaceBlockStructString(interfaceBlock);
        }

        if (arraySize > 0)
        {
            for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
            {
                interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex);
            }
        }
        else
        {
            interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX);
        }
    }

    return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks));
}

TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
{
    const TString &arrayIndexString =  (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
    const TString &blockName = interfaceBlock.name() + arrayIndexString;
    TString hlsl;

    hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
            "{\n";

    if (interfaceBlock.hasInstanceName())
    {
        hlsl += "    " + InterfaceBlockStructName(interfaceBlock) + " " +
                interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
    }
    else
    {
        const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
        hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage);
    }

    hlsl += "};\n\n";

    return hlsl;
}

TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
{
    if (!interfaceBlock.hasInstanceName())
    {
        return "";
    }
    else if (interfaceBlock.isArray())
    {
        return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
    }
    else
    {
        return Decorate(interfaceBlock.instanceName());
    }
}

TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
{
    TString hlsl;

    Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper();

    for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
    {
        const TField &field = *interfaceBlock.fields()[typeIndex];
        const TType &fieldType = *field.type();

        if (blockStorage == EbsStd140)
        {
            // 2 and 3 component vector types in some cases need pre-padding
            hlsl += padHelper.prePadding(fieldType);
        }

        hlsl += "    " + InterfaceBlockFieldTypeString(field, blockStorage) +
                " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n";

        // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
        if (blockStorage == EbsStd140)
        {
            const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
            hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking);
        }
    }

    return hlsl;
}

TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
{
    const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();

    return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n"
           "{\n" +
           interfaceBlockMembersString(interfaceBlock, blockStorage) +
           "};\n\n";
}

}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "IndexServlet.h"
#include "SearchQuery.h"
#include "fnord-json/json.h"

using namespace fnord;

namespace cm {

IndexServlet::IndexServlet(
    RefPtr<cm::IndexReader> index,
    RefPtr<fts::Analyzer> analyzer) :
    index_(index),
    analyzer_(analyzer) {}

void IndexServlet::handleHTTPRequest(
    fnord::http::HTTPRequest* req,
    fnord::http::HTTPResponse* res) {
  URI uri(req->uri());

  res->addHeader("Access-Control-Allow-Origin", "*");

  try {
    if (StringUtil::endsWith(uri.path(), "/search")) {
      return searchQuery(req, res, &uri);
    }

    if (StringUtil::endsWith(uri.path(), "/doc")) {
      return fetchDoc(req, res, &uri);
    }

    if (StringUtil::endsWith(uri.path(), "/docs")) {
      return fetchDocs(req, res, &uri);
    }

    res->setStatus(fnord::http::kStatusNotFound);
    res->addBody("not found");
  } catch (const Exception& e) {
    res->setStatus(http::kStatusInternalServerError);
    res->addBody(StringUtil::format("error: $0", e.getMessage()));
  }
}

void IndexServlet::searchQuery(
    http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String query_str;
  if (!fnord::URI::getParam(params, "q", &query_str)) {
    res->addBody("error: missing ?q=... parameter");
    res->setStatus(http::kStatusBadRequest);
    return;
  }

  SearchQuery query;
  query.addField("title~de", 2.0);
  query.addField("text~de", 1.0);
  query.addQuery(query_str, Language::DE, analyzer_.get());
  query.execute(index_.get());

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/json; charset=utf-8");
  json::JSONOutputStream jsons(res->getBodyOutputStream());
  query.writeJSON(&jsons);
}

void IndexServlet::fetchDoc(
    http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String docid_str;
  if (!fnord::URI::getParam(params, "id", &docid_str)) {
    res->addBody("error: missing ?id=... parameter");
    res->setStatus(http::kStatusBadRequest);
    return;
  }

  DocID docid = { .docid = docid_str };
  auto txn = index_->db_->startTransaction(true);
  auto doc = index_->docIndex()->findDocument(docid, txn.get());
  txn->abort();

  auto fields = doc->fields();
  fields["docid"] = docid_str;

  auto doc_json = json::toJSONString(fields);
  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/json; charset=utf-8");
  res->addBody(doc_json);
}

void IndexServlet::fetchDocs(
    http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String docids_str;
  if (!fnord::URI::getParam(params, "ids", &docids_str)) {
    res->addBody("error: missing ?ids=... parameter");
    res->setStatus(http::kStatusBadRequest);
    return;
  }

  auto docid_strs = StringUtil::split(docids_str, ",");

  json::JSONObject json;
  json.emplace_back(json::JSON_OBJECT_BEGIN);

  for (const auto& docid_str : docid_strs) {
    DocID docid = { .docid = docid_str };
    auto txn = index_->db_->startTransaction(true);
    auto doc = index_->docIndex()->findDocument(docid, txn.get());
    txn->abort();

    auto fields = doc->fields();
    fields["docid"] = docid_str;

    json.emplace_back(json::JSON_STRING, docid_str);
    json::toJSON(fields, &json);
  }

  json.emplace_back(json::JSON_OBJECT_END);

  auto doc_json = json::toJSONString(json);
  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/json; charset=utf-8");
  res->addBody(doc_json);
}

}
<commit_msg>GET /index/docs field filter<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "IndexServlet.h"
#include "SearchQuery.h"
#include "fnord-json/json.h"

using namespace fnord;

namespace cm {

IndexServlet::IndexServlet(
    RefPtr<cm::IndexReader> index,
    RefPtr<fts::Analyzer> analyzer) :
    index_(index),
    analyzer_(analyzer) {}

void IndexServlet::handleHTTPRequest(
    fnord::http::HTTPRequest* req,
    fnord::http::HTTPResponse* res) {
  URI uri(req->uri());

  res->addHeader("Access-Control-Allow-Origin", "*");

  try {
    if (StringUtil::endsWith(uri.path(), "/search")) {
      return searchQuery(req, res, &uri);
    }

    if (StringUtil::endsWith(uri.path(), "/doc")) {
      return fetchDoc(req, res, &uri);
    }

    if (StringUtil::endsWith(uri.path(), "/docs")) {
      return fetchDocs(req, res, &uri);
    }

    res->setStatus(fnord::http::kStatusNotFound);
    res->addBody("not found");
  } catch (const Exception& e) {
    res->setStatus(http::kStatusInternalServerError);
    res->addBody(StringUtil::format("error: $0", e.getMessage()));
  }
}

void IndexServlet::searchQuery(
    http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String query_str;
  if (!fnord::URI::getParam(params, "q", &query_str)) {
    res->addBody("error: missing ?q=... parameter");
    res->setStatus(http::kStatusBadRequest);
    return;
  }

  SearchQuery query;
  query.addField("title~de", 2.0);
  query.addField("text~de", 1.0);
  query.addQuery(query_str, Language::DE, analyzer_.get());
  query.execute(index_.get());

  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/json; charset=utf-8");
  json::JSONOutputStream jsons(res->getBodyOutputStream());
  query.writeJSON(&jsons);
}

void IndexServlet::fetchDoc(
    http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String docid_str;
  if (!fnord::URI::getParam(params, "id", &docid_str)) {
    res->addBody("error: missing ?id=... parameter");
    res->setStatus(http::kStatusBadRequest);
    return;
  }

  DocID docid = { .docid = docid_str };
  auto txn = index_->db_->startTransaction(true);
  auto doc = index_->docIndex()->findDocument(docid, txn.get());
  txn->abort();

  auto fields = doc->fields();
  fields["docid"] = docid_str;

  auto doc_json = json::toJSONString(fields);
  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/json; charset=utf-8");
  res->addBody(doc_json);
}

void IndexServlet::fetchDocs(
    http::HTTPRequest* req,
    http::HTTPResponse* res,
    URI* uri) {
  const auto& params = uri->queryParams();

  String docids_str;
  if (!fnord::URI::getParam(params, "ids", &docids_str)) {
    res->addBody("error: missing ?ids=... parameter");
    res->setStatus(http::kStatusBadRequest);
    return;
  }

  auto docid_strs = StringUtil::split(docids_str, ",");

  Set<String> field_list;
  String fieldlist_str;
  if (fnord::URI::getParam(params, "fields", &fieldlist_str)) {
    for (const auto& f : StringUtil::split(fieldlist_str, ",")) {
      field_list.emplace(f);
    }
  }

  json::JSONObject json;
  json.emplace_back(json::JSON_OBJECT_BEGIN);

  for (const auto& docid_str : docid_strs) {
    DocID docid = { .docid = docid_str };
    auto txn = index_->db_->startTransaction(true);
    auto doc = index_->docIndex()->findDocument(docid, txn.get());
    txn->abort();

    auto fields = doc->fields();
    fields["docid"] = docid_str;
    if (field_list.size() > 0) {
      for (auto iter = fields.begin(); iter != fields.end(); ) {
        if (field_list.count(iter->first) == 0) {
          iter = fields.erase(iter);
        } else {
          ++iter;
        }
      }
    }

    json.emplace_back(json::JSON_STRING, docid_str);
    json::toJSON(fields, &json);
  }

  json.emplace_back(json::JSON_OBJECT_END);

  auto doc_json = json::toJSONString(json);
  res->setStatus(http::kStatusOK);
  res->addHeader("Content-Type", "application/json; charset=utf-8");
  res->addBody(doc_json);
}

}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2005-2007 by the FIFE Team                              *
 *   fife-public@lists.sourceforge.net                                     *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or modify          *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
 ***************************************************************************/

// Standard C++ library includes

// 3rd party library includes

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder
#include "map/map.h"
#include "map/objectinfo.h"
#include "map/view.h"
#include "map/visual.h"
#include "video/complexanimation.h"
#include "imagecache.h"
#include "log.h"

#include "setvisual.h"

namespace FIFE { namespace map { namespace command {

	void SetVisual::execute(const Info& cmd) {
		ObjectPtr moi = cmd.object;

		if (!moi) {
			Warn("mc_setvisual") << "No MOI for object " << cmd.object;
			return;
		}

		if (!moi->getLayer()) {
			Warn("mc_setvisual")
				<< "Cannot set visual for object not on map: "
				<< moi->getLocation();
			return;
		}

		if (moi->getElevation() != m_view->getElevationNum()) {
			Log("mc_setvisual") << "Setting visual for object not on map view.";
			moi->setVisualLocation(cmd.stringParam);
			return;
		}

		if (cmd.stringParam == "") {
			Log("mc_setvisual") << "Setting null-visual for object " << cmd.object;
			if (moi->getVisualId() && m_view) {
				m_view->removeVisual(moi->getVisualId());
			}
			moi->setVisualId(0);
			return;
		}

		if (m_view) {
			Visual* visual;
			if (moi->getVisualId()) {
				visual = m_view->getVisual(moi->getVisualId());
			} else {
				visual = new Visual(moi);
			}

			RenderableLocation loc(cmd.stringParam);
			loc.setType(RenderAble::RT_COMPLEX_ANIMATION);
			loc.setDirection(cmd.params[0]);
			moi->setVisualLocation(loc);

			visual->setRenderable(
				ImageCache::instance()->addImageFromLocation(loc),
				RenderAble::RT_COMPLEX_ANIMATION );
			ComplexAnimation* anim = visual->getComplexAnimation();
			if (anim) {
				anim->enqueueAction(Action(0, cmd.params[0]));
			}

			Debug("mc_setvisual")
				<< "Setting Visual: " << cmd.stringParam
				<< " for object type: "
				<< moi->get<std::string>(ObjectInfo::ObjectTypeParam);
			if (!moi->getVisualId()) {
				moi->setVisualId( m_view->addVisual(visual) );
			} else {
				if (m_view->getVisual(moi->getVisualId())) {
					m_view->notifyVisualChanged(moi->getVisualId());
				} else {
					moi->setVisualId( m_view->addVisual(visual) );
				}
			}
		} else { // !m_view
			moi->setVisualId(0);
		}
		moi->set<long>("_visual_id",moi->getVisualId());
		moi->set<std::string>("_visual_path",moi->getVisualLocation().toString());
	}
} } }
<commit_msg>This is the quick and dirty fix to the problem, that the map_control won't display any critters on a map that it already used.<commit_after>/***************************************************************************
 *   Copyright (C) 2005-2007 by the FIFE Team                              *
 *   fife-public@lists.sourceforge.net                                     *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or modify          *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
 ***************************************************************************/

// Standard C++ library includes

// 3rd party library includes

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder
#include "map/map.h"
#include "map/objectinfo.h"
#include "map/view.h"
#include "map/visual.h"
#include "video/complexanimation.h"
#include "imagecache.h"
#include "log.h"

#include "setvisual.h"

namespace FIFE { namespace map { namespace command {

	void SetVisual::execute(const Info& cmd) {
		ObjectPtr moi = cmd.object;

		if (!moi) {
			Warn("mc_setvisual") << "No MOI for object " << cmd.object;
			return;
		}

		if (!moi->getLayer()) {
			Warn("mc_setvisual")
				<< "Cannot set visual for object not on map: "
				<< moi->getLocation();
			return;
		}

		if (moi->getElevation() != m_view->getElevationNum()) {
			Log("mc_setvisual") << "Setting visual for object not on map view.";
			moi->setVisualLocation(cmd.stringParam);
			return;
		}

		if (cmd.stringParam == "") {
			Log("mc_setvisual") << "Setting null-visual for object " << cmd.object;
			if (moi->getVisualId() && m_view) {
				m_view->removeVisual(moi->getVisualId());
			}
			moi->setVisualId(0);
			return;
		}

		if (m_view) {
			Visual* visual;
			if (moi->getVisualId()) {
				visual = m_view->getVisual(moi->getVisualId());
			} else {
				visual = new Visual(moi);
			}

			RenderableLocation loc(cmd.stringParam);
			loc.setType(RenderAble::RT_COMPLEX_ANIMATION);
			loc.setDirection(cmd.params[0]);
			moi->setVisualLocation(loc);

			visual->setRenderable(
				ImageCache::instance()->addImageFromLocation(loc),
				loc.getType() );
			ComplexAnimation* anim = visual->getComplexAnimation();
			if (anim) {
				anim->enqueueAction(Action(0, cmd.params[0]));
			}

			Debug("mc_setvisual")
				<< "Setting Visual: " << cmd.stringParam
				<< " for object type: "
				<< moi->get<std::string>(ObjectInfo::ObjectTypeParam);
			if (!moi->getVisualId()) {
				moi->setVisualId( m_view->addVisual(visual) );
			} else {
				if (m_view->getVisual(moi->getVisualId())) {
					m_view->notifyVisualChanged(moi->getVisualId());
				} else {
					moi->setVisualId( m_view->addVisual(visual) );
				}
			}
		} else { // !m_view
			moi->setVisualId(0);
		}
		moi->set<long>("_visual_id",moi->getVisualId());
		moi->set<std::string>("_visual_path",moi->getVisualLocation().getFilename());
	}
} } }
<|endoftext|>


<commit_before>
/*
 * Copyright (C) 2010, Victor Semionov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

#include <string>
#include <vector>
#include <map>
#include <iostream>

#include "Poco/Util/ServerApplication.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Net/DNS.h"
#include "Poco/String.h"
#include "Poco/FileStream.h"
#include "Poco/LineEndingConverter.h"
#include "Poco/StringTokenizer.h"
#include "Poco/URI.h"
#include "Poco/Path.h"

#include "IndigoFiler.h"
#include "IndigoConfiguration.h"
#include "IndigoRequestHandler.h"
#include "ThreadPoolCollector.h"

using namespace std;

using namespace Poco;
using namespace Poco::Util;
using namespace Poco::Net;

class IndigoRequestHandlerFactory: public HTTPRequestHandlerFactory
{
public:
	HTTPRequestHandler *createRequestHandler(const HTTPServerRequest &request)
	{
		return new IndigoRequestHandler();
	}
};

class IndigoFiler: public ServerApplication
{
public:
	IndigoFiler(): helpRequested(false), versionRequested(false)
	{
	}

protected:
	void initialize(Application &self)
	{
		ServerApplication::initialize(self);

		string configPath = locateConfiguration(APP_NAME_UNIX "." "ini");
		loadConfiguration(configPath);
	}

	void uninitialize()
	{
		ServerApplication::uninitialize();
	}

	void defineOptions(OptionSet &options)
	{
		ServerApplication::defineOptions(options);

		options.addOption(
			Option("help", "h", "display help information on command line arguments")
				.required(false)
				.repeatable(false));

		options.addOption(
			Option("version", "v", "display version information")
				.required(false)
				.repeatable(false));
	}

	void handleOption(const string &name, const string &value)
	{
		ServerApplication::handleOption(name, value);

		if (name == "help")
			helpRequested = true;
		else if (name == "version")
			versionRequested = true;
	}

	int main(const vector<string> &args)
	{
		if (helpRequested)
		{
			displayHelp();
		}
		else if (versionRequested)
		{
			displayVersion();
		}
		else
		{
			const string serverSection = "Server";

			string serverName = config().getString(serverSection + "." + "name", "");
			if (serverName.empty())
				serverName = DNS::hostName();

			string root = config().getString(serverSection + "." + "root", "virtual");
			if (root == "virtual")
				root = "";

			string index = config().getString(serverSection + "." + "index", "index.html");

			const IndigoConfiguration &configuration = IndigoConfiguration::init(
				serverName,
				config().getString(serverSection + "." + "address", "0.0.0.0"),
				config().getInt(serverSection + "." + "port", 80),
				config().getInt(serverSection + "." + "backlog", 64),
				config().getInt(serverSection + "." + "minThreads", 2),
				config().getInt(serverSection + "." + "maxThreads", 16),
				config().getInt(serverSection + "." + "maxQueued", 64),
				config().getInt(serverSection + "." + "timeout", 60),
				config().getBool(serverSection + "." + "keepalive", true),
				config().getInt(serverSection + "." + "keepaliveTimeout", 15),
				config().getInt(serverSection + "." + "maxKeepaliveRequests", 0),
				config().getInt(serverSection + "." + "idleTime", 60),
				config().getInt(serverSection + "." + "threadIdleTime", 10),
				config().getBool(serverSection + "." + "collectIdleThreads", false),
				root,
				readIndexes(index),
				config().getBool(serverSection + "." + "autoIndex", true),
				readShares(),
				readMimeTypes()
				);
			configuration.validate();

			HTTPServerParams::Ptr params = new HTTPServerParams;
			params->setMaxThreads(configuration.getMaxThreads());
			params->setMaxQueued(configuration.getMaxQueued());
			params->setServerName(configuration.getServerName());
			params->setSoftwareVersion(APP_NAME_SHORT "/" APP_VERSION);
			params->setTimeout(configuration.getTimeout() * 1000000);
			params->setKeepAlive(configuration.getKeepalive());
			params->setKeepAliveTimeout(configuration.getKeepaliveTimeout() * 1000000);
			params->setMaxKeepAliveRequests(configuration.getMaxKeepaliveRequests());
			params->setThreadIdleTime(configuration.getThreadIdleTime() * 1000000);

			HTTPRequestHandlerFactory::Ptr factory = new IndigoRequestHandlerFactory();

			ThreadPool pool("workers", configuration.getMinThreads(), configuration.getMaxThreads(), configuration.getIdleTime());

			SocketAddress saddr(configuration.getAddress(), configuration.getPort());
			ServerSocket sock(saddr, configuration.getBacklog());

			// set the socket send timeout; not done in POCO
			sock.setSendTimeout(configuration.getTimeout() * 1000000);

			ThreadPoolCollector collector(pool);

			HTTPServer srv(factory, pool, sock, params);

			if (configuration.getCollectIdleThreads())
				collector.startCollecting();

			srv.start();

			waitForTerminationRequest();

			srv.stop();

			collector.stopCollecting();
		}

		return EXIT_OK;
	}

private:
	void displayHelp()
	{
		HelpFormatter helpFormatter(options());
		helpFormatter.setCommand(commandName());
		helpFormatter.setUsage("[options]");
		helpFormatter.setHeader("A simple web server for static content.");
		helpFormatter.format(cout);
	}

	void displayVersion()
	{
		cout << APP_NAME " " APP_VERSION << endl;
		cout << APP_COPYRIGHT_NOTICE;
	}

	set<string> readIndexes(const string &index)
	{
		set<string> indexes;

		StringTokenizer tok(index, " \t", StringTokenizer::TOK_IGNORE_EMPTY);
		int cnt = tok.count();
		for (int i = 0; i < cnt; i++)
		{
			string idx;
			URI::decode(tok[i], idx);
			poco_assert(idx.empty() == false);

			indexes.insert(idx);
		}

		return indexes;
	}

	map<string, string> readShares()
	{
		const string sharesSection = "VirtualRoot";

		map<string, string> shares;

		AbstractConfiguration::Keys keys;
		config().keys(sharesSection, keys);

		for (size_t i = 0; i < keys.size(); i++)
		{
			const string &shareName = keys[i];
			if (shareName.empty())
				continue;

			string sharePath = config().getString(sharesSection + "." + shareName, "");
			if (sharePath.empty())
				continue;

			string decodedShareName;
			URI::decode(shareName, decodedShareName);
			string decodedSharePath;
			URI::decode(sharePath, decodedSharePath);

			shares[decodedShareName] = decodedSharePath;
		}

		return shares;
	}

	void readMimeTypes(string filename, map<string, string> &mimeTypes)
	{
		string filepath = locateConfiguration(filename);

		FileInputStream fin(filepath);
		InputLineEndingConverter in(fin, LineEnding::NEWLINE_LF);

		string line;
		while (getline(in, line))
		{
			line = line.substr(0, line.find('#'));

			StringTokenizer tok(line, " \t", StringTokenizer::TOK_IGNORE_EMPTY);
			int cnt = tok.count();
			if (cnt >= 2)
			{
				const string &type = tok[0];
				poco_assert(type.empty() == false);

				for (int i = 1; i < cnt; i++)
				{
					const string &ext = tok[i];
					poco_assert(ext.empty() == false);

					mimeTypes[ext] = type;
				}
			}
		}
	}

	map<string, string> readMimeTypes()
	{
		map<string, string> mimeTypes;

		readMimeTypes("mime.types", mimeTypes);
		readMimeTypes("mime.types.extra", mimeTypes);
		readMimeTypes("mime.types.user", mimeTypes);

		return mimeTypes;
	}

	string locateConfiguration(const string &filename)
	{
		string dir = config().getString("application.dir");
		Path path(dir);
		path.makeDirectory().setFileName(filename);
		return path.toString();
	}

	bool helpRequested;
	bool versionRequested;
};

int main(int argc, char **argv)
{
	IndigoFiler indigo;
	return indigo.run(argc, argv);
}
<commit_msg>Disable SO_REUSEADDR on the server socket.<commit_after>
/*
 * Copyright (C) 2010, Victor Semionov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

#include <string>
#include <vector>
#include <map>
#include <iostream>

#include "Poco/Util/ServerApplication.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Net/DNS.h"
#include "Poco/String.h"
#include "Poco/FileStream.h"
#include "Poco/LineEndingConverter.h"
#include "Poco/StringTokenizer.h"
#include "Poco/URI.h"
#include "Poco/Path.h"

#include "IndigoFiler.h"
#include "IndigoConfiguration.h"
#include "IndigoRequestHandler.h"
#include "ThreadPoolCollector.h"

using namespace std;

using namespace Poco;
using namespace Poco::Util;
using namespace Poco::Net;

class IndigoRequestHandlerFactory: public HTTPRequestHandlerFactory
{
public:
	HTTPRequestHandler *createRequestHandler(const HTTPServerRequest &request)
	{
		return new IndigoRequestHandler();
	}
};

class IndigoFiler: public ServerApplication
{
public:
	IndigoFiler(): helpRequested(false), versionRequested(false)
	{
	}

protected:
	void initialize(Application &self)
	{
		ServerApplication::initialize(self);

		string configPath = locateConfiguration(APP_NAME_UNIX "." "ini");
		loadConfiguration(configPath);
	}

	void uninitialize()
	{
		ServerApplication::uninitialize();
	}

	void defineOptions(OptionSet &options)
	{
		ServerApplication::defineOptions(options);

		options.addOption(
			Option("help", "h", "display help information on command line arguments")
				.required(false)
				.repeatable(false));

		options.addOption(
			Option("version", "v", "display version information")
				.required(false)
				.repeatable(false));
	}

	void handleOption(const string &name, const string &value)
	{
		ServerApplication::handleOption(name, value);

		if (name == "help")
			helpRequested = true;
		else if (name == "version")
			versionRequested = true;
	}

	int main(const vector<string> &args)
	{
		if (helpRequested)
		{
			displayHelp();
		}
		else if (versionRequested)
		{
			displayVersion();
		}
		else
		{
			const string serverSection = "Server";

			string serverName = config().getString(serverSection + "." + "name", "");
			if (serverName.empty())
				serverName = DNS::hostName();

			string root = config().getString(serverSection + "." + "root", "virtual");
			if (root == "virtual")
				root = "";

			string index = config().getString(serverSection + "." + "index", "index.html");

			const IndigoConfiguration &configuration = IndigoConfiguration::init(
				serverName,
				config().getString(serverSection + "." + "address", "0.0.0.0"),
				config().getInt(serverSection + "." + "port", 80),
				config().getInt(serverSection + "." + "backlog", 64),
				config().getInt(serverSection + "." + "minThreads", 2),
				config().getInt(serverSection + "." + "maxThreads", 16),
				config().getInt(serverSection + "." + "maxQueued", 64),
				config().getInt(serverSection + "." + "timeout", 60),
				config().getBool(serverSection + "." + "keepalive", true),
				config().getInt(serverSection + "." + "keepaliveTimeout", 15),
				config().getInt(serverSection + "." + "maxKeepaliveRequests", 0),
				config().getInt(serverSection + "." + "idleTime", 60),
				config().getInt(serverSection + "." + "threadIdleTime", 10),
				config().getBool(serverSection + "." + "collectIdleThreads", false),
				root,
				readIndexes(index),
				config().getBool(serverSection + "." + "autoIndex", true),
				readShares(),
				readMimeTypes()
				);
			configuration.validate();

			HTTPServerParams::Ptr params = new HTTPServerParams;
			params->setMaxThreads(configuration.getMaxThreads());
			params->setMaxQueued(configuration.getMaxQueued());
			params->setServerName(configuration.getServerName());
			params->setSoftwareVersion(APP_NAME_SHORT "/" APP_VERSION);
			params->setTimeout(configuration.getTimeout() * 1000000);
			params->setKeepAlive(configuration.getKeepalive());
			params->setKeepAliveTimeout(configuration.getKeepaliveTimeout() * 1000000);
			params->setMaxKeepAliveRequests(configuration.getMaxKeepaliveRequests());
			params->setThreadIdleTime(configuration.getThreadIdleTime() * 1000000);

			HTTPRequestHandlerFactory::Ptr factory = new IndigoRequestHandlerFactory();

			ThreadPool pool("workers", configuration.getMinThreads(), configuration.getMaxThreads(), configuration.getIdleTime());

			SocketAddress saddr(configuration.getAddress(), configuration.getPort());
			ServerSocket sock;
			sock.bind(saddr, false);
			sock.listen(configuration.getBacklog());
			sock.setSendTimeout(configuration.getTimeout() * 1000000); // not done in POCO

			ThreadPoolCollector collector(pool);

			HTTPServer srv(factory, pool, sock, params);

			if (configuration.getCollectIdleThreads())
				collector.startCollecting();

			srv.start();

			waitForTerminationRequest();

			srv.stop();

			collector.stopCollecting();
		}

		return EXIT_OK;
	}

private:
	void displayHelp()
	{
		HelpFormatter helpFormatter(options());
		helpFormatter.setCommand(commandName());
		helpFormatter.setUsage("[options]");
		helpFormatter.setHeader("A simple web server for static content.");
		helpFormatter.format(cout);
	}

	void displayVersion()
	{
		cout << APP_NAME " " APP_VERSION << endl;
		cout << APP_COPYRIGHT_NOTICE;
	}

	set<string> readIndexes(const string &index)
	{
		set<string> indexes;

		StringTokenizer tok(index, " \t", StringTokenizer::TOK_IGNORE_EMPTY);
		int cnt = tok.count();
		for (int i = 0; i < cnt; i++)
		{
			string idx;
			URI::decode(tok[i], idx);
			poco_assert(idx.empty() == false);

			indexes.insert(idx);
		}

		return indexes;
	}

	map<string, string> readShares()
	{
		const string sharesSection = "VirtualRoot";

		map<string, string> shares;

		AbstractConfiguration::Keys keys;
		config().keys(sharesSection, keys);

		for (size_t i = 0; i < keys.size(); i++)
		{
			const string &shareName = keys[i];
			if (shareName.empty())
				continue;

			string sharePath = config().getString(sharesSection + "." + shareName, "");
			if (sharePath.empty())
				continue;

			string decodedShareName;
			URI::decode(shareName, decodedShareName);
			string decodedSharePath;
			URI::decode(sharePath, decodedSharePath);

			shares[decodedShareName] = decodedSharePath;
		}

		return shares;
	}

	void readMimeTypes(string filename, map<string, string> &mimeTypes)
	{
		string filepath = locateConfiguration(filename);

		FileInputStream fin(filepath);
		InputLineEndingConverter in(fin, LineEnding::NEWLINE_LF);

		string line;
		while (getline(in, line))
		{
			line = line.substr(0, line.find('#'));

			StringTokenizer tok(line, " \t", StringTokenizer::TOK_IGNORE_EMPTY);
			int cnt = tok.count();
			if (cnt >= 2)
			{
				const string &type = tok[0];
				poco_assert(type.empty() == false);

				for (int i = 1; i < cnt; i++)
				{
					const string &ext = tok[i];
					poco_assert(ext.empty() == false);

					mimeTypes[ext] = type;
				}
			}
		}
	}

	map<string, string> readMimeTypes()
	{
		map<string, string> mimeTypes;

		readMimeTypes("mime.types", mimeTypes);
		readMimeTypes("mime.types.extra", mimeTypes);
		readMimeTypes("mime.types.user", mimeTypes);

		return mimeTypes;
	}

	string locateConfiguration(const string &filename)
	{
		string dir = config().getString("application.dir");
		Path path(dir);
		path.makeDirectory().setFileName(filename);
		return path.toString();
	}

	bool helpRequested;
	bool versionRequested;
};

int main(int argc, char **argv)
{
	IndigoFiler indigo;
	return indigo.run(argc, argv);
}
<|endoftext|>


<commit_before>#include "cinder/app/AppCocoaTouch.h"
#include "cinder/app/Renderer.h"
#include "cinder/Surface.h"
#include "cinder/gl/Texture.h"
#include "cinder/Camera.h"

#include "pockets/gl/Vbo.h"

using namespace ci;
using namespace ci::app;
using namespace std;

struct VertexData
{
  Vec3f	position;
  Vec3f normal;
  ColorA	color;
  Vec2f texcoord;
};

class VboSampleApp : public AppCocoaTouch {
  public:
	virtual void	setup();
	virtual void	resize( ResizeEvent event );
	virtual void	update();
	virtual void	draw();
	virtual void	mouseDown( MouseEvent event );

	Matrix44f	mCubeRotation;
	gl::Texture mTex;
	CameraPersp	mCam;
};

void VboSampleApp::setup()
{
	mCubeRotation.setToIdentity();

	// Create a blue-green gradient as an OpenGL texture
	Surface8u surface( 256, 256, false );
	Surface8u::Iter iter = surface.getIter();
	while( iter.line() ) {
		while( iter.pixel() ) {
			iter.r() = 0;
			iter.g() = iter.x();
			iter.b() = iter.y();
		}
	}

	mTex = gl::Texture( surface );

  pockets::gl::AttributeSet attributes;
  attributes.addAttribute( "position", 3, GL_FLOAT, offsetof( VertexData, position ) );
  attributes.addAttribute( "normal", 3, GL_FLOAT, offsetof( VertexData, normal ) );
  attributes.addAttribute( "color", 3, GL_FLOAT, offsetof( VertexData, color ) );
  attributes.addAttribute( "texcoord", 2, GL_FLOAT, offsetof( VertexData, texcoord ) );
  attributes.setStride( sizeof( VertexData ) );

  for( auto &attr : attributes )
  {
    cout << "Offset of: " << attr.getName() << " = " << attr.getOffset() << endl;
  }

  auto indices = pockets::gl::Vbo::create( pockets::gl::Attribute( "index", 1, GL_UNSIGNED_SHORT ) );
  auto vertices = pockets::gl::Vbo::create( attributes );
  auto mesh = pockets::gl::VboMesh::create();
  mesh->addBuffer( indices );
  mesh->addBuffer( vertices );
}

void VboSampleApp::resize( ResizeEvent event )
{
	mCam.lookAt( Vec3f( 3, 2, -3 ), Vec3f::zero() );
	mCam.setPerspective( 60, event.getAspectRatio(), 1, 1000 );
}

void VboSampleApp::mouseDown( MouseEvent event )
{
	console() << "Mouse down @ " << event.getPos() << std::endl;
}

void VboSampleApp::update()
{
	mCubeRotation.rotate( Vec3f( 1, 1, 1 ), 0.03f );
}

void VboSampleApp::draw()
{
	gl::clear( Color( 0.2f, 0.2f, 0.3f ) );
	gl::enable( GL_TEXTURE_2D );
	gl::enableDepthRead();

	mTex.bind();
	gl::setMatrices( mCam );
	glPushMatrix();
		gl::multModelView( mCubeRotation );
		gl::drawCube( Vec3f::zero(), Vec3f( 2.0f, 2.0f, 2.0f ) );
	glPopMatrix();
}

CINDER_APP_COCOA_TOUCH( VboSampleApp, RendererGl )
<commit_msg>Removing non-es2 code.<commit_after>#include "cinder/app/AppCocoaTouch.h"
#include "cinder/app/Renderer.h"
#include "cinder/Surface.h"
#include "cinder/gl/Texture.h"
#include "cinder/Camera.h"

#include "pockets/gl/Vbo.h"

using namespace ci;
using namespace ci::app;
using namespace std;

struct VertexData
{
  Vec3f	position;
  Vec3f normal;
  ColorA	color;
  Vec2f texcoord;
};

class VboSampleApp : public AppCocoaTouch {
  public:
	virtual void	setup();
	virtual void	resize( ResizeEvent event );
	virtual void	update();
	virtual void	draw();
	virtual void	mouseDown( MouseEvent event );

	Matrix44f	mCubeRotation;
	gl::Texture mTex;
	CameraPersp	mCam;
};

void VboSampleApp::setup()
{
	mCubeRotation.setToIdentity();

	// Create a blue-green gradient as an OpenGL texture
	Surface8u surface( 256, 256, false );
	Surface8u::Iter iter = surface.getIter();
	while( iter.line() ) {
		while( iter.pixel() ) {
			iter.r() = 0;
			iter.g() = iter.x();
			iter.b() = iter.y();
		}
	}

	mTex = gl::Texture( surface );

  pockets::gl::AttributeSet attributes;
  attributes.addAttribute( "position", 3, GL_FLOAT, offsetof( VertexData, position ) );
  attributes.addAttribute( "normal", 3, GL_FLOAT, offsetof( VertexData, normal ) );
  attributes.addAttribute( "color", 3, GL_FLOAT, offsetof( VertexData, color ) );
  attributes.addAttribute( "texcoord", 2, GL_FLOAT, offsetof( VertexData, texcoord ) );
  attributes.setStride( sizeof( VertexData ) );

  for( auto &attr : attributes )
  {
    cout << "Offset of: " << attr.getName() << " = " << attr.getOffset() << endl;
  }

  auto indices = pockets::gl::Vbo::create( pockets::gl::Attribute( "index", 1, GL_UNSIGNED_SHORT ) );
  auto vertices = pockets::gl::Vbo::create( attributes );
  auto mesh = pockets::gl::VboMesh::create();
  mesh->addBuffer( indices );
  mesh->addBuffer( vertices );
}

void VboSampleApp::resize( ResizeEvent event )
{
	mCam.lookAt( Vec3f( 3, 2, -3 ), Vec3f::zero() );
	mCam.setPerspective( 60, event.getAspectRatio(), 1, 1000 );
}

void VboSampleApp::mouseDown( MouseEvent event )
{
	console() << "Mouse down @ " << event.getPos() << std::endl;
}

void VboSampleApp::update()
{
	mCubeRotation.rotate( Vec3f( 1, 1, 1 ), 0.03f );
}

void VboSampleApp::draw()
{
	gl::clear( Color( 0.2f, 0.2f, 0.3f ) );
	gl::enable( GL_TEXTURE_2D );
	gl::enableDepthRead();

	mTex.bind();
}

CINDER_APP_COCOA_TOUCH( VboSampleApp, RendererGl )
<|endoftext|>