<commit_before>#include "string.h"
#include <string>
#include <iostream>
#include <fstream>
#include <unordered_set>

int gx, gy;
int totalEdges;
int capacity;
int* usages;

using namespace std;

int get_horizontal_right_edge(int x, int y) {
    return  (y * (gx - 1) + x);
}

int get_vertical_upper_edge(int x, int y) {
    return (gx - 1) * gy + (y * gx) + x;
}

void getSegmentFromEdge(int edgeId, int& x1, int& y1, int& x2, int& y2) {
    int totalHorizEdges =  (gx - 1) * gy;
    if (edgeId < totalHorizEdges) {
        // horizontal edge
        x1 = edgeId % (gx - 1);
        y1 = (edgeId) / (gx - 1);
        x2 =  x1 + 1;
        y2 =  y1;
    } else {
        // vertical edge
        x1 = (edgeId - totalHorizEdges) % (gx);
        y1 = ((edgeId - totalHorizEdges) - x1) / gx;
        x2 =  x1;
        y2 =  y1 + 1;
    }
}

int getEdgeId(int x1, int y1, int x2, int y2) {
    int edgeId = -1;
    if(x1 < x2) {
        edgeId = get_horizontal_right_edge(x1, y1);
    } else if (x1 > x2) {
        edgeId = get_horizontal_right_edge(x2, y2);
    } else if (y1 < y2) {
        edgeId = get_vertical_upper_edge(x1, y1);
    } else if (y1 > y2) {
        edgeId = get_vertical_upper_edge(x2, y2);
    } else {
        printf("ERROR: non-adgacent edge lookup\n");
        exit(-1);
    }
    return edgeId;
}

void getEdges(int x1, int y1, int x2, int y2, unordered_set<int>& edges) {
    if (x1 != x2) {
        for (int dx = 0; dx < abs(x1 - x2); dx++) {
            edges.insert(getEdgeId((x1 + dx), y1, (x2 + (dx + 1)), y2));
        }
    } else if (y1 != y2) {
        for (int dy = 0; dy < abs(y1 - y2); dy++) {
            edges.insert(getEdgeId(x1, (y1 + dy), x2, (y2 + (dy + 1))));
        }
    } else {
        printf("<< ERROR: Invalid edge(s) in solution file: (%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
        exit(-1);
    }
}

int main(int argc, char **argv) {
    string line;
    char junk[80];

 	if(argc!=4){
 		printf("Usage : ./visualize <input_benchmark_filename> <solution_filename> <output_filename>\n");
 		return 1;
 	}

 	int status;

	string inputFilename = argv[1];
	string solutionFilename = argv[2];
 	char* outputFilename = argv[3];

 	// read benchmark
    ifstream in(inputFilename);
    if (in.is_open()) {
        int numNets;
        int numBlockages = -1;
        getline(in,line);
        sscanf(line.c_str(), "%s %d %d", junk, &gx, &gy);
        totalEdges = (2 * gx * gy) - gx - gy;
        usages = (int*) malloc(sizeof(int) * totalEdges);
        getline(in,line);
        sscanf(line.c_str(), "%s %d", junk, &capacity);
        for(int i = 0; i < totalEdges; i++) {
            usages[i] = capacity;
        }
        getline(in,line);
        sscanf(line.c_str(), "%s %s %d", junk, junk, &numNets);
        while (getline(in, line)) {
            // Time for blockages
            if (numNets == 0) {
                if (numBlockages == -1) {
                    sscanf(line.c_str(), "%d", &numBlockages);
                } else {
                    int x1, y1, x2, y2;
                    int updatedCap;
                    sscanf(line.c_str(), "%d %d %d %d %d", &x1, &y1, &x2, &y2, &updatedCap);
                    usages[getEdgeId(x1, y1, x2, y2)] = updatedCap;
                }
            }
            if (line[0] == 'n') {
                numNets--;
                if (numNets == 0) {
                    int numPins;
                    sscanf(line.c_str(), "%s %d", junk, &numPins);
                    // skip over pins to get to blockage line
                    while(numPins != 0) {
                        getline(in, line);
                        numPins--;
                    }
                }
            }
        }
        in.close();
    }

    // read solution
    ifstream soln(solutionFilename);
    if (soln.is_open()) {
        unordered_set<int> netEdges;
        while(getline(soln, line)) {
            if (line[0] == '!') {
                for (int edge : netEdges) {
                    usages[edge]--;
                }
                netEdges.clear();
            } else if (line[0] != 'n') {
                int x1, y1, x2, y2;
                sscanf(line.c_str(), "(%d,%d)-(%d,%d)", &x1, &y1, &x2, &y2);
                getEdges(x1, y1, x2, y2, netEdges);
            }
        }
        in.close();
    }

    int tof = 0;
    int ovf = 0;
    int maxOverflow = 1;   // max usage of overflowed edge
    for (int i = 0; i < totalEdges; i++) {
        ovf = usages[i];
        if (ovf < 0) {
            tof += abs(ovf);
            if (abs(ovf) > maxOverflow)
                maxOverflow = abs(ovf);
        }
    }

    // build svg
    //  use old c files for fprintf convenience
    FILE* f = fopen(outputFilename, "w");
    fprintf(f, "<!DOCTYPE html>\n");
    fprintf(f, "

Total Overflow: %d

\n", tof);
    fprintf(f, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style='width:%ipx;height:%ipx'>\n", gx * 10, gy * 10);

    for (unsigned int i = 0; i < gx; i++) {
        for (unsigned int j = 0; j < gy; j++) {
            fprintf(f, "<circle cx=\"%d\" cy=\"%d\" r=\"1\" stroke=\"black\" stroke-width=\"0\" fill=\"grey\" />\n", i*10, j*10);
        }
    }

    int usage;
    int r, g, b, width;
    for (int i = 0; i < totalEdges; i++) {
        usage = usages[i];
        if (usage == capacity) {
            continue;
        } else if (usage > 0) {
            // non-overflow case... grey. darker == more usage
            r = int(225.0 * (double(usage) / double(capacity)));
            g = r;
            b = r;
            width = 7 - int(7.0 * (double(usage) / double(capacity)));
        } else {
            // overlfow... red. darker == more usage
//            r = int(245.0 * (double(abs(usage)) / double(maxOverflow)));
            r = 255;
            g = 0;
            b = 0;
            width =  7 - int(7.0 * (double(abs(usage)) / double(maxOverflow)));
        }
        int x1, y1, x2, y2;
        getSegmentFromEdge(i, x1, y1, x2, y2);
        fprintf(f, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(%d,%d,%d);stroke-width:%d\" />\n", 10 * x1, 10*y1, 10*x2, 10*y2, r, g, b, width);
    }

    printf("total overflow: %d\n", tof);
 	return 0;
}
<commit_msg>visual tweaks<commit_after>#include "string.h"
#include <string>
#include <iostream>
#include <fstream>
#include <unordered_set>

int gx, gy;
int totalEdges;
int capacity;
int* usages;

using namespace std;

int get_horizontal_right_edge(int x, int y) {
    return  (y * (gx - 1) + x);
}

int get_vertical_upper_edge(int x, int y) {
    return (gx - 1) * gy + (y * gx) + x;
}

void getSegmentFromEdge(int edgeId, int& x1, int& y1, int& x2, int& y2) {
    int totalHorizEdges =  (gx - 1) * gy;
    if (edgeId < totalHorizEdges) {
        // horizontal edge
        x1 = edgeId % (gx - 1);
        y1 = (edgeId) / (gx - 1);
        x2 =  x1 + 1;
        y2 =  y1;
    } else {
        // vertical edge
        x1 = (edgeId - totalHorizEdges) % (gx);
        y1 = ((edgeId - totalHorizEdges) - x1) / gx;
        x2 =  x1;
        y2 =  y1 + 1;
    }
}

int getEdgeId(int x1, int y1, int x2, int y2) {
    int edgeId = -1;
    if(x1 < x2) {
        edgeId = get_horizontal_right_edge(x1, y1);
    } else if (x1 > x2) {
        edgeId = get_horizontal_right_edge(x2, y2);
    } else if (y1 < y2) {
        edgeId = get_vertical_upper_edge(x1, y1);
    } else if (y1 > y2) {
        edgeId = get_vertical_upper_edge(x2, y2);
    } else {
        printf("ERROR: non-adgacent edge lookup\n");
        exit(-1);
    }
    return edgeId;
}

void getEdges(int x1, int y1, int x2, int y2, unordered_set<int>& edges) {
    if (x1 != x2) {
        for (int dx = 0; dx < abs(x1 - x2); dx++) {
            edges.insert(getEdgeId((x1 + dx), y1, (x2 + (dx + 1)), y2));
        }
    } else if (y1 != y2) {
        for (int dy = 0; dy < abs(y1 - y2); dy++) {
            edges.insert(getEdgeId(x1, (y1 + dy), x2, (y2 + (dy + 1))));
        }
    } else {
        printf("<< ERROR: Invalid edge(s) in solution file: (%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
        exit(-1);
    }
}

int main(int argc, char **argv) {
    string line;
    char junk[80];

 	if(argc!=4){
 		printf("Usage : ./visualize <input_benchmark_filename> <solution_filename> <output_filename>\n");
 		return 1;
 	}

 	int status;

	string inputFilename = argv[1];
	string solutionFilename = argv[2];
 	char* outputFilename = argv[3];

 	// read benchmark
    ifstream in(inputFilename);
    if (in.is_open()) {
        int numNets;
        int numBlockages = -1;
        getline(in,line);
        sscanf(line.c_str(), "%s %d %d", junk, &gx, &gy);
        totalEdges = (2 * gx * gy) - gx - gy;
        usages = (int*) malloc(sizeof(int) * totalEdges);
        getline(in,line);
        sscanf(line.c_str(), "%s %d", junk, &capacity);
        for(int i = 0; i < totalEdges; i++) {
            usages[i] = capacity;
        }
        getline(in,line);
        sscanf(line.c_str(), "%s %s %d", junk, junk, &numNets);
        while (getline(in, line)) {
            // Time for blockages
            if (numNets == 0) {
                if (numBlockages == -1) {
                    sscanf(line.c_str(), "%d", &numBlockages);
                } else {
                    int x1, y1, x2, y2;
                    int updatedCap;
                    sscanf(line.c_str(), "%d %d %d %d %d", &x1, &y1, &x2, &y2, &updatedCap);
                    usages[getEdgeId(x1, y1, x2, y2)] = updatedCap;
                }
            }
            if (line[0] == 'n') {
                numNets--;
                if (numNets == 0) {
                    int numPins;
                    sscanf(line.c_str(), "%s %d", junk, &numPins);
                    // skip over pins to get to blockage line
                    while(numPins != 0) {
                        getline(in, line);
                        numPins--;
                    }
                }
            }
        }
        in.close();
    }

    // read solution
    ifstream soln(solutionFilename);
    if (soln.is_open()) {
        unordered_set<int> netEdges;
        while(getline(soln, line)) {
            if (line[0] == '!') {
                for (int edge : netEdges) {
                    usages[edge]--;
                }
                netEdges.clear();
            } else if (line[0] != 'n') {
                int x1, y1, x2, y2;
                sscanf(line.c_str(), "(%d,%d)-(%d,%d)", &x1, &y1, &x2, &y2);
                getEdges(x1, y1, x2, y2, netEdges);
            }
        }
        in.close();
    }

    int tof = 0;
    int ovf = 0;
    int maxOverflow = 1;   // max usage of overflowed edge
    for (int i = 0; i < totalEdges; i++) {
        ovf = usages[i];
        if (ovf < 0) {
            tof += abs(ovf);
            if (abs(ovf) > maxOverflow)
                maxOverflow = abs(ovf);
        }
    }

    // build svg
    //  use old c files for fprintf convenience
    FILE* f = fopen(outputFilename, "w");
    fprintf(f, "<!DOCTYPE html>\n");
    fprintf(f, "

Total Overflow: %d

\n", tof);
    fprintf(f, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style='width:%ipx;height:%ipx'>\n", gx * 10, gy * 10);

    for (unsigned int i = 0; i < gx; i++) {
        for (unsigned int j = 0; j < gy; j++) {
            fprintf(f, "<circle cx=\"%d\" cy=\"%d\" r=\"1\" stroke=\"black\" stroke-width=\"0\" fill=\"grey\" />\n", i*10, j*10);
        }
    }

    int usage;
    int r, g, b, width;
    for (int i = 0; i < totalEdges; i++) {
        usage = usages[i];
        if (usage == capacity) {
            continue;
        } else if (usage > 0) {
            // non-overflow case... grey. darker == more usage
            r = int(225.0 * (double(usage) / double(capacity))) + 30;
            g = r;
            b = r;
            width = 7 - int(7.0 * (double(usage) / double(capacity)));
        } else {
            // overlfow... red. darker == more usage
//            r = int(245.0 * (double(abs(usage)) / double(maxOverflow)));
            r = 255;
            g = 0;
            b = 0;
            width =  6;
        }
        int x1, y1, x2, y2;
        getSegmentFromEdge(i, x1, y1, x2, y2);
        fprintf(f, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" style=\"stroke:rgb(%d,%d,%d);stroke-width:%d\" />\n", 10 * x1, 10*y1, 10*x2, 10*y2, r, g, b, width);
    }

    printf("total overflow: %d\n", tof);
 	return 0;
}
<|endoftext|>


<commit_before>ccb4d4b5-4b02-11e5-bbde-28cfe9171a43<commit_msg>fix for the previous fix<commit_after>ccbe4c9e-4b02-11e5-b1ce-28cfe9171a43<|endoftext|>


<commit_before>853d0da6-4b02-11e5-893f-28cfe9171a43<commit_msg>Too poor for Dropbox<commit_after>85492199-4b02-11e5-ab86-28cfe9171a43<|endoftext|>


<commit_before>2152160f-2748-11e6-8030-e0f84713e7b8<commit_msg>Did ANOTHER thing<commit_after>21724cee-2748-11e6-9fe5-e0f84713e7b8<|endoftext|>


<commit_before>665dd282-2749-11e6-b045-e0f84713e7b8<commit_msg>update testing<commit_after>66692db3-2749-11e6-bb61-e0f84713e7b8<|endoftext|>


<commit_before>d04b2c02-2747-11e6-a465-e0f84713e7b8<commit_msg>more fixes<commit_after>d06a7b85-2747-11e6-8268-e0f84713e7b8<|endoftext|>


<commit_before>7c73f414-4b02-11e5-82c7-28cfe9171a43<commit_msg>bug fix<commit_after>7c7f05e8-4b02-11e5-bf40-28cfe9171a43<|endoftext|>


<commit_before>de6768fd-4b02-11e5-b0fa-28cfe9171a43<commit_msg>NO CHANGES<commit_after>de7296f0-4b02-11e5-b4df-28cfe9171a43<|endoftext|>


<commit_before>b167460f-2747-11e6-bdcf-e0f84713e7b8<commit_msg>OKAY this time it should work<commit_after>b17e31e8-2747-11e6-bd42-e0f84713e7b8<|endoftext|>


<commit_before>42c747fd-2748-11e6-bfd9-e0f84713e7b8<commit_msg>ashley broke it<commit_after>42d216ab-2748-11e6-871e-e0f84713e7b8<|endoftext|>


<commit_before>11cc02eb-ad5d-11e7-8627-ac87a332f658<commit_msg>update testing<commit_after>12335419-ad5d-11e7-b3be-ac87a332f658<|endoftext|>


<commit_before>
#include <cassert>
#include <cstring>
#include <thread>
#include <unistd.h>
#include <climits>
#include <iostream>
#include <edisense_comms.h>
#include <member.h>
#include <sys/stat.h>

//#include <boost/filesystem.hpp>

#include "global.h"
#include "state.h"

#include "server/server_internal.h"
#include "partition/partition_db.h"
#include "daemons/daemons.h"
#include "util/hash.h"
#include "ble/ble_client_internal.h"

#define NOT_IMPLEMENTED printf("NOT_IMPLEMENTED\n"); exit(0);

#ifndef HOST_NAME_MAX // This variable isn't present in BSD, which means it isn't on OSX either
#define HOST_NAME_MAX 255
#endif

#define TRACE_ON false
#define TRACE(x) if(TRACE_ON) printf("%s\n", x);

#define DEBUG(x) printf("%d\n", x);

static void InitializeState()
{
  g_current_node_state = new NodeStateMachine();

  char hostname[HOST_NAME_MAX + 1];
  if (gethostname(hostname, sizeof(hostname)) != 0)
  {
    perror("Unable to gethostname for current machine. Exiting.");
    exit(1);
  }
  // print current machine's hostname and id
  std::cout << "Machine hostname : " << hostname << std::endl;
  g_current_node_id = hostToNodeId(std::string(hostname)); // from hash.h
  std::cout << "Machine node id : " << g_current_node_id << std::endl;

  // database direcory must exist
  struct stat stat_database_dir;;
  if (lstat(g_db_files_dirname.c_str(), &stat_database_dir) == -1)
  {
    std::cout << "DB directory does not exist. Creating it" << std::endl;
    mkdir(g_db_files_dirname.c_str(), 0700);
  }
  else
  {
    std::cerr << "DB directory already exists. Perhaps you want to start the machine in recover mode? Fatal error." << std::endl;
    exit(1);
  }

  // cluster member list must exist <---------need boost
  struct stat stat_cluster_member_list;
  if (lstat(g_cluster_member_list_filename.c_str(), &stat_cluster_member_list) == -1)
  {
    std::cerr << "Could not stat cluster member list file. Fatal error." << std::endl;
    exit(1);
  }

  g_current_node_state->loadClusterMemberList(g_cluster_member_list_filename);

  // the intial partition map must exist <---------need boost
  struct stat stat_partition_table_file;
  if (lstat(g_cached_partition_map_filename.c_str(), &stat_partition_table_file) == -1)
  {
    std::cerr << "Could not stat partition-node map file. Fatal error." << std::endl;
    exit(1);
  }

  g_cached_partition_table = new PartitionTable(g_cached_partition_map_filename);

  // initialize partition table
  int num_partitions = g_cached_partition_table->getNumPartitions();
  int num_replicas = g_cached_partition_table->getNumReplicas();
  node_t *partition_table = g_cached_partition_table->getPartitionTable();
  std::cout << "initialize for " << num_partitions << " partitions and " << num_replicas << " replicas" << std::endl;

  // build list of partitions owned from scratch
  for (partition_t partition_id = 0; partition_id < num_partitions; partition_id++)
  {
    int base_index = partition_id * num_replicas;
    for (int i = 0; i < num_replicas; i++)
    {

      if (partition_table[i + base_index] == g_current_node_id)
      {
        PartitionMetadata pm;
        pm.db = new PartitionDB(GetPartitionDBFilename(partition_id));
        pm.state = PartitionState::STABLE;

        g_current_node_state->partitions_owned_map[partition_id] = pm;
      }
    }
  }

  g_current_node_state->state = NodeState::STABLE;

  // save the partition state
  g_current_node_state->savePartitionState(g_owned_partition_state_filename);
  g_current_node_state->saveNodeState(g_current_node_state_filename);
}

// Citation: modified argument parsing function adapted from word2vec by T. Mikolov
static int ArgPos(const char *str, int argc, const char **argv, bool has_additional)
{
  int i;
  for (i = 1; i < argc; i++)
  {
    if (strcmp(str, argv[i]) == 0)
    {
      if (has_additional && i == argc - 1)
      {
        printf("Argument missing for %s\n", str);
        exit(1);
      }
      return i;
    }
  }
  return -1;
}

int main(int argc, const char *argv[])
{
  if (argc == 1) // print usage instructions
  {
    std::cout << "Usage: \n"
      << "\t--datadir <dirname> REQUIRED [place to store db shards]\n"
      << "\t--nodestate <filename> REQUIRED [current node state]\n"
      << "\t--clustermembers <filename> REQUIRED [list of cluster members]\n"
      << "\t--ownershipmap <filename> REQUIRED [list of partitions owned by current node]\n"
      << "\t--partitionmap <filename> REQUIRED [mapping of partitions to nodes]\n"
      << "\t--log <filename> REQUIRED [log file for recovery]\n"
      << "\t--join OPTIONAL\n"
      << "\t--recover OPTIONAL\n"
      << "\t--debug OPTIONAL [start sending fake data to other cluster members]\n"
//      << "\t--name OPTIONAL [give the node a custom name that can be reached, IP address]"
      << std::endl;
      return 0;
  }

  std::string logfile;

  int i;
  bool join = false, recover = false, debug = false;
  if ((i = ArgPos("--datadir", argc, argv, true)) > 0)
    g_db_files_dirname = std::string(argv[i+1]);
  if ((i = ArgPos("--nodestate", argc, argv, true)) > 0)
    g_current_node_state_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--clustermembers", argc, argv, true)) > 0)
    g_cluster_member_list_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--ownershipmap", argc, argv, true)) > 0)
    g_owned_partition_state_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--partitionmap", argc, argv, true)) > 0)
    g_cached_partition_map_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--log", argc, argv, true)) > 0)
    logfile = std::string(argv[i+1]);
  if ((i = ArgPos("--join", argc, argv, false)) > 0)
    join = true;
  if ((i = ArgPos("--recover", argc, argv, false)) > 0)
    recover = true;
  if ((i = ArgPos("--debug", argc, argv, false)) > 0)
    debug = true;

  std::cout << "DB directory : " << g_db_files_dirname << std::endl;
  std::cout << "Node state file : " << g_current_node_state_filename << std::endl;
  std::cout << "Cluster members file : " << g_cluster_member_list_filename << std::endl;
  std::cout << "Ownership map file : " << g_owned_partition_state_filename << std::endl;
  std::cout << "Partition-node map file : " << g_cached_partition_map_filename << std::endl;
  std::cout << "Log file : " << logfile << std::endl;

  if (join && recover)
  {
    perror("cannot join and recover\n");
    exit(0);
  }

  if (g_db_files_dirname == "")
  {
    perror("must specify a directory for database files\n");
    exit(0);
  }
  if (g_current_node_state_filename == "")
  {
    perror("must specify a filename for persisting node state\n");
    exit(0);
  }
  if (g_cluster_member_list_filename == "")
  {
    perror("must specify a file for list of cluster members\n");
    exit(0);
  }
  if (g_owned_partition_state_filename == "")
  {
    perror("must specify a file for owned partition state\n");
    exit(0);
  }
  if (g_cached_partition_map_filename == "")
  {
    perror("must specify a file for partition map\n");
    exit(0);
  }
  if (logfile == "")
  {
    perror("must specify a file for log\n");
    exit(0);
  }

  if (join)
  {
    NOT_IMPLEMENTED
  }
  else if (recover)
  {
    NOT_IMPLEMENTED
  }
  else
  {
    InitializeState();
  }

  edisense_comms::Member member;
  Server server;
  member.start(&server);

  std::thread rebalance_thread(LoadBalanceDaemon, &member, 60 * 5, logfile); // 5 minutes
  std::thread gc_thread(GarbageCollectDaemon, 60 * 60 * 12); // 12 hrs

  if (debug) // simulate data
  {
    for (int j = 42; j < 60; j++)
    {
      std::thread simulate_put_thread(SimulatePutDaemon, &member,1, j);
      simulate_put_thread.detach();
    }
  }

  gc_thread.join();
  rebalance_thread.join();

  member.stop();
}<commit_msg>added recover<commit_after>
#include <cassert>
#include <cstring>
#include <thread>
#include <unistd.h>
#include <climits>
#include <iostream>
#include <edisense_comms.h>
#include <member.h>
#include <sys/stat.h>

//#include <boost/filesystem.hpp>

#include "global.h"
#include "state.h"

#include "server/server_internal.h"
#include "partition/partition_db.h"
#include "daemons/daemons.h"
#include "util/hash.h"
#include "ble/ble_client_internal.h"

#define NOT_IMPLEMENTED printf("NOT_IMPLEMENTED\n"); exit(0);

#ifndef HOST_NAME_MAX // This variable isn't present in BSD, which means it isn't on OSX either
#define HOST_NAME_MAX 255
#endif

#define TRACE_ON false
#define TRACE(x) if(TRACE_ON) printf("%s\n", x);

static void RecoverState(std::string &logfile)
{
  g_current_node_state = new NodeStateMachine();

  char hostname[HOST_NAME_MAX + 1];
  if (gethostname(hostname, sizeof(hostname)) != 0)
  {
    perror("Unable to gethostname for current machine. Exiting.");
    exit(1);
  }

  // print current machine's hostname and id
  std::cout << "Machine hostname : " << hostname << std::endl;
  g_current_node_id = hostToNodeId(std::string(hostname)); // from hash.h
  std::cout << "Machine node id : " << g_current_node_id << std::endl;

  // database direcory must exist
  struct stat stat_database_dir;;
  if (lstat(g_db_files_dirname.c_str(), &stat_database_dir) == -1)
  {
    std::cerr << "DB directory does not exist. Recover failed." << std::endl;
    exit(0);
  }

  struct stat stat_cluster_member_list;
  if (lstat(g_cluster_member_list_filename.c_str(), &stat_cluster_member_list) == -1)
  {
    std::cerr << "Could not stat cluster member list file. Fatal error." << std::endl;
    exit(1);
  }

  g_current_node_state->loadClusterMemberList(g_cluster_member_list_filename);

   // the intial partition map must exist <---------need boost
  struct stat stat_partition_table_file;
  if (lstat(g_cached_partition_map_filename.c_str(), &stat_partition_table_file) == -1)
  {
    std::cerr << "Could not stat partition-node map file. Fatal error." << std::endl;
    exit(1);
  }

  g_cached_partition_table = new PartitionTable(g_cached_partition_map_filename);

  g_current_node_state->loadPartitionState(g_owned_partition_state_filename);
  g_current_node_state->loadNodeState(g_current_node_state_filename);
}

static void InitializeState()
{
  g_current_node_state = new NodeStateMachine();

  char hostname[HOST_NAME_MAX + 1];
  if (gethostname(hostname, sizeof(hostname)) != 0)
  {
    perror("Unable to gethostname for current machine. Exiting.");
    exit(1);
  }
  // print current machine's hostname and id
  std::cout << "Machine hostname : " << hostname << std::endl;
  g_current_node_id = hostToNodeId(std::string(hostname)); // from hash.h
  std::cout << "Machine node id : " << g_current_node_id << std::endl;

  // database direcory must not exist
  struct stat stat_database_dir;;
  if (lstat(g_db_files_dirname.c_str(), &stat_database_dir) == -1)
  {
    std::cout << "DB directory does not exist. Creating it" << std::endl;
    mkdir(g_db_files_dirname.c_str(), 0700);
  }
  else
  {
    std::cerr << "DB directory already exists. Perhaps you want to start the machine in recover mode? Fatal error." << std::endl;
    exit(1);
  }

  // cluster member list must exist <---------need boost
  struct stat stat_cluster_member_list;
  if (lstat(g_cluster_member_list_filename.c_str(), &stat_cluster_member_list) == -1)
  {
    std::cerr << "Could not stat cluster member list file. Fatal error." << std::endl;
    exit(1);
  }

  g_current_node_state->loadClusterMemberList(g_cluster_member_list_filename);

  // the intial partition map must exist <---------need boost
  struct stat stat_partition_table_file;
  if (lstat(g_cached_partition_map_filename.c_str(), &stat_partition_table_file) == -1)
  {
    std::cerr << "Could not stat partition-node map file. Fatal error." << std::endl;
    exit(1);
  }

  g_cached_partition_table = new PartitionTable(g_cached_partition_map_filename);

  // initialize partition table
  int num_partitions = g_cached_partition_table->getNumPartitions();
  int num_replicas = g_cached_partition_table->getNumReplicas();
  node_t *partition_table = g_cached_partition_table->getPartitionTable();
  std::cout << "initialize for " << num_partitions << " partitions and " << num_replicas << " replicas" << std::endl;

  // build list of partitions owned from scratch
  for (partition_t partition_id = 0; partition_id < num_partitions; partition_id++)
  {
    int base_index = partition_id * num_replicas;
    for (int i = 0; i < num_replicas; i++)
    {

      if (partition_table[i + base_index] == g_current_node_id)
      {
        PartitionMetadata pm;
        pm.db = new PartitionDB(GetPartitionDBFilename(partition_id));
        pm.state = PartitionState::STABLE;

        g_current_node_state->partitions_owned_map[partition_id] = pm;
      }
    }
  }

  g_current_node_state->state = NodeState::STABLE;

  // save the partition state
  g_current_node_state->savePartitionState(g_owned_partition_state_filename);
  g_current_node_state->saveNodeState(g_current_node_state_filename);
}

// Citation: modified argument parsing function adapted from word2vec by T. Mikolov
static int ArgPos(const char *str, int argc, const char **argv, bool has_additional)
{
  int i;
  for (i = 1; i < argc; i++)
  {
    if (strcmp(str, argv[i]) == 0)
    {
      if (has_additional && i == argc - 1)
      {
        printf("Argument missing for %s\n", str);
        exit(1);
      }
      return i;
    }
  }
  return -1;
}

int main(int argc, const char *argv[])
{
  if (argc == 1) // print usage instructions
  {
    std::cout << "Usage: \n"
      << "\t--datadir <dirname> REQUIRED [place to store db shards]\n"
      << "\t--nodestate <filename> REQUIRED [current node state]\n"
      << "\t--clustermembers <filename> REQUIRED [list of cluster members]\n"
      << "\t--ownershipmap <filename> REQUIRED [list of partitions owned by current node]\n"
      << "\t--partitionmap <filename> REQUIRED [mapping of partitions to nodes]\n"
      << "\t--log <filename> REQUIRED [log file for recovery]\n"
      << "\t--join OPTIONAL\n"
      << "\t--recover OPTIONAL\n"
      << "\t--debug OPTIONAL [start sending fake data to other cluster members]\n"
//      << "\t--name OPTIONAL [give the node a custom name that can be reached, IP address]"
      << std::endl;
      return 0;
  }

  std::string logfile;

  int i;
  bool join = false, recover = false, debug = false;
  if ((i = ArgPos("--datadir", argc, argv, true)) > 0)
    g_db_files_dirname = std::string(argv[i+1]);
  if ((i = ArgPos("--nodestate", argc, argv, true)) > 0)
    g_current_node_state_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--clustermembers", argc, argv, true)) > 0)
    g_cluster_member_list_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--ownershipmap", argc, argv, true)) > 0)
    g_owned_partition_state_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--partitionmap", argc, argv, true)) > 0)
    g_cached_partition_map_filename = std::string(argv[i+1]);
  if ((i = ArgPos("--log", argc, argv, true)) > 0)
    logfile = std::string(argv[i+1]);
  if ((i = ArgPos("--join", argc, argv, false)) > 0)
    join = true;
  if ((i = ArgPos("--recover", argc, argv, false)) > 0)
    recover = true;
  if ((i = ArgPos("--debug", argc, argv, false)) > 0)
    debug = true;

  std::cout << "DB directory : " << g_db_files_dirname << std::endl;
  std::cout << "Node state file : " << g_current_node_state_filename << std::endl;
  std::cout << "Cluster members file : " << g_cluster_member_list_filename << std::endl;
  std::cout << "Ownership map file : " << g_owned_partition_state_filename << std::endl;
  std::cout << "Partition-node map file : " << g_cached_partition_map_filename << std::endl;
  std::cout << "Log file : " << logfile << std::endl;

  if (join && recover)
  {
    perror("cannot join and recover\n");
    exit(0);
  }

  if (g_db_files_dirname == "")
  {
    perror("must specify a directory for database files\n");
    exit(0);
  }
  if (g_current_node_state_filename == "")
  {
    perror("must specify a filename for persisting node state\n");
    exit(0);
  }
  if (g_cluster_member_list_filename == "")
  {
    perror("must specify a file for list of cluster members\n");
    exit(0);
  }
  if (g_owned_partition_state_filename == "")
  {
    perror("must specify a file for owned partition state\n");
    exit(0);
  }
  if (g_cached_partition_map_filename == "")
  {
    perror("must specify a file for partition map\n");
    exit(0);
  }
  if (logfile == "")
  {
    perror("must specify a file for log\n");
    exit(0);
  }

  if (join)
  {
    NOT_IMPLEMENTED
  }
  else if (recover)
  {
    RecoverState(logfile);
  }
  else
  {
    InitializeState();
  }

  edisense_comms::Member member;
  Server server;
  member.start(&server);

  std::thread rebalance_thread(LoadBalanceDaemon, &member, 60 * 5, logfile); // 5 minutes
  std::thread gc_thread(GarbageCollectDaemon, 60 * 60 * 12); // 12 hrs

  if (debug) // simulate data
  {
    for (int j = 42; j < 60; j++)
    {
      std::thread simulate_put_thread(SimulatePutDaemon, &member,1, j);
      simulate_put_thread.detach();
    }
  }

  gc_thread.join();
  rebalance_thread.join();

  member.stop();
}<|endoftext|>


<commit_before>/****************************************************************************
**
** The MIT License (MIT)
**
** Copyright (c) 2016 The University of Sheffield (www.sheffield.ac.uk)
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE
**
****************************************************************************/
#include <misc/CODeMMisc.h>
#include <misc/examples/CODeMProblems.h>
#include <core/CODeMGlobal.h>

#include <random>
#include <ctime>
#include <iostream>
#include <string>

using namespace std;
using namespace CODeM;

inline void defineSeed(int seed) {std::srand(seed);}
inline void randomSeed() {std::srand((unsigned)std::time(0));}

void dispVector(vector<double> vec, string sep=", ", string endVec="; ")
{
    for(auto i = vec.begin(); i != (vec.end() -1); ++i) {
        cout << *i << sep;
    }
    cout << vec.back() << endVec;
}

int main()
{
    defineSeed(0);

    int nObj = 2;
    int nVar = 6;
    int nPareto = 5;
    int nRand   = 10;
    int nSamp = 50;

    vector<vector<double> > paretoDeterministic;
    vector<vector<double> > randDeterministic;
    vector<vector<vector<double> > > paretoObj;
    vector<vector<vector<double> > > randObj;

    vector<vector<double> > paretoDirVars = simplexLattice(nPareto-1, 2);

    // Pareto optimal vectors
    for(int i=0; i<paretoDirVars.size(); i++) {
        vector<double> iVec(nVar, 0.5);
        iVec[0] = paretoDirVars[i][0];
        vector<double> determObjVec = deterministicOVec(7, iVec, nObj);
        paretoDeterministic.push_back(determObjVec);
        vector<vector<double> > oVecSamps = CODeM::GECCOExample(iVec, nObj, nSamp);
        paretoObj.push_back(oVecSamps);
    }

    // Random vectors
    for(int i=0; i<nRand; i++) {
        vector<double> iVec;
        for(int j=0; j<nVar; j++) {
            iVec.push_back(randUni());
        }
        vector<double> determObjVec = deterministicOVec(7, iVec, nObj);
        randDeterministic.push_back(determObjVec);
        vector<vector<double> > oVecSamps = CODeM::GECCOExample(iVec, nObj, nSamp);
        randObj.push_back(oVecSamps);
    }

    // Display the results
    cout << "\n% Optimal vectors:" << endl;
    for(int v=0; v<paretoObj.size(); v++) {
        cout << "paretoObj{" << v+1 << "} = [";
        for(int i=0; i<paretoObj[v].size(); i++) {
            dispVector(paretoObj[v][i]);
        }
        cout << "];" << endl;
    }

    cout << "\n% Random vectors:" << endl;
    for(int v=0; v<randObj.size(); v++) {
        cout << "randObj{" << v+1 << "} = [";
        for(int i=0; i<randObj[v].size(); i++) {
            dispVector(randObj[v][i]);
        }
        cout << "];" << endl;
    }

    cout << "\n% Optimal deterministic vectors:" << endl;
    cout << "determOptimal = [";
    for(int i=0; i<paretoDeterministic.size(); i++) {
        dispVector(paretoDeterministic[i]);
    }
    cout << "];" << endl;

    cout << "\n% Random deterministic vectors:" << endl;
    cout << "determRand = [";
    for(int i=0; i<randDeterministic.size(); i++) {
        dispVector(randDeterministic[i]);
    }
    cout << "];\n" << endl;

    return 0;
}
<commit_msg>changing main() to accept input arguments<commit_after>/****************************************************************************
**
** The MIT License (MIT)
**
** Copyright (c) 2016 The University of Sheffield (www.sheffield.ac.uk)
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE
**
****************************************************************************/
#include <misc/CODeMMisc.h>
#include <misc/examples/CODeMProblems.h>
#include <core/CODeMGlobal.h>

#include <random>
#include <ctime>
#include <iostream>
#include <stdio.h>
#include <string>

using namespace std;
using namespace CODeM;

inline void defineSeed(int seed) {std::srand(seed);}
inline void randomSeed() {std::srand((unsigned)std::time(0));}

void dispVector(vector<double> vec, string sep=", ", string endVec="; ")
{
    for(auto i = vec.begin(); i != (vec.end() -1); ++i) {
        cout << *i << sep;
    }
    cout << vec.back() << endVec;
}

void showUsage(progName) {

    printf("\n"
           "Usage: %s [OPTION(S)]\n\n", progName);

    printf(
"This program evaluates a set of candidate solutions for an uncertain           \n"
" multiobjective optimization problem using the CODeM toolkit. The output of the\n"
" program is a set of decision vectors and a set of objective vectors for each  \n"
" decision vector. The objective vectors for every solution represent different \n"
" samples from the random variate.                                              \n\n"

"Options:                                                                       \n"
" -h, --help                Print this summary and exit.                        \n"
" -v, --version             Print version number and exit.                      \n"
" -f, --file    = FILENAME  An input file with all the configuration options.   \n"
"                           If FILENAME is not specified, the options are       \n"
"                           configured from the command. FILENAME may include a \n"
"                           relative or absolute path.                          \n"
" -o, --output  = FILENAME  A file to write the outputs. If FILENAME is not     \n"
"                           specified, the output is printed to the console.    \n"
" -p, --problem = NUMBER    A chioce of benchmark problem from the CODeM suite. \n"
"                           Use NUMBER = 0 for the problem in the GECCO'16      \n"
"                           paper. Use NUMBER = 1,...,6 for CODeM1,...,CODeM6.  \n"
" -x, --solSet  = SET       A set of decision vectors to evaluate. SET needs to \n"
"                           be provided within double qoutes, where each vector \n"
"                           is separated with a semicolon, and the elements     \n"
"                           within a vector separated with a space. e.g., a set \n"
"                           of three vectors with two variables each:           \n"
"                           SET = \"1.1 1.2; 2.1 2.2; 3.0 4.0\"                 \n"
"                           If SET is not specified two defalut sets are        \n"
"                           generated: one with solutions that are optimal for  \n"
"                           the deterministic problem, and one with random      \n"
"                           vectors. Their sizes are specified with the -s and  \n"
"                           -n options.                                         \n"
" -m, --nObj    = NUMBER    The dimensionality of the objective space. If NUMBER\n"
"                           is not specified, the default is 2 objectives.      \n"
" -d, --nVars   = NUMBER    The dimensionality of the decision space. If NUMBER \n"
"                           is not specified, the default is nObj + 10.         \n"
" -s, --nSols   = NUMBER    The number of decision vectors to evaluate. Two     \n"
"                           sets of size NUMBER are generated: one with         \n"
"                           solutions that are optimal for the deterministic    \n"
"                           problem, and one with random vectors. If NUMBER is  \n"
"                           not specified, the default value is NUMBER = 10.    \n"
" -n, --nSamps  = NUMBER    The number of function evaluations for each decision\n"
"                           vector. if NUMER is not specified, the default value\n"
"                           is NUMBER = 5."
"\n");

}

//int main(int argc, char* argv[])
//{
//    if (argc < 3) {
//        showUsage(argv[0]);
//        return 1;
//    }
//    std::vector <std::string> sources;
//    std::string destination;
//    for (int i = 1; i < argc; ++i) {
//        std::string arg = argv[i];
//        if ((arg == "-h") || (arg == "--help")) {
//            show_usage(argv[0]);
//            return 0;
//        } else if ((arg == "-d") || (arg == "--destination")) {
//            if (i + 1 < argc) { // Make sure we aren't at the end of argv!
//                destination = argv[i++]; // Increment 'i' so we don't get the argument as the next argv[i].
//            } else { // Uh-oh, there was no argument to the destination option.
//                  std::cerr << "--destination option requires one argument." << std::endl;
//                return 1;
//            }
//        } else {
//            sources.push_back(argv[i]);
//        }
//    }
//    return move(sources, destination);
//}

int main(int argc, char** argv)
{
    for(int i = 0; i < argc; ++i) {
        cout << "Argument " << i << ": " << argv[i] << endl;
    }
    return 0;
}

//int main()
//{
//    defineSeed(0);

//    int nObj = 2;
//    int nVar = 6;
//    int nPareto = 5;
//    int nRand   = 10;
//    int nSamp = 50;

//    vector<vector<double> > paretoDeterministic;
//    vector<vector<double> > randDeterministic;
//    vector<vector<vector<double> > > paretoObj;
//    vector<vector<vector<double> > > randObj;

//    vector<vector<double> > paretoDirVars = simplexLattice(nPareto-1, 2);

//    // Pareto optimal vectors
//    for(int i=0; i<paretoDirVars.size(); i++) {
//        vector<double> iVec(nVar, 0.5);
//        iVec[0] = paretoDirVars[i][0];
//        vector<double> determObjVec = deterministicOVec(7, iVec, nObj);
//        paretoDeterministic.push_back(determObjVec);
//        vector<vector<double> > oVecSamps = CODeM::GECCOExample(iVec, nObj, nSamp);
//        paretoObj.push_back(oVecSamps);
//    }

//    // Random vectors
//    for(int i=0; i<nRand; i++) {
//        vector<double> iVec;
//        for(int j=0; j<nVar; j++) {
//            iVec.push_back(randUni());
//        }
//        vector<double> determObjVec = deterministicOVec(7, iVec, nObj);
//        randDeterministic.push_back(determObjVec);
//        vector<vector<double> > oVecSamps = CODeM::GECCOExample(iVec, nObj, nSamp);
//        randObj.push_back(oVecSamps);
//    }

//    // Display the results
//    cout << "\n% Optimal vectors:" << endl;
//    for(int v=0; v<paretoObj.size(); v++) {
//        cout << "paretoObj{" << v+1 << "} = [";
//        for(int i=0; i<paretoObj[v].size(); i++) {
//            dispVector(paretoObj[v][i]);
//        }
//        cout << "];" << endl;
//    }

//    cout << "\n% Random vectors:" << endl;
//    for(int v=0; v<randObj.size(); v++) {
//        cout << "randObj{" << v+1 << "} = [";
//        for(int i=0; i<randObj[v].size(); i++) {
//            dispVector(randObj[v][i]);
//        }
//        cout << "];" << endl;
//    }

//    cout << "\n% Optimal deterministic vectors:" << endl;
//    cout << "determOptimal = [";
//    for(int i=0; i<paretoDeterministic.size(); i++) {
//        dispVector(paretoDeterministic[i]);
//    }
//    cout << "];" << endl;

//    cout << "\n% Random deterministic vectors:" << endl;
//    cout << "determRand = [";
//    for(int i=0; i<randDeterministic.size(); i++) {
//        dispVector(randDeterministic[i]);
//    }
//    cout << "];\n" << endl;

//    return 0;
//}
<|endoftext|>


<commit_before>#if (RASPBERRY_PI)
#include <led-matrix.h>
#include <threaded-canvas-manipulator.h>
#endif
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <bass.h>
#include <assert.h>
#include <stdlib.h>
#include <pthread.h>

#define SPECWIDTH 64 // display width (should be multiple of 4)
#define SPECHEIGHT 32  // height (changing requires palette adjustments too)
#define BANDS 64

#define CHAIN 4
#define ROWS 32
#define REFRESH_RATE 30
#define THREAD_CHECK_DELAY 500

#define MAX(x,y) ((x > y) ? x : y)

#pragma pack(1)
typedef struct {
  BYTE rgbRed,rgbGreen,rgbBlue;
} RGB;
#pragma pack()
#if (RASPBERRY_PI)
using namespace rgb_matrix;
#endif
DWORD chan;

volatile bool playing = false;
volatile bool alive = true;

const RGB main_palette[] = {
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {200, 0, 0},
  {200, 0, 0},
  {200, 0, 0},
  {200, 0, 0},
  {200, 0, 0}
};

RGB palette[ROWS];

uint16_t refresh_rate;

#if (RASPBERRY_PI)
class VolumeBars : public ThreadedCanvasManipulator {
public:
  VolumeBars(Canvas *m, int delay_ms=50)
    : ThreadedCanvasManipulator(m), delay_ms_(delay_ms),
      numBars_(BANDS), t_(0) {
  }

  void Run() {
    int x,y,y1,y2;
    y1 = 0;
    height_ = canvas()->height();
    barWidth_ = 2; //width/numBars_;

    // Start the loop
    while (running()) {
      float fft[1024];
      BASS_ChannelGetData(chan,fft,BASS_DATA_FFT2048); // get the FFT data
      for (x=0;x<SPECWIDTH;x++) {
        y=sqrt(fft[x+1])*3*SPECHEIGHT-4; // scale it (sqrt to make low values more visible)
        if (y>SPECHEIGHT) y=SPECHEIGHT; // cap it
        y2 = SPECHEIGHT + 1;
        while (--y2>MAX(y,y1)) drawBarRow(x, y2, {0,0,0});
        if (x && (y1=(y+y1)/2)) // interpolate from previous to make the display smoother
          while (--y1>=0) drawBarRow(x, y1, palette[y1]);
        y1=y;
        while (--y>=0) drawBarRow(x, y, palette[y]); // draw level
      }
      usleep(refresh_rate * 1000);
    }
  }

private:
  void drawBarRow(int bar, uint8_t y, RGB color) {
    for (uint8_t x=bar*barWidth_; x<(bar+1)*barWidth_; ++x) {
      canvas()->SetPixel(x, height_-1-y, color.rgbRed, color.rgbGreen, color.rgbBlue);
    }
  }

  int delay_ms_;
  int numBars_;
  int barWidth_;
  int height_;
  int heightGreen_;
  int heightYellow_;
  int heightOrange_;
  int heightRed_;
  int t_;
};
#endif

void *threadFunc(void *arg)
{
  while(alive)
  {
    if (playing && BASS_StreamGetFilePosition(chan, BASS_FILEPOS_CURRENT) == BASS_StreamGetFilePosition(chan, BASS_FILEPOS_SIZE))
    {
      printf("finished\n");
      fflush(stdout);
      playing = false;
    }
    usleep(THREAD_CHECK_DELAY * 1000);
  }
}

void handle_play(char* str)
{
    DWORD r;
    playing = false;
    BASS_StreamFree(chan); // close old stream
    if (!(chan=BASS_StreamCreateURL(str,0,BASS_STREAM_BLOCK|BASS_STREAM_STATUS|BASS_STREAM_AUTOFREE,NULL,(void*)r))) {
      printf("BASS Error: %d\n", BASS_ErrorGetCode());
    } else {
      BASS_ChannelPlay(chan,FALSE);
      playing = true;
    }
}

void handle_volume(char* str)
{
  uint8_t vol = atoi(str);
  BASS_SetVolume(vol/100.0);
}

// http://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c
char** str_split(char* a_str, const char a_delim)
{
    char** result    = 0;
    size_t count     = 0;
    char* tmp        = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = (char**)malloc(sizeof(char*) * count);

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);

        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    return result;
}

void reset_colors()
{
  memcpy(palette, main_palette, sizeof(main_palette));
  refresh_rate = REFRESH_RATE;
}

void handle_color(char* str)
{
  char** tokens = str_split(str, ' ');
  uint8_t color[4];
  if (tokens)
  {
      int i;
      for (i = 0; *(tokens + i); i++)
      {
          color[i] = atoi(*(tokens + i));
          free(*(tokens + i));
      }
      free(tokens);
  }
  uint8_t upper, lower;
  if (color[0] < 0 || color[0] >= 32)
  {
    return;
  }
  else if (color[0] == 0)
  {
    lower = 0;
    upper = 11;
  }
  else if (color[0] == 1)
  {
    lower = 11;
    upper = 21;
  }
  else if (color[0] == 2)
  {
    lower = 21;
    upper = 27;
  }
  else if (color[0] == 3)
  {
    lower = 27;
    upper = 32;
  }
  for (uint8_t i = lower; i < upper; i++)
  {
    palette[i].rgbRed = color[1];
    palette[i].rgbGreen = color[2];
    palette[i].rgbBlue = color[3];
  }
}

void handle_refresh(char* str)
{
  refresh_rate = atoi(str);
}

int main(int argc, char *argv[])
{
#if (RASPBERRY_PI)
  if (getuid() != 0) {
    fprintf(stderr, "Must run as root to be able to access /dev/mem\n"
            "Prepend 'sudo' to the command:\n\tsudo %s ...\n", argv[0]);
    return 1;
  }

  reset_colors();

  // Need to be root for this
  GPIO io;
  if (!io.Init())
    return 1;

  RGBMatrix *matrix = new RGBMatrix(&io, ROWS, CHAIN);

  Canvas *canvas = matrix;

  ThreadedCanvasManipulator *image_gen = image_gen = new VolumeBars(canvas, REFRESH_RATE);
#endif
  // initialize BASS
  if (!BASS_Init(-1,44100,0,NULL,NULL)) {
    printf("Can't initialize device\n");
    return 0;
  }

  BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST,1); // enable playlist processing
  BASS_SetConfig(BASS_CONFIG_NET_PREBUF,0); // minimize automatic pre-buffering, so we can do it (and display it) instead

  BASS_PluginLoad("libbass_aac.so",0); // load BASS_AAC (if present) for AAC support
#if (RASPBERRY_PI)
  image_gen->Start();
#endif
  char url[1000];
  pthread_t pth;
  pthread_create(&pth, NULL, threadFunc, NULL);
  while (true)
  {
    fgets(url, sizeof(url), stdin);
    url[strcspn(url, "\n")] = 0;
    if (strncmp(url, "play ", 5) == 0)
    {
      handle_play(url+5);
    }
    else if (strncmp(url, "pause ", 6) == 0)
    {
      BASS_Pause();
    }
    else if (strncmp(url, "unpause ", 8) == 0)
    {
      BASS_Start();
    }
    else if (strncmp(url, "color ", 6) == 0)
    {
      handle_color(url+6);
    }
    else if (strncmp(url, "volume ", 7) == 0)
    {
      handle_volume(url+7);
    }
    else if (strncmp(url, "reset ", 6) == 0)
    {
      reset_colors();
    }
    else if (strncmp(url, "refresh ", 8) == 0)
    {
      handle_refresh(url+8);
    }
    else if (strncmp(url, "stop ", 5) == 0)
    {
      BASS_Stop();
      alive = false;
      return 0;
    }
  }

  BASS_Free();
#if(RASPBERRY_PI)
  // Stop image generating thread.
  delete image_gen;
  delete canvas;
#endif
  return 0;
}
<commit_msg>Correct Interpolation<commit_after>#if (RASPBERRY_PI)
#include <led-matrix.h>
#include <threaded-canvas-manipulator.h>
#endif
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <bass.h>
#include <assert.h>
#include <stdlib.h>
#include <pthread.h>

#define SPECWIDTH 64 // display width (should be multiple of 4)
#define SPECHEIGHT 32  // height (changing requires palette adjustments too)
#define BANDS 64

#define CHAIN 4
#define ROWS 32
#define REFRESH_RATE 30
#define THREAD_CHECK_DELAY 500

#define MAX(x,y) ((x > y) ? x : y)

#pragma pack(1)
typedef struct {
  BYTE rgbRed,rgbGreen,rgbBlue;
} RGB;
#pragma pack()
#if (RASPBERRY_PI)
using namespace rgb_matrix;
#endif
DWORD chan;

volatile bool playing = false;
volatile bool alive = true;

const RGB main_palette[] = {
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {0, 200, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {150, 150, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {250, 100, 0},
  {200, 0, 0},
  {200, 0, 0},
  {200, 0, 0},
  {200, 0, 0},
  {200, 0, 0}
};

RGB palette[ROWS];

uint16_t refresh_rate;

#if (RASPBERRY_PI)
class VolumeBars : public ThreadedCanvasManipulator {
public:
  VolumeBars(Canvas *m, int delay_ms=50)
    : ThreadedCanvasManipulator(m), delay_ms_(delay_ms),
      numBars_(BANDS), t_(0) {
  }

  void Run() {
    int x,y,y1,y2;
    y1 = 0;
    height_ = canvas()->height();
    barWidth_ = 2; //width/numBars_;

    // Start the loop
    while (running()) {
      float fft[1024];
      BASS_ChannelGetData(chan,fft,BASS_DATA_FFT2048); // get the FFT data
      for (x=0;x<SPECWIDTH*2;x+=2) {
        y=sqrt(fft[x+1])*3*SPECHEIGHT-4; // scale it (sqrt to make low values more visible)
        if (y>SPECHEIGHT) y=SPECHEIGHT; // cap it
        y2 = SPECHEIGHT + 1;
        y1 = (y1+y)/2;
        while (--y2>y1) drawBarRow(x, y2, {0,0,0});
        while (--y1>=0) drawBarRow(x, y1, palette[y1]);
        y1=y;
        y2 = SPECHEIGHT + 1;
        while (--y2>y) drawBarRow(x+1, y2, {0,0,0});
        while (--y>=0) drawBarRow(x+1, y, palette[y]); // draw level
      }
      usleep(refresh_rate * 1000);
    }
  }

private:
  void drawBarRow(int bar, uint8_t y, RGB color) {
    canvas()->SetPixel(bar, height_-1-y, color.rgbRed, color.rgbGreen, color.rgbBlue);
  }

  int delay_ms_;
  int numBars_;
  int barWidth_;
  int height_;
  int heightGreen_;
  int heightYellow_;
  int heightOrange_;
  int heightRed_;
  int t_;
};
#endif

void *threadFunc(void *arg)
{
  while(alive)
  {
    if (playing && BASS_StreamGetFilePosition(chan, BASS_FILEPOS_CURRENT) == BASS_StreamGetFilePosition(chan, BASS_FILEPOS_SIZE))
    {
      printf("finished\n");
      fflush(stdout);
      playing = false;
    }
    usleep(THREAD_CHECK_DELAY * 1000);
  }
}

void handle_play(char* str)
{
    DWORD r;
    playing = false;
    BASS_StreamFree(chan); // close old stream
    if (!(chan=BASS_StreamCreateURL(str,0,BASS_STREAM_BLOCK|BASS_STREAM_STATUS|BASS_STREAM_AUTOFREE,NULL,(void*)r))) {
      printf("BASS Error: %d\n", BASS_ErrorGetCode());
    } else {
      BASS_ChannelPlay(chan,FALSE);
      playing = true;
    }
}

void handle_volume(char* str)
{
  uint8_t vol = atoi(str);
  BASS_SetVolume(vol/100.0);
}

// http://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c
char** str_split(char* a_str, const char a_delim)
{
    char** result    = 0;
    size_t count     = 0;
    char* tmp        = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = (char**)malloc(sizeof(char*) * count);

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);

        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    return result;
}

void reset_colors()
{
  memcpy(palette, main_palette, sizeof(main_palette));
  refresh_rate = REFRESH_RATE;
}

void handle_color(char* str)
{
  char** tokens = str_split(str, ' ');
  uint8_t color[4];
  if (tokens)
  {
      int i;
      for (i = 0; *(tokens + i); i++)
      {
          color[i] = atoi(*(tokens + i));
          free(*(tokens + i));
      }
      free(tokens);
  }
  uint8_t upper, lower;
  if (color[0] < 0 || color[0] >= 32)
  {
    return;
  }
  else if (color[0] == 0)
  {
    lower = 0;
    upper = 11;
  }
  else if (color[0] == 1)
  {
    lower = 11;
    upper = 21;
  }
  else if (color[0] == 2)
  {
    lower = 21;
    upper = 27;
  }
  else if (color[0] == 3)
  {
    lower = 27;
    upper = 32;
  }
  for (uint8_t i = lower; i < upper; i++)
  {
    palette[i].rgbRed = color[1];
    palette[i].rgbGreen = color[2];
    palette[i].rgbBlue = color[3];
  }
}

void handle_refresh(char* str)
{
  refresh_rate = atoi(str);
}

int main(int argc, char *argv[])
{
#if (RASPBERRY_PI)
  if (getuid() != 0) {
    fprintf(stderr, "Must run as root to be able to access /dev/mem\n"
            "Prepend 'sudo' to the command:\n\tsudo %s ...\n", argv[0]);
    return 1;
  }

  reset_colors();

  // Need to be root for this
  GPIO io;
  if (!io.Init())
    return 1;

  RGBMatrix *matrix = new RGBMatrix(&io, ROWS, CHAIN);

  Canvas *canvas = matrix;

  ThreadedCanvasManipulator *image_gen = image_gen = new VolumeBars(canvas, REFRESH_RATE);
#endif
  // initialize BASS
  if (!BASS_Init(-1,44100,0,NULL,NULL)) {
    printf("Can't initialize device\n");
    return 0;
  }

  BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST,1); // enable playlist processing
  BASS_SetConfig(BASS_CONFIG_NET_PREBUF,0); // minimize automatic pre-buffering, so we can do it (and display it) instead

  BASS_PluginLoad("libbass_aac.so",0); // load BASS_AAC (if present) for AAC support
#if (RASPBERRY_PI)
  image_gen->Start();
#endif
  char url[1000];
  pthread_t pth;
  pthread_create(&pth, NULL, threadFunc, NULL);
  while (true)
  {
    fgets(url, sizeof(url), stdin);
    url[strcspn(url, "\n")] = 0;
    if (strncmp(url, "play ", 5) == 0)
    {
      handle_play(url+5);
    }
    else if (strncmp(url, "pause ", 6) == 0)
    {
      BASS_Pause();
    }
    else if (strncmp(url, "unpause ", 8) == 0)
    {
      BASS_Start();
    }
    else if (strncmp(url, "color ", 6) == 0)
    {
      handle_color(url+6);
    }
    else if (strncmp(url, "volume ", 7) == 0)
    {
      handle_volume(url+7);
    }
    else if (strncmp(url, "reset ", 6) == 0)
    {
      reset_colors();
    }
    else if (strncmp(url, "refresh ", 8) == 0)
    {
      handle_refresh(url+8);
    }
    else if (strncmp(url, "stop ", 5) == 0)
    {
      BASS_Stop();
      alive = false;
      return 0;
    }
  }

  BASS_Free();
#if(RASPBERRY_PI)
  // Stop image generating thread.
  delete image_gen;
  delete canvas;
#endif
  return 0;
}
<|endoftext|>


<commit_before>79acd138-4b02-11e5-a80f-28cfe9171a43<commit_msg>Bug fixes and performance improvements<commit_after>79bb8a7a-4b02-11e5-baf6-28cfe9171a43<|endoftext|>


<commit_before>ca815bcc-4b02-11e5-ae97-28cfe9171a43<commit_msg>Fix that bug where things didn't work but now they should<commit_after>ca8ec082-4b02-11e5-92fe-28cfe9171a43<|endoftext|>


<commit_before>// BOOST!
#include <boost/algorithm/string.hpp>

// Load up the libxml
#include <libxml/tree.h>
#include <libxml/HTMLparser.h>
#include <libxml++/libxml++.h>

// We need curl? YES!
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>

// Emmmm..... Strings and io and f streams?... my favorite...
#include <iostream>
#include <string>
#include <fstream>

// Back to the threads
#include <thread>

// This is just for sakes
#define HEADER_ACCEPT     "Accept: text/html"
#define HEADER_USER_AGENT "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.125 Safari/537.36"

// We need some colors!!!
#define CLR_0 "\x1b[0m"
#define CLR_1 "\x1b[31;1m"
#define CLR_2 "\x1b[32;1m"
#define CLR_3 "\x1b[33;1m"
#define CLR_4 "\x1b[34;1m"
#define CLR_5 "\x1b[35;1m"
#define CLR_6 "\x1b[36;1m"
#define CLR_7 "\x1b[37;1m"
#define CLR_8 "\x1b[38;1m"

// We need some fine defs for the URL segments
#define LOTTO_URI_PREFFIX "http://pcso-lotto-results-and-statistics.webnatin.com/"
#define LOTTO_URI_SUFFIX  "results.asp"

void replace(std::string& str, const std::string& from, const std::string& to) {
	// get the first pos
	size_t start_pos = str.find(from);

	// loop until we have removed all
	while (start_pos != std::string::npos) {
		// remove it
		str.replace(start_pos, from.length(), to);

		// try to find another
		start_pos = str.find(from);
	}
}

/**
 * We need an alias to boost's string trim...
 */
std::string trim(std::string string) {
	replace(string, "\u00A0"," ");   // Replaces NBSPs normal space...
	boost::algorithm::trim(string);  // Trims normal white space...
	return string;                   // Give it back man...
}

/**
 * This function actually parses the results then stores them all in a CSV
 * that you can open in a spreadsheet :)
 */
void get_results(std::string type) {
	// We need a file name...
	std::string file_name("results/" + type + ".csv");

	// We need to get a handle on the file...
	std::ofstream file(file_name);

	// Check if we have opened the file...
	if (!file.is_open()) {
		std::cout << "Error opening \"" << file_name << "\"" << std::endl;
		return;
	}

	// Added the header to the file...
	file << "\"Game\",\"Date\",\"Result\",\"Amount\",\"Winners\"" << std::endl;

	// We need a curl request instance
	curlpp::Easy request;

	// Specify the URL
	request.setOpt(curlpp::options::Url(LOTTO_URI_PREFFIX + type + LOTTO_URI_SUFFIX));

	// Specify some headers
	std::list<std::string> headers;
	headers.push_back(HEADER_ACCEPT);
	headers.push_back(HEADER_USER_AGENT);
	request.setOpt(new curlpp::options::HttpHeader(headers));
	request.setOpt(new curlpp::options::FollowLocation(true));

	// Configure curlpp to use stream
	std::ostringstream responseStream;
	curlpp::options::WriteStream streamWriter(&responseStream);
	request.setOpt(streamWriter);

	// Collect response
	request.perform();
	std::string re = responseStream.str();

	// Parse HTML and create a DOM tree
	xmlDoc* doc = htmlReadDoc((xmlChar*)re.c_str(), NULL, NULL, HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING);

	// Encapsulate raw libxml document in a libxml++ wrapper
	auto *r = xmlDocGetRootElement(doc);
	auto *root = new xmlpp::Element(r);

	// get the rows
	auto games   = root->find("//table/tr[position() > 1]/td[1]/text()");
	auto dates   = root->find("//table/tr[position() > 1]/td[3]/text()");
	auto results = root->find("//table/tr[position() > 1]/td[4]/b/text()");
	auto amounts = root->find("//table/tr[position() > 1]/td[5]/text()");
	auto winners = root->find("//table/tr[position() > 1]/td[6]/text()");

	std::cout << "games"   << ": " << games.size()    << ", ";
	std::cout << "dates"   << ": " << dates.size()    << ", ";
	std::cout << "results" << ": " << results.size()  << ", ";
	std::cout << "amounts" << ": " << amounts.size()  << ", ";
	std::cout << "winners" << ": " << winners.size();
	std::cout << std::endl;

	// loop the results
	for (int i = 0; i < games.size(); ++i) {
		// Now add the results for the result
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(games[i])->get_content())   << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(dates[i])->get_content())   << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(results[i])->get_content()) << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(amounts[i])->get_content()) << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(winners[i])->get_content()) << "\"";
		file << std::endl;
	}

	// House keeping. Can we come in? :P
	delete root;
	xmlFreeDoc(doc);
	file.close();
}

/**
 * This is MAIN, if you don't know it, go study CPP
 */
int main(int argc, char *argv[])
{
	// How many result types do we run?
	int result_types_count = 8;

	// What type of results do we need?
	std::string result_types[] = {
		"2-d",
		"3-d",
		"4-d",
		"6-42",
		"6-45",
		"6-49",
		"6-55",
		"6-d",
	};

	// Where do we store our threads? LOL!
	std::thread threads[result_types_count];

	// Start our threads!
	for (int i = 0; i < result_types_count; ++i) {
		threads[i] = std::thread(std::bind(get_results, result_types[i]));
	}

	// What did we get from the threads doc?
	for (int i = 0; i < result_types_count; ++i) {
		// We need to get back to the main thread!
		threads[i].join();
	}

	// Wow!
	return 0;
}
<commit_msg>Added mezmerizing colors that may hurt your eyes to show thread works<commit_after>// BOOST!
#include <boost/algorithm/string.hpp>

// Load up the libxml
#include <libxml/tree.h>
#include <libxml/HTMLparser.h>
#include <libxml++/libxml++.h>

// We need curl? YES!
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>

// Emmmm..... Strings and io and f streams?... my favorite...
#include <iostream>
#include <string>
#include <fstream>

// Back to the threads
#include <thread>

// This is just for sakes
#define HEADER_ACCEPT     "Accept: text/html"
#define HEADER_USER_AGENT "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.125 Safari/537.36"

// We need some colors!!!
#define CLR_0 "\x1b[0m"
#define CLR_1 "\x1b[31;1m"
#define CLR_2 "\x1b[32;1m"
#define CLR_3 "\x1b[33;1m"
#define CLR_4 "\x1b[34;1m"
#define CLR_5 "\x1b[35;1m"
#define CLR_6 "\x1b[36;1m"
#define CLR_7 "\x1b[37;1m"
#define CLR_8 "\x1b[38;1m"

// We need some fine defs for the URL segments
#define LOTTO_URI_PREFFIX "http://pcso-lotto-results-and-statistics.webnatin.com/"
#define LOTTO_URI_SUFFIX  "results.asp"

void replace(std::string& str, const std::string& from, const std::string& to) {
	// get the first pos
	size_t start_pos = str.find(from);

	// loop until we have removed all
	while (start_pos != std::string::npos) {
		// remove it
		str.replace(start_pos, from.length(), to);

		// try to find another
		start_pos = str.find(from);
	}
}

/**
 * We need an alias to boost's string trim...
 */
std::string trim(std::string string) {
	replace(string, "\u00A0"," ");   // Replaces NBSPs normal space...
	boost::algorithm::trim(string);  // Trims normal white space...
	return string;                   // Give it back man...
}

/**
 * This function actually parses the results then stores them all in a CSV
 * that you can open in a spreadsheet :)
 */
void get_results(std::string type, std::string color) {
	// We need a file name...
	std::string file_name("results/" + type + ".csv");

	// We need to get a handle on the file...
	std::ofstream file(file_name);

	// Check if we have opened the file...
	if (!file.is_open()) {
		std::cout << "Error opening \"" << file_name << "\"" << std::endl;
		return;
	}

	// Added the header to the file...
	file << "\"Game\",\"Date\",\"Result\",\"Amount\",\"Winners\"" << std::endl;

	// We need a curl request instance
	curlpp::Easy request;

	// Specify the URL
	request.setOpt(curlpp::options::Url(LOTTO_URI_PREFFIX + type + LOTTO_URI_SUFFIX));

	// Specify some headers
	std::list<std::string> headers;
	headers.push_back(HEADER_ACCEPT);
	headers.push_back(HEADER_USER_AGENT);
	request.setOpt(new curlpp::options::HttpHeader(headers));
	request.setOpt(new curlpp::options::FollowLocation(true));

	// Configure curlpp to use stream
	std::ostringstream responseStream;
	curlpp::options::WriteStream streamWriter(&responseStream);
	request.setOpt(streamWriter);

	// Collect response
	request.perform();
	std::string re = responseStream.str();

	// Parse HTML and create a DOM tree
	xmlDoc* doc = htmlReadDoc((xmlChar*)re.c_str(), NULL, NULL, HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING);

	// Encapsulate raw libxml document in a libxml++ wrapper
	auto *r = xmlDocGetRootElement(doc);
	auto *root = new xmlpp::Element(r);

	// get the rows
	auto games   = root->find("//table/tr[position() > 1]/td[1]/text()");
	auto dates   = root->find("//table/tr[position() > 1]/td[3]/text()");
	auto results = root->find("//table/tr[position() > 1]/td[4]/b/text()");
	auto amounts = root->find("//table/tr[position() > 1]/td[5]/text()");
	auto winners = root->find("//table/tr[position() > 1]/td[6]/text()");

	std::cout << color << "\n" ;
	std::cout << "games"   << ": " << games.size()    << ", ";
	std::cout << "dates"   << ": " << dates.size()    << ", ";
	std::cout << "results" << ": " << results.size()  << ", ";
	std::cout << "amounts" << ": " << amounts.size()  << ", ";
	std::cout << "winners" << ": " << winners.size();
	std::cout << std::endl;

	// loop the results
	for (int i = 0; i < games.size(); ++i) {
		// Now add the results for the result
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(games[i])->get_content())   << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(dates[i])->get_content())   << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(results[i])->get_content()) << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(amounts[i])->get_content()) << "\",";
		file << "\"" << trim((std::string) dynamic_cast<xmlpp::ContentNode*>(winners[i])->get_content()) << "\"";
		file << std::endl;
		std::cout << "●";
	}
	std::cout << CLR_0 ;

	// House keeping. Can we come in? :P
	delete root;
	xmlFreeDoc(doc);
	file.close();
}

/**
 * This is MAIN, if you don't know it, go study CPP
 */
int main(int argc, char *argv[])
{
	// How many result types do we run?
	int result_types_count = 8;

	// What type of results do we need?
	std::string result_types[] = {
		"2-d",
		"3-d",
		"4-d",
		"6-42",
		"6-45",
		"6-49",
		"6-55",
		"6-d",
	};

	// Packing up colors
	std::string colors[] = {CLR_1,CLR_2,CLR_3,CLR_4,CLR_5,CLR_6,CLR_7,CLR_8};

	// Where do we store our threads? LOL!
	std::thread threads[result_types_count];

	// Start our threads!
	for (int i = 0; i < result_types_count; ++i) {
		threads[i] = std::thread(std::bind(get_results, result_types[i], colors[i]));
	}

	// What did we get from the threads doc?
	for (int i = 0; i < result_types_count; ++i) {
		// We need to get back to the main thread!
		threads[i].join();
	}

	// Wow!
	return 0;
}
<|endoftext|>


<commit_before>3b3dbd8f-ad59-11e7-8162-ac87a332f658<commit_msg>Typical bobby<commit_after>3c4818dc-ad59-11e7-8e7f-ac87a332f658<|endoftext|>


<commit_before>#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include "uuid.h"

#include "application.h"

#define EXPECTED_PACKET_SIZE 99

// Service Constants
IPAddress upnp_address( 239, 255, 255, 250 );
int upnp_port = 1900;
int web_port = 49153;
char device_name[64] = "living room light";

// Templates
const std::string upnp_search = "M-SEARCH";
const std::string wemo_search = "ST: urn:Belkin:device:**";
const std::string wemo_reply_template  =
  "HTTP/1.1 200 OK\n"
  "CACHE-CONTROL: max-age=86400\n"
  "DATE: {{TIMESTAMP}}\n"
  "EXT:\n"
  "LOCATION: http://{{IP_ADDRESS}}:49153/setup.xml\n"
  "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\n"
  "01-NLS: {{UUID}}\n"
  "SERVER: Unspecified, UPnP/1.0, Unspecified\n"
  "X-User-Agent: redsonic\n"
  "ST: urn:Belkin:device:**\n"
  "USN: uuid:Socket-1_0-{{SERIAL_NUMBER}}::urn:Belkin:device:**\n"
  "\n\n";

// Support Constants
static char HEX_DIGITS[] = "0123456789abcdef";

IPAddress ip_address;
std::string device_uuid;
std::string device_serial;

UDP udp;
TCPServer server = TCPServer(web_port);

// Kudos: http://stackoverflow.com/a/27658515
std::string replace_all(
  const std::string& str,
  const std::string& find,
  const std::string& replace
) {
  using namespace std;
  std::string result;
  size_t find_len = find.size();
  size_t pos,from=0;
  while (std::string::npos != (pos=str.find(find,from))) {
    result.append(str, from, pos-from);
    result.append(replace);
    from = pos + find_len;
  }
  result.append(str, from, std::string::npos);
  return result;
}

bool isMulticastSearch() {
  int byte_count = udp.parsePacket();

  if ( byte_count > 0 ) {
    // Read to buffer (defensively and stuff)
    Serial.println("Reading data...");
    char buffer[EXPECTED_PACKET_SIZE + 1];
    int read_amount = (EXPECTED_PACKET_SIZE < byte_count)? byte_count : EXPECTED_PACKET_SIZE;
    udp.read(buffer, read_amount);
    buffer[read_amount] = 0;

    // Cast to String
    const std::string data(buffer);
    Serial.println(data.c_str());

    // Find the stuff we care about
    if (data.find(upnp_search) != std::string::npos &&
        data.find(wemo_search) != std::string::npos) {
      return true;
    }
  }

  return false;
}

void sendSearchReply() {
  Serial.println("Sending reply to successful search...");
  udp.beginPacket(upnp_address, upnp_port);

  char ip_string[24];
  sprintf(ip_string, "%d.%d.%d.%d", ip_address[0], ip_address[1], ip_address[2], ip_address[3]);

  std::string wemo_reply;
  wemo_reply = replace_all(wemo_reply_template, "{{TIMESTAMP}}", "Mon, 22 Jun 2015 17:24:01 GMT");
  wemo_reply = replace_all(wemo_reply, "{{IP_ADDRESS}}", ip_string);
  wemo_reply = replace_all(wemo_reply, "{{UUID}}", device_uuid);
  wemo_reply = replace_all(wemo_reply, "{{SERIAL_NUMBER}}", device_serial);

  udp.write(wemo_reply.c_str());
  udp.endPacket();
}

void toUnsignedString(char dest[], int offset, int len, long i, int shift) {
  int charPos = len;
  int radix = 1 << shift;
  long mask = radix - 1;
  do {
    dest[offset + --charPos] = HEX_DIGITS[(int) (i & mask)];
    i = i >> shift;
  } while (i != 0 && charPos > 0);
}

void hexDigits(char dest[], int offset, int digits, long val) {
  long hi = 1L << (digits * 4);
  toUnsignedString(dest, offset, digits, hi | (val & (hi - 1)), 4);
}

std::string uuidToString(std::pair<uint64_t, uint64_t>uuid_pair) {
  char uuid_string[37];

  hexDigits(uuid_string, 0, 8, uuid_pair.first >> 32);
  uuid_string[8] = 45;
  hexDigits(uuid_string, 9, 4, uuid_pair.first >> 16);
  uuid_string[13] = 45;
  hexDigits(uuid_string, 14, 4, uuid_pair.first);
  uuid_string[18] = 45;
  hexDigits(uuid_string, 19, 4, uuid_pair.second >> 48);
  uuid_string[23] = 45;
  hexDigits(uuid_string, 24, 4, uuid_pair.second >> 44);
  hexDigits(uuid_string, 28, 4, uuid_pair.second >> 28);
  hexDigits(uuid_string, 32, 4, uuid_pair.second >> 12);

  uuid_string[36] = 0;
  return std::string(uuid_string);
}

// std::string join(const std::vector<std::string>& vec, const char* delim) {
//   std::stringstream res;
//   copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(res, delim));
//   return res.str();
// }

std::string getDeviceSerial() {
  byte mac[6];
  WiFi.macAddress(mac);
  std::stringstream ss;
  ss << "c0"; // prefix
  for(int i = 0; i < 6; ++i) ss << std::hex << (int) mac[i];
  return ss.str();
}

std::string getDeviceUUID() {
  byte mac[6];
  WiFi.macAddress(mac);
  uint64_t host = ((uint64_t) mac[5] << 32) + (mac[4] << 24) + (mac[3] << 16) + (mac[2] << 8) + mac[1];
  uuid::Uuid uuid = uuid::uuid1(host, (uint16_t) mac[0]);
  return uuidToString(uuid.integer());
}

void setup() {
  Serial.begin(9600); // open serial over USB
  Serial.println("Starting up...");

  // Generate device values
  device_uuid = getDeviceUUID();
  device_serial = getDeviceSerial();

  waitUntil(WiFi.ready);
  Serial.print("Local IP: ");
  ip_address = WiFi.localIP();
  Serial.println(ip_address);
  Serial.println("Setting up UDP");

  // Start UDP
  udp.begin(upnp_port);
  udp.joinMulticast(upnp_address);

  // Start TCP
  server.begin();
}

void loop() {
  bool send_reply = isMulticastSearch();
  udp.flush();
  if (send_reply) sendSearchReply();

  TCPClient client = server.available();
  if (client.connected()) {
    while (client.available()) {
      char c = client.read();
      server.write(c);
      Serial.print("message recieved:");
      Serial.println(c);
    }
  }
}
<commit_msg>feat(Goals): Quick inline docs to state TCPServer goals<commit_after>#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include "uuid.h"

#include "application.h"

#define EXPECTED_PACKET_SIZE 99

// Service Constants
IPAddress upnp_address( 239, 255, 255, 250 );
int upnp_port = 1900;
int web_port = 49153;
char device_name[64] = "living room light";

// Templates
const std::string upnp_search = "M-SEARCH";
const std::string wemo_search = "ST: urn:Belkin:device:**";
const std::string wemo_reply_template  =
  "HTTP/1.1 200 OK\n"
  "CACHE-CONTROL: max-age=86400\n"
  "DATE: {{TIMESTAMP}}\n"
  "EXT:\n"
  "LOCATION: http://{{IP_ADDRESS}}:49153/setup.xml\n"
  "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\n"
  "01-NLS: {{UUID}}\n"
  "SERVER: Unspecified, UPnP/1.0, Unspecified\n"
  "X-User-Agent: redsonic\n"
  "ST: urn:Belkin:device:**\n"
  "USN: uuid:Socket-1_0-{{SERIAL_NUMBER}}::urn:Belkin:device:**\n"
  "\n\n";

// Support Constants
static char HEX_DIGITS[] = "0123456789abcdef";

IPAddress ip_address;
std::string device_uuid;
std::string device_serial;

UDP udp;
TCPServer server = TCPServer(web_port);

// Kudos: http://stackoverflow.com/a/27658515
std::string replace_all(
  const std::string& str,
  const std::string& find,
  const std::string& replace
) {
  using namespace std;
  std::string result;
  size_t find_len = find.size();
  size_t pos,from=0;
  while (std::string::npos != (pos=str.find(find,from))) {
    result.append(str, from, pos-from);
    result.append(replace);
    from = pos + find_len;
  }
  result.append(str, from, std::string::npos);
  return result;
}

bool isMulticastSearch() {
  int byte_count = udp.parsePacket();

  if ( byte_count > 0 ) {
    // Read to buffer (defensively and stuff)
    Serial.println("Reading data...");
    char buffer[EXPECTED_PACKET_SIZE + 1];
    int read_amount = (EXPECTED_PACKET_SIZE < byte_count)? byte_count : EXPECTED_PACKET_SIZE;
    udp.read(buffer, read_amount);
    buffer[read_amount] = 0;

    // Cast to String
    const std::string data(buffer);
    Serial.println(data.c_str());

    // Find the stuff we care about
    if (data.find(upnp_search) != std::string::npos &&
        data.find(wemo_search) != std::string::npos) {
      return true;
    }
  }

  return false;
}

void sendSearchReply() {
  Serial.println("Sending reply to successful search...");
  udp.beginPacket(upnp_address, upnp_port);

  char ip_string[24];
  sprintf(ip_string, "%d.%d.%d.%d", ip_address[0], ip_address[1], ip_address[2], ip_address[3]);

  std::string wemo_reply;
  wemo_reply = replace_all(wemo_reply_template, "{{TIMESTAMP}}", "Mon, 22 Jun 2015 17:24:01 GMT");
  wemo_reply = replace_all(wemo_reply, "{{IP_ADDRESS}}", ip_string);
  wemo_reply = replace_all(wemo_reply, "{{UUID}}", device_uuid);
  wemo_reply = replace_all(wemo_reply, "{{SERIAL_NUMBER}}", device_serial);

  udp.write(wemo_reply.c_str());
  udp.endPacket();
}

void toUnsignedString(char dest[], int offset, int len, long i, int shift) {
  int charPos = len;
  int radix = 1 << shift;
  long mask = radix - 1;
  do {
    dest[offset + --charPos] = HEX_DIGITS[(int) (i & mask)];
    i = i >> shift;
  } while (i != 0 && charPos > 0);
}

void hexDigits(char dest[], int offset, int digits, long val) {
  long hi = 1L << (digits * 4);
  toUnsignedString(dest, offset, digits, hi | (val & (hi - 1)), 4);
}

std::string uuidToString(std::pair<uint64_t, uint64_t>uuid_pair) {
  char uuid_string[37];

  hexDigits(uuid_string, 0, 8, uuid_pair.first >> 32);
  uuid_string[8] = 45;
  hexDigits(uuid_string, 9, 4, uuid_pair.first >> 16);
  uuid_string[13] = 45;
  hexDigits(uuid_string, 14, 4, uuid_pair.first);
  uuid_string[18] = 45;
  hexDigits(uuid_string, 19, 4, uuid_pair.second >> 48);
  uuid_string[23] = 45;
  hexDigits(uuid_string, 24, 4, uuid_pair.second >> 44);
  hexDigits(uuid_string, 28, 4, uuid_pair.second >> 28);
  hexDigits(uuid_string, 32, 4, uuid_pair.second >> 12);

  uuid_string[36] = 0;
  return std::string(uuid_string);
}

// std::string join(const std::vector<std::string>& vec, const char* delim) {
//   std::stringstream res;
//   copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(res, delim));
//   return res.str();
// }

std::string getDeviceSerial() {
  byte mac[6];
  WiFi.macAddress(mac);
  std::stringstream ss;
  ss << "c0"; // prefix
  for(int i = 0; i < 6; ++i) ss << std::hex << (int) mac[i];
  return ss.str();
}

std::string getDeviceUUID() {
  byte mac[6];
  WiFi.macAddress(mac);
  uint64_t host = ((uint64_t) mac[5] << 32) + (mac[4] << 24) + (mac[3] << 16) + (mac[2] << 8) + mac[1];
  uuid::Uuid uuid = uuid::uuid1(host, (uint16_t) mac[0]);
  return uuidToString(uuid.integer());
}

void setup() {
  Serial.begin(9600); // open serial over USB
  Serial.println("Starting up...");

  // Generate device values
  device_uuid = getDeviceUUID();
  device_serial = getDeviceSerial();

  waitUntil(WiFi.ready);
  Serial.print("Local IP: ");
  ip_address = WiFi.localIP();
  Serial.println(ip_address);
  Serial.println("Setting up UDP");

  // Start UDP
  udp.begin(upnp_port);
  udp.joinMulticast(upnp_address);

  // Start TCP
  server.begin();
}

void loop() {
  bool send_reply = isMulticastSearch();
  udp.flush();
  if (send_reply) sendSearchReply();

  TCPClient client = server.available();
  if (client.connected()) {
    while (client.available()) {
      // Now actually read this into a string, check for the path params for
      // the config XML file and the control calls, then return the appropriate
      // template or control what needs to be controlled.
      // a) Call the turn on / off methods
      // b) Set a cloud variable
      // c) ... Profit?
      char c = client.read();
      server.write(c);
      Serial.print("message recieved:");
      Serial.println(c);
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004-2008  See the AUTHORS file for details.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "znc.h"
#include <getopt.h>

static struct option g_LongOpts[] = {
	{ "help",			no_argument,	0,	'h' },
	{ "version",			no_argument,	0,	'v' },
	{ "no-color",			no_argument,	0,	'n' },
	{ "allow-root",			no_argument,	0,	'r' },
	{ "makeconf",			no_argument,	0,	'c' },
	{ "makepass",			no_argument,	0,	's' },
#ifdef HAVE_LIBSSL
	{ "makepem",			no_argument,	0,	'p' },
	{ "encrypt-pem",		no_argument,	0, 	'e' },
#endif /* HAVE_LIBSSL */
	{ "datadir",                    required_argument,	0,   'd' },
	{ 0, 0, 0, 0 }
};

static void GenerateHelp(const char *appname) {
	CUtils::PrintMessage("USAGE: " + CString(appname) + " [options] [config]");
	CUtils::PrintMessage("Options are:");
	CUtils::PrintMessage("\t-h, --help         List available command line options (this page)");
	CUtils::PrintMessage("\t-v, --version      Output version information and exit");
	CUtils::PrintMessage("\t-n, --no-color     Don't use escape sequences in the output");
	CUtils::PrintMessage("\t-r, --allow-root   Don't complain if ZNC is run as root");
	CUtils::PrintMessage("\t-c, --makeconf     Interactively create a new config");
	CUtils::PrintMessage("\t-s, --makepass     Generates a password for use in config");
#ifdef HAVE_LIBSSL
	CUtils::PrintMessage("\t-p, --makepem      Generates a pemfile for use with SSL");
	CUtils::PrintMessage("\t-e, --encrypt-pem  when used along with --makepem, encrypts the private key in the pemfile");
#endif /* HAVE_LIBSSL */
	CUtils::PrintMessage("\t-d, --datadir      Set a different znc repository (default is ~/.znc)");
}

static void die(int sig) {
	signal(SIGPIPE, SIG_DFL);

#ifdef _DEBUG
	CUtils::PrintMessage("Exiting on SIG [" + CString(sig) + "]");
	if ((sig == SIGABRT) || (sig == SIGSEGV)) {
		abort();
	}
#endif /* _DEBUG */

	delete &CZNC::Get();
	exit(sig);
}

static void rehash(int sig) {
	CZNC::Get().SetNeedRehash(true);
}

static bool isRoot() {
	// User root? If one of these were root, we could switch the others to root, too
	if (geteuid() == 0 || getuid() == 0)
		return true;

	return false;
}

int main(int argc, char** argv) {
	CString sConfig;
	CString sDataDir = "";

	srand(time(NULL));
	CUtils::SetStdoutIsTTY(isatty(1));

#ifdef HAVE_LIBSSL
	InitSSL();
#endif /* HAVE_LIBSSL */

	int iArg, iOptIndex = -1;
	bool bMakeConf = false;
	bool bMakePass = false;
	bool bAllowRoot = false;
#ifdef HAVE_LIBSSL
	bool bMakePem = false;
	bool bEncPem = false;

	while ((iArg = getopt_long(argc, argv, "hvnrcsped:", g_LongOpts, &iOptIndex)) != -1) {
#else
	while ((iArg = getopt_long(argc, argv, "hvnrcsd:", g_LongOpts, &iOptIndex)) != -1) {
#endif /* HAVE_LIBSSL */
	    switch (iArg) {
		case 'h':
			GenerateHelp(argv[0]);
			return 0;
		case 'v':
			cout << CZNC::GetTag() << endl;
			return 0;
		case 'n':
			CUtils::SetStdoutIsTTY(false);
			break;
		case 'r':
			bAllowRoot = true;
			break;
		case 'c':
			bMakeConf = true;
			break;
		case 's':
			bMakePass = true;
			break;
#ifdef HAVE_LIBSSL
		case 'p':
			bMakePem = true;
			break;
		case 'e':
			bEncPem = true;
			break;
#endif /* HAVE_LIBSSL */
		case 'd':
			sDataDir = CString(optarg);
			break;
		case '?':
		default:
			GenerateHelp(argv[0]);
			return 1;
	    }
	}

	if (optind < argc) {
		sConfig = argv[optind];
	} else {
		sConfig = "znc.conf";
	}

	CZNC* pZNC = &CZNC::Get();
	pZNC->InitDirs(((argc) ? argv[0] : ""), sDataDir);

#ifdef HAVE_LIBSSL
	if (bMakePem) {
		pZNC->WritePemFile(bEncPem);

		delete pZNC;
		return 0;
	}
	if (bEncPem && !bMakePem) {
		CUtils::PrintError("--encrypt-pem should be used along with --makepem.");
		return 1;
	}

#endif /* HAVE_LIBSSL */
	if (bMakePass) {
		CString sSalt;
		CString sHash = CUtils::GetSaltedHashPass(sSalt);
		CUtils::PrintMessage("Use this in the <User> section of your config:");
		CUtils::PrintMessage("Pass = md5#" + sHash + "#" + sSalt + "#");

		return 0;
	}

	if (bMakeConf) {
		if (pZNC->WriteNewConfig(sConfig)) {
			char const* args[5];

			if (argc > 2) {
				args[0] = argv[0];
				if (!sDataDir.empty()) {
					args[1] = "--datadir";
					args[2] = strdup(sDataDir.c_str());
					args[3] = argv[optind];
					args[4] = NULL;
				} else {
					args[1] = argv[optind];
					args[2] = NULL;
				}
			} else if (argc > 1) {
				args[0] = argv[0];
				if (!sDataDir.empty()) {
					args[1] = "--datadir";
					args[2] = strdup(sDataDir.c_str());
					args[3] = NULL;
				} else {
					args[1] = NULL;
				}
			} else {
				CUtils::PrintError("Unable to launch znc [Try manually restarting]");
				return 1;
			}

			if ((chdir(pZNC->GetCurPath().c_str()) == -1)
					|| (execv(*argv, (char *const*)args) == -1)) {
				CUtils::PrintError("Unable to launch znc [" + CString(strerror(errno)) + "]");
				return 1;
			}
		}

		return 0;
	}

	if (!pZNC->ParseConfig(sConfig)) {
		CUtils::PrintError("Unrecoverable config error.");
		delete pZNC;
		return 1;
	}

	if (!pZNC->OnBoot()) {
		CUtils::PrintError("Exiting due to module boot errors.");
		delete pZNC;
		return 1;
	}

	if (isRoot()) {
		CUtils::PrintError("You are running ZNC as root! Don't do that! There are not many valid");
		CUtils::PrintError("reasons for this and it can, in theory, cause great damage!");
		if (!bAllowRoot) {
			exit(1);
		}
		CUtils::PrintError("You have been warned.");
		CUtils::PrintError("Hit CTRL+C now if you don't want to run ZNC as root.");
		CUtils::PrintError("ZNC will start in 30 seconds.");
		sleep(30);
	}

#ifdef _DEBUG
	int iPid = getpid();
	CUtils::PrintMessage("Staying open for debugging [pid: " + CString(iPid) + "]");

	pZNC->WritePidFile(iPid);
	CUtils::PrintMessage(CZNC::GetTag());
#else
	CUtils::PrintAction("Forking into the background");

	int iPid = fork();

	if (iPid == -1) {
		CUtils::PrintStatus(false, strerror(errno));
		delete pZNC;
		exit(1);
	}

	if (iPid > 0) {
		// We are the parent. We are done and will go to bed.
		CUtils::PrintStatus(true, "[pid: " + CString(iPid) + "]");

		pZNC->WritePidFile(iPid);
		CUtils::PrintMessage(CZNC::GetTag());
		exit(0);
	}

	// Redirect std in/out/err to /dev/null
	close(0); open("/dev/null", O_RDONLY);
	close(1); open("/dev/null", O_WRONLY);
	close(2); open("/dev/null", O_WRONLY);

	CUtils::SetStdoutIsTTY(false);

	// We are the child. There is no way we can be a process group
	// leader, thus setsid() must succeed.
	setsid();
	// Now we are in our own process group and session (no controlling
	// terminal). We are independent!
#endif

	struct sigaction sa;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &sa, (struct sigaction*) NULL);

	sa.sa_handler = rehash;
	sigaction(SIGHUP,  &sa, (struct sigaction*) NULL);

	// Once this signal is caught, the signal handler is reset
	// to SIG_DFL. This avoids endless loop with signals.
	sa.sa_flags = SA_RESETHAND;
	sa.sa_handler = die;
	sigaction(SIGINT,  &sa, (struct sigaction*) NULL);
	sigaction(SIGILL,  &sa, (struct sigaction*) NULL);
	sigaction(SIGQUIT, &sa, (struct sigaction*) NULL);
	sigaction(SIGBUS,  &sa, (struct sigaction*) NULL);
	sigaction(SIGSEGV, &sa, (struct sigaction*) NULL);
	sigaction(SIGTERM, &sa, (struct sigaction*) NULL);

	int iRet = 0;

	try {
		iRet = pZNC->Loop();
	} catch (CException e) {
		// EX_Shutdown is thrown to exit
		switch (e.GetType()) {
			case CException::EX_Shutdown:
				iRet = 0;
			default:
				iRet = 1;
		}
	}

	delete pZNC;

	return iRet;
}
<commit_msg>Don't start a new process for starting znc after --makeconf<commit_after>/*
 * Copyright (C) 2004-2008  See the AUTHORS file for details.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "znc.h"
#include <getopt.h>

static struct option g_LongOpts[] = {
	{ "help",			no_argument,	0,	'h' },
	{ "version",			no_argument,	0,	'v' },
	{ "no-color",			no_argument,	0,	'n' },
	{ "allow-root",			no_argument,	0,	'r' },
	{ "makeconf",			no_argument,	0,	'c' },
	{ "makepass",			no_argument,	0,	's' },
#ifdef HAVE_LIBSSL
	{ "makepem",			no_argument,	0,	'p' },
	{ "encrypt-pem",		no_argument,	0, 	'e' },
#endif /* HAVE_LIBSSL */
	{ "datadir",                    required_argument,	0,   'd' },
	{ 0, 0, 0, 0 }
};

static void GenerateHelp(const char *appname) {
	CUtils::PrintMessage("USAGE: " + CString(appname) + " [options] [config]");
	CUtils::PrintMessage("Options are:");
	CUtils::PrintMessage("\t-h, --help         List available command line options (this page)");
	CUtils::PrintMessage("\t-v, --version      Output version information and exit");
	CUtils::PrintMessage("\t-n, --no-color     Don't use escape sequences in the output");
	CUtils::PrintMessage("\t-r, --allow-root   Don't complain if ZNC is run as root");
	CUtils::PrintMessage("\t-c, --makeconf     Interactively create a new config");
	CUtils::PrintMessage("\t-s, --makepass     Generates a password for use in config");
#ifdef HAVE_LIBSSL
	CUtils::PrintMessage("\t-p, --makepem      Generates a pemfile for use with SSL");
	CUtils::PrintMessage("\t-e, --encrypt-pem  when used along with --makepem, encrypts the private key in the pemfile");
#endif /* HAVE_LIBSSL */
	CUtils::PrintMessage("\t-d, --datadir      Set a different znc repository (default is ~/.znc)");
}

static void die(int sig) {
	signal(SIGPIPE, SIG_DFL);

#ifdef _DEBUG
	CUtils::PrintMessage("Exiting on SIG [" + CString(sig) + "]");
	if ((sig == SIGABRT) || (sig == SIGSEGV)) {
		abort();
	}
#endif /* _DEBUG */

	delete &CZNC::Get();
	exit(sig);
}

static void rehash(int sig) {
	CZNC::Get().SetNeedRehash(true);
}

static bool isRoot() {
	// User root? If one of these were root, we could switch the others to root, too
	if (geteuid() == 0 || getuid() == 0)
		return true;

	return false;
}

int main(int argc, char** argv) {
	CString sConfig;
	CString sDataDir = "";

	srand(time(NULL));
	CUtils::SetStdoutIsTTY(isatty(1));

#ifdef HAVE_LIBSSL
	InitSSL();
#endif /* HAVE_LIBSSL */

	int iArg, iOptIndex = -1;
	bool bMakeConf = false;
	bool bMakePass = false;
	bool bAllowRoot = false;
#ifdef HAVE_LIBSSL
	bool bMakePem = false;
	bool bEncPem = false;

	while ((iArg = getopt_long(argc, argv, "hvnrcsped:", g_LongOpts, &iOptIndex)) != -1) {
#else
	while ((iArg = getopt_long(argc, argv, "hvnrcsd:", g_LongOpts, &iOptIndex)) != -1) {
#endif /* HAVE_LIBSSL */
	    switch (iArg) {
		case 'h':
			GenerateHelp(argv[0]);
			return 0;
		case 'v':
			cout << CZNC::GetTag() << endl;
			return 0;
		case 'n':
			CUtils::SetStdoutIsTTY(false);
			break;
		case 'r':
			bAllowRoot = true;
			break;
		case 'c':
			bMakeConf = true;
			break;
		case 's':
			bMakePass = true;
			break;
#ifdef HAVE_LIBSSL
		case 'p':
			bMakePem = true;
			break;
		case 'e':
			bEncPem = true;
			break;
#endif /* HAVE_LIBSSL */
		case 'd':
			sDataDir = CString(optarg);
			break;
		case '?':
		default:
			GenerateHelp(argv[0]);
			return 1;
	    }
	}

	if (optind < argc) {
		sConfig = argv[optind];
	} else {
		sConfig = "znc.conf";
	}

	CZNC* pZNC = &CZNC::Get();
	pZNC->InitDirs(((argc) ? argv[0] : ""), sDataDir);

#ifdef HAVE_LIBSSL
	if (bMakePem) {
		pZNC->WritePemFile(bEncPem);

		delete pZNC;
		return 0;
	}
	if (bEncPem && !bMakePem) {
		CUtils::PrintError("--encrypt-pem should be used along with --makepem.");
		return 1;
	}

#endif /* HAVE_LIBSSL */
	if (bMakePass) {
		CString sSalt;
		CString sHash = CUtils::GetSaltedHashPass(sSalt);
		CUtils::PrintMessage("Use this in the <User> section of your config:");
		CUtils::PrintMessage("Pass = md5#" + sHash + "#" + sSalt + "#");

		return 0;
	}

	if (bMakeConf) {
		if (!pZNC->WriteNewConfig(sConfig)) {
			delete pZNC;
			return 0;
		}
		/* Fall through to normal bootup */
	}

	if (!pZNC->ParseConfig(sConfig)) {
		CUtils::PrintError("Unrecoverable config error.");
		delete pZNC;
		return 1;
	}

	if (!pZNC->OnBoot()) {
		CUtils::PrintError("Exiting due to module boot errors.");
		delete pZNC;
		return 1;
	}

	if (isRoot()) {
		CUtils::PrintError("You are running ZNC as root! Don't do that! There are not many valid");
		CUtils::PrintError("reasons for this and it can, in theory, cause great damage!");
		if (!bAllowRoot) {
			exit(1);
		}
		CUtils::PrintError("You have been warned.");
		CUtils::PrintError("Hit CTRL+C now if you don't want to run ZNC as root.");
		CUtils::PrintError("ZNC will start in 30 seconds.");
		sleep(30);
	}

#ifdef _DEBUG
	int iPid = getpid();
	CUtils::PrintMessage("Staying open for debugging [pid: " + CString(iPid) + "]");

	pZNC->WritePidFile(iPid);
	CUtils::PrintMessage(CZNC::GetTag());
#else
	CUtils::PrintAction("Forking into the background");

	int iPid = fork();

	if (iPid == -1) {
		CUtils::PrintStatus(false, strerror(errno));
		delete pZNC;
		exit(1);
	}

	if (iPid > 0) {
		// We are the parent. We are done and will go to bed.
		CUtils::PrintStatus(true, "[pid: " + CString(iPid) + "]");

		pZNC->WritePidFile(iPid);
		CUtils::PrintMessage(CZNC::GetTag());
		exit(0);
	}

	// Redirect std in/out/err to /dev/null
	close(0); open("/dev/null", O_RDONLY);
	close(1); open("/dev/null", O_WRONLY);
	close(2); open("/dev/null", O_WRONLY);

	CUtils::SetStdoutIsTTY(false);

	// We are the child. There is no way we can be a process group
	// leader, thus setsid() must succeed.
	setsid();
	// Now we are in our own process group and session (no controlling
	// terminal). We are independent!
#endif

	struct sigaction sa;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGPIPE, &sa, (struct sigaction*) NULL);

	sa.sa_handler = rehash;
	sigaction(SIGHUP,  &sa, (struct sigaction*) NULL);

	// Once this signal is caught, the signal handler is reset
	// to SIG_DFL. This avoids endless loop with signals.
	sa.sa_flags = SA_RESETHAND;
	sa.sa_handler = die;
	sigaction(SIGINT,  &sa, (struct sigaction*) NULL);
	sigaction(SIGILL,  &sa, (struct sigaction*) NULL);
	sigaction(SIGQUIT, &sa, (struct sigaction*) NULL);
	sigaction(SIGBUS,  &sa, (struct sigaction*) NULL);
	sigaction(SIGSEGV, &sa, (struct sigaction*) NULL);
	sigaction(SIGTERM, &sa, (struct sigaction*) NULL);

	int iRet = 0;

	try {
		iRet = pZNC->Loop();
	} catch (CException e) {
		// EX_Shutdown is thrown to exit
		switch (e.GetType()) {
			case CException::EX_Shutdown:
				iRet = 0;
			default:
				iRet = 1;
		}
	}

	delete pZNC;

	return iRet;
}
<|endoftext|>