int main(int argc, char **argv) { int fd, i, j, k; int c; int foreground=0; int active_slave=0; int log_options; char config_file_name[PATH_MAX] = RENDERD_CONFIG; while (1) { int option_index = 0; static struct option long_options[] = { {"config", 1, 0, 'c'}, {"foreground", 1, 0, 'f'}, {"slave", 1, 0, 's'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "hfc:", long_options, &option_index); if (c == -1) break; switch (c) { case 'f': foreground=1; break; case 'c': strncpy(config_file_name, optarg, PATH_MAX-1); config_file_name[PATH_MAX-1] = 0; break; case 's': if (sscanf(optarg, "%i", &active_slave) != 1) { fprintf(stderr, "--slave needs to be nummeric (%s)\n", optarg); active_slave = 0; } break; case 'h': fprintf(stderr, "Usage: renderd [OPTION] ...\n"); fprintf(stderr, "Mapnik rendering daemon\n"); fprintf(stderr, " -f, --foreground run in foreground\n"); fprintf(stderr, " -h, --help display this help and exit\n"); fprintf(stderr, " -c, --config=CONFIG set location of config file (default /etc/renderd.conf)\n"); fprintf(stderr, " -s, --slave=CONFIG_NR set which render slave this is (default 0)\n"); exit(0); default: fprintf(stderr, "unknown config option '%c'\n", c); exit(1); } } log_options = LOG_PID; #ifdef LOG_PERROR if (foreground) log_options |= LOG_PERROR; #endif openlog("renderd", log_options, LOG_DAEMON); syslog(LOG_INFO, "Rendering daemon started"); pthread_mutex_init(&qLock, NULL); pthread_cond_init(&qCond, NULL); reqHead.next = reqHead.prev = &reqHead; reqPrioHead.next = reqPrioHead.prev = &reqPrioHead; reqBulkHead.next = reqBulkHead.prev = &reqBulkHead; dirtyHead.next = dirtyHead.prev = &dirtyHead; renderHead.next = renderHead.prev = &renderHead; hashidxSize = HASHIDX_SIZE; item_hashidx = (struct item_idx *) malloc(sizeof(struct item_idx) * hashidxSize); bzero(item_hashidx, sizeof(struct item_idx) * hashidxSize); stats.noDirtyRender = 0; stats.noReqDroped = 0; stats.noReqRender = 0; stats.noReqPrioRender = 0; stats.noReqBulkRender = 0; xmlconfigitem maps[XMLCONFIGS_MAX]; bzero(maps, sizeof(xmlconfigitem) * XMLCONFIGS_MAX); renderd_config config_slaves[MAX_SLAVES]; bzero(config_slaves, sizeof(renderd_config) * MAX_SLAVES); bzero(&config, sizeof(renderd_config)); dictionary *ini = iniparser_load(config_file_name); if (! ini) { exit(1); } noSlaveRenders = 0; int iconf = -1; char buffer[PATH_MAX]; for (int section=0; section < iniparser_getnsec(ini); section++) { char *name = iniparser_getsecname(ini, section); syslog(LOG_INFO, "Parsing section %s\n", name); if (strncmp(name, "renderd", 7) && strcmp(name, "mapnik")) { if (config.tile_dir == NULL) { fprintf(stderr, "No valid (active) renderd config section available\n"); exit(7); } /* this is a map section */ iconf++; if (iconf >= XMLCONFIGS_MAX) { fprintf(stderr, "Config: more than %d configurations found\n", XMLCONFIGS_MAX); exit(7); } if (strlen(name) >= (XMLCONFIG_MAX - 1)) { fprintf(stderr, "XML name too long: %s\n", name); exit(7); } strcpy(maps[iconf].xmlname, name); sprintf(buffer, "%s:uri", name); char *ini_uri = iniparser_getstring(ini, buffer, (char *)""); if (strlen(ini_uri) >= (PATH_MAX - 1)) { fprintf(stderr, "URI too long: %s\n", ini_uri); exit(7); } strcpy(maps[iconf].xmluri, ini_uri); sprintf(buffer, "%s:xml", name); char *ini_xmlpath = iniparser_getstring(ini, buffer, (char *)""); if (strlen(ini_xmlpath) >= (PATH_MAX - 1)){ fprintf(stderr, "XML path too long: %s\n", ini_xmlpath); exit(7); } strcpy(maps[iconf].xmlfile, ini_xmlpath); sprintf(buffer, "%s:host", name); char *ini_hostname = iniparser_getstring(ini, buffer, (char *) ""); if (strlen(ini_hostname) >= (PATH_MAX - 1)) { fprintf(stderr, "Host name too long: %s\n", ini_hostname); exit(7); } strcpy(maps[iconf].host, ini_hostname); sprintf(buffer, "%s:htcphost", name); char *ini_htcpip = iniparser_getstring(ini, buffer, (char *) ""); if (strlen(ini_htcpip) >= (PATH_MAX - 1)) { fprintf(stderr, "HTCP host name too long: %s\n", ini_htcpip); exit(7); } strcpy(maps[iconf].htcpip, ini_htcpip); sprintf(buffer, "%s:tilesize", name); char *ini_tilesize = iniparser_getstring(ini, buffer, (char *) "256"); maps[iconf].tile_px_size = atoi(ini_tilesize); if (maps[iconf].tile_px_size < 1) { fprintf(stderr, "Tile size is invalid: %s\n", ini_tilesize); exit(7); } sprintf(buffer, "%s:tiledir", name); char *ini_tiledir = iniparser_getstring(ini, buffer, (char *) config.tile_dir); if (strlen(ini_tiledir) >= (PATH_MAX - 1)) { fprintf(stderr, "Tiledir too long: %s\n", ini_tiledir); exit(7); } strcpy(maps[iconf].tile_dir, ini_tiledir); } else if (strncmp(name, "renderd", 7) == 0) { int render_sec = 0; if (sscanf(name, "renderd%i", &render_sec) != 1) { render_sec = 0; } syslog(LOG_INFO, "Parsing render section %i\n", render_sec); if (render_sec >= MAX_SLAVES) { syslog(LOG_ERR, "Can't handle more than %i render sections\n", MAX_SLAVES); exit(7); } sprintf(buffer, "%s:socketname", name); config_slaves[render_sec].socketname = iniparser_getstring(ini, buffer, (char *) RENDER_SOCKET); sprintf(buffer, "%s:iphostname", name); config_slaves[render_sec].iphostname = iniparser_getstring(ini, buffer, ""); sprintf(buffer, "%s:ipport", name); config_slaves[render_sec].ipport = iniparser_getint(ini, buffer, 0); sprintf(buffer, "%s:num_threads", name); config_slaves[render_sec].num_threads = iniparser_getint(ini, buffer, NUM_THREADS); sprintf(buffer, "%s:tile_dir", name); config_slaves[render_sec].tile_dir = iniparser_getstring(ini, buffer, (char *) HASH_PATH); sprintf(buffer, "%s:stats_file", name); config_slaves[render_sec].stats_filename = iniparser_getstring(ini, buffer, NULL); if (render_sec == active_slave) { config.socketname = config_slaves[render_sec].socketname; config.iphostname = config_slaves[render_sec].iphostname; config.ipport = config_slaves[render_sec].ipport; config.num_threads = config_slaves[render_sec].num_threads; config.tile_dir = config_slaves[render_sec].tile_dir; config.stats_filename = config_slaves[render_sec].stats_filename; config.mapnik_plugins_dir = iniparser_getstring(ini, "mapnik:plugins_dir", (char *) MAPNIK_PLUGINS); config.mapnik_font_dir = iniparser_getstring(ini, "mapnik:font_dir", (char *) FONT_DIR); config.mapnik_font_dir_recurse = iniparser_getboolean(ini, "mapnik:font_dir_recurse", FONT_RECURSE); } else { noSlaveRenders += config_slaves[render_sec].num_threads; } } } if (config.ipport > 0) { syslog(LOG_INFO, "config renderd: ip socket=%s:%i\n", config.iphostname, config.ipport); } else { syslog(LOG_INFO, "config renderd: unix socketname=%s\n", config.socketname); } syslog(LOG_INFO, "config renderd: num_threads=%d\n", config.num_threads); if (active_slave == 0) { syslog(LOG_INFO, "config renderd: num_slaves=%d\n", noSlaveRenders); } syslog(LOG_INFO, "config renderd: tile_dir=%s\n", config.tile_dir); syslog(LOG_INFO, "config renderd: stats_file=%s\n", config.stats_filename); syslog(LOG_INFO, "config mapnik: plugins_dir=%s\n", config.mapnik_plugins_dir); syslog(LOG_INFO, "config mapnik: font_dir=%s\n", config.mapnik_font_dir); syslog(LOG_INFO, "config mapnik: font_dir_recurse=%d\n", config.mapnik_font_dir_recurse); for (i = 0; i < MAX_SLAVES; i++) { if (config_slaves[i].num_threads == 0) { continue; } if (i == active_slave) { syslog(LOG_INFO, "config renderd(%i): Active\n", i); } if (config_slaves[i].ipport > 0) { syslog(LOG_INFO, "config renderd(%i): ip socket=%s:%i\n", i, config_slaves[i].iphostname, config_slaves[i].ipport); } else { syslog(LOG_INFO, "config renderd(%i): unix socketname=%s\n", i, config_slaves[i].socketname); } syslog(LOG_INFO, "config renderd(%i): num_threads=%d\n", i, config_slaves[i].num_threads); syslog(LOG_INFO, "config renderd(%i): tile_dir=%s\n", i, config_slaves[i].tile_dir); syslog(LOG_INFO, "config renderd(%i): stats_file=%s\n", i, config_slaves[i].stats_filename); } for(iconf = 0; iconf < XMLCONFIGS_MAX; ++iconf) { if (maps[iconf].xmlname[0] != 0) { syslog(LOG_INFO, "config map %d: name(%s) file(%s) uri(%s) htcp(%s) host(%s)", iconf, maps[iconf].xmlname, maps[iconf].xmlfile, maps[iconf].xmluri, maps[iconf].htcpip, maps[iconf].host); } } fd = server_socket_init(&config); #if 0 if (fcntl(fd, F_SETFD, O_RDWR | O_NONBLOCK) < 0) { fprintf(stderr, "setting socket non-block failed\n"); close(fd); exit(5); } #endif //sigPipeAction.sa_handler = pipe_handler; sigPipeAction.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &sigPipeAction, NULL) < 0) { fprintf(stderr, "failed to register signal handler\n"); close(fd); exit(6); } render_init(config.mapnik_plugins_dir, config.mapnik_font_dir, config.mapnik_font_dir_recurse); /* unless the command line said to run in foreground mode, fork and detach from terminal */ if (foreground) { fprintf(stderr, "Running in foreground mode...\n"); } else { if (daemon(0, 0) != 0) { fprintf(stderr, "can't daemonize: %s\n", strerror(errno)); } /* write pid file */ FILE *pidfile = fopen(PIDFILE, "w"); if (pidfile) { (void) fprintf(pidfile, "%d\n", getpid()); (void) fclose(pidfile); } } if (config.stats_filename != NULL) { if (pthread_create(&stats_thread, NULL, stats_writeout_thread, NULL)) { syslog(LOG_WARNING, "Could not create stats writeout thread"); } } else { syslog(LOG_INFO, "No stats file specified in config. Stats reporting disabled"); } render_threads = (pthread_t *) malloc(sizeof(pthread_t) * config.num_threads); for(i=0; i<config.num_threads; i++) { if (pthread_create(&render_threads[i], NULL, render_thread, (void *)maps)) { fprintf(stderr, "error spawning render thread\n"); close(fd); exit(7); } } if (active_slave == 0) { //Only the master renderd opens connections to its slaves k = 0; slave_threads = (pthread_t *) malloc(sizeof(pthread_t) * noSlaveRenders); for (i = 1; i < MAX_SLAVES; i++) { for (j = 0; j < config_slaves[i].num_threads; j++) { if (pthread_create(&slave_threads[k++], NULL, slave_thread, (void *) &config_slaves[i])) { fprintf(stderr, "error spawning render thread\n"); close(fd); exit(7); } } } } process_loop(fd); unlink(config.socketname); close(fd); return 0; }
int main(int argc, char argv[]) { int ret = 0; struct sockaddr_in client_address; int client_fd = 0; printf("\n"); printf("Welcome to Chat Server....\n"); memset(&serverStats, 0, sizeof(struct ServerStats_t)); serverStats.max_threads = MAX_THREADS; // start the main and make the server listen on port 12345 if (server_socket_init() == -1) { printf("An error occured. Closing program \n"); return 1 ; } //server_wait_client(server_fd); while(1) { //int rfd; int *arg; char ipstr[INET6_ADDRSTRLEN]; int port; int new_sd; int ret =0; struct sockaddr_storage remote_info ; pthread_t threads[MAX_THREADS]; socklen_t addr_size; addr_size = sizeof(addr_size); new_sd = accept(server_fd, (struct sockaddr *) &remote_info, &addr_size); getpeername(new_sd, (struct sockaddr*)&remote_info, &addr_size); // deal with both IPv4 and IPv6: if (remote_info.ss_family == AF_INET) { struct sockaddr_in *s = (struct sockaddr_in *)&remote_info; port = ntohs(s->sin_port); inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); } else { // AF_INET6 struct sockaddr_in6 *s = (struct sockaddr_in6 *)&remote_info; port = ntohs(s->sin6_port); inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr); } printf("\n"); if(new_sd >= 0) { printf("Server accepted new connection on socket id :%d\n", new_sd); /* A connection between a client and the server has been established. * Now create a new thread and handover the client_sockfd */ pthread_mutex_lock(&curr_thread_count_mutex); if (curr_thread_count < MAX_THREADS) { /* Prepare client infos in handy structure */ client_info *ci = (client_info *)malloc(sizeof(client_info)); ci->sockfd = new_sd; ci->address = remote_info; sprintf(ci->nickname, "Client_%d\n", new_sd); /* Add client info to linked list */ llist_insert(&list_start, ci); llist_show(&list_start); /* System Monitoring Statistics Counter : Increments the number of active_connections counter. Shows the number of active clients*/ serverStats.num_of_active_connections++; /* Pass client info and invoke new thread */ ret = pthread_create(&threads[curr_thread_count], NULL, (void *)&server_read_client, (void *)&new_sd); /* only pass socket id ? */ if (ret == 0) { serverStats.num_of_clients_serviced++; pthread_detach(threads[curr_thread_count]); curr_thread_count++; /* Notify server and clients */ printf("User %s joined the chat.\n", ci->nickname); printf("Connections used: %d of %d\n", curr_thread_count, MAX_THREADS); } else { serverStats.num_of_conn_dropped++; llist_remove_by_sockfd(&list_start, new_sd); serverStats.num_of_active_connections--; free(ci); close(new_sd); } } else { serverStats.num_of_conn_dropped++; printf("Max. connections reached. Connection limit is %d. Connection dropped.\n", MAX_THREADS); close(new_sd); } pthread_mutex_unlock(&curr_thread_count_mutex); } else { /* Connection could not be established. Post error and exit. */ //perror(strerror(errno)); printf("Error creating socket\n"); exit(-1); } } return 0; }