<commit_before>/* Copyright 2009 SPARTA, Inc., dba Cobham Analytic Solutions
 *
 * This file is part of WATCHER.
 *
 *     WATCHER is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     WATCHER is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Watcher.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file routeFeeder.cpp
 * @author Geoff Lawler <geoff.lawler@cobham.com>
 * @date 2009-07-15
 */
#include <stdio.h>
#include <sysexits.h> 	// portablish exit values.
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <string.h>
#include <assert.h>

#include <string>
#include <vector>

#include <libwatcher/client.h>                         // we are a client of the watcher.
#include <libwatcher/edgeMessage.h>         // we may send edgeMessages to the watcher.
#include <libwatcher/connectivityMessage.h> // we may send connectivityMessages to the watcher.
#include <logger.h>

using namespace std;
using namespace watcher;
using namespace watcher::event;

static const char *rcsid __attribute__ ((unused)) = "$Id: routingfeeder.c,v 1.0 2009/04/28 22:08:47 glawler Exp $";

// #define DEBUG 1

/* This is a feeder which polls the routing table,
 * and draws the routing algorithm's edges on the watcher
 *
 *  Copyright (C) 2006,2007,2008,2009 Sparta Inc.  Written by the NIP group, SRD, ISSO
 */

struct Route
{
    unsigned int dst;
    unsigned int nexthop;
    unsigned int mask;
    char iface[16];

    Route(int d, int n, int m, char i[16]) : dst(d), nexthop(n), mask(m) { memcpy(iface, i, sizeof(iface)); }
    Route(const Route &cpy) { dst=cpy.dst; nexthop=cpy.nexthop; mask=cpy.mask; memcpy(iface, cpy.iface, sizeof(iface)); }
    ~Route() { }
    ostream &operator<<(ostream &out) { return out << "dst: " << dst << " nexthop: " << nexthop << " mask: " << mask << " iface: " << (const char *)iface; }

};

bool operator==(const Route &a, const Route &b) {
    return a.dst==b.dst && a.nexthop==b.nexthop && a.mask==b.mask && !strncmp(a.iface, b.iface, sizeof(a.iface));
}

bool operator<(const Route &a, const Route &b) {
    return a.dst < b.dst;
}

typedef vector<Route> RouteList;

/*
   Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask       MTU      Window  IRTT
   eth0    7402A8C0        7C02A8C0        0007    0       0       0       FFFFFFFF   00       0
   eth0    7402A8C0        7202A8C0        0007    0       0       0       FFFFFFFF   00       0
   */

static void routeRead(unsigned int network, unsigned int netmask, RouteList &oneHopRoutes, RouteList &nextHopRoutes)
{
    TRACE_ENTER();

    FILE *fil;
    char line[1024];

    fil=fopen("/proc/net/route","r");
    while(fgets(line,sizeof(line)-1,fil))
    {
        char iface[16];
        int flags,refcnt,use,metric,mtu,window;
        unsigned int dst,nexthop,mask;
        int rc;

        rc=sscanf(line,"%s\t%x\t%x\t%d\t%d\t%d\t%d\t%x\t%o\t%d\n",iface,&dst,&nexthop,&flags,&refcnt,&use,&metric,&mask,&mtu,&window);

        if (rc==10 && ((ntohl(dst) & ntohl(netmask)) == ntohl(network))) {
            if (nexthop==0)
                nextHopRoutes.push_back(Route(dst, nexthop, mask, iface));
            else
                oneHopRoutes.push_back(Route(dst, nexthop, mask, iface));
        }
    }

    fclose(fil);

    TRACE_EXIT();
    return;
}

#if DEBUG
static void routeDump(const RouteList &r)
{
    TRACE_ENTER();

    if (r.size()) {
        for (RouteList::const_iterator i=r.begin(); i!=r.end(); i++) {
            ostringstream out;
            out << *i;
        }
        LOG_DEBUG("%s", out.str().c_str());
    }

    TRACE_EXIT();
}
#endif // DEBUG

typedef struct detector
{
    Client *watcherClientPtr;

    useconds_t reportperiod;		/* frequency to generate reports at */
    int reportnum;
    string iface;
    int routeedgewidth;
    Color onehopcolor;
    Color nexthopcolor;

    string nexthoplayer;
    string onehoplayer;

    int duration;			  /* Time to run (in seconds) or 0 to run until broken */

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

    RouteList prevNextHopRoutes;   /* The previous next hop list we saw. */
    RouteList prevOneHopRoutes;    /* the previous one hop list we saw. */

    bool constantUpdates;

} detector;

typedef struct DetectorInit
{
    useconds_t reportperiod;		/* frequency to generate reports at */
    string iface;
    int onehopfamily;
    Color onehopcolor;
    Color nexthopcolor;
    int mouthnum;
    int duration;			  /* Time to run (in seconds) or 0 to run until broken */
    int routeedgewidth;

    string serverName;

    string nexthoplayer;
    string onehoplayer;

    bool constantUpdates;

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

} DetectorInit;

static void updateRoutes(detector *st, RouteList &oneHopRoutes, RouteList &nextHopRoutes)
{
    TRACE_ENTER();

    static vector<MessagePtr> messages;
    if(!messages.empty())
        messages.clear();

    bool sendMessage=false;

    /*
     * If constant updates is true, always send route list. Else only send when the new list differs from the old.
     */
    if (st->constantUpdates || oneHopRoutes!=st->prevOneHopRoutes) {
        ConnectivityMessagePtr message(new ConnectivityMessage);
        message->layer=ONE_HOP_ROUTING_LAYER;
        for (RouteList::const_iterator i=oneHopRoutes.begin(); i!=oneHopRoutes.end(); i++)
            if (st->iface != string(i->iface))
                message->neighbors.push_back(boost::asio::ip::address_v4(i->dst));
        st->prevOneHopRoutes=oneHopRoutes;
        messages.push_back(message);
        sendMessage=true;
    }
    if (st->constantUpdates || nextHopRoutes!=st->prevNextHopRoutes) {
        ConnectivityMessagePtr message(new ConnectivityMessage);
        message->layer=ROUTING_LAYER;
        for (RouteList::const_iterator i=nextHopRoutes.begin(); i!=nextHopRoutes.end(); i++)
            if (st->iface != string(i->iface))
                message->neighbors.push_back(boost::asio::ip::address_v4(i->nexthop));
        st->prevNextHopRoutes=nextHopRoutes;
        messages.push_back(message);
        sendMessage=true;
    }

    if (sendMessage)
        st->watcherClientPtr->sendMessages(messages);

    TRACE_EXIT();
}

/* This is called regularly by the select loop (below)
 * It will create a message, and send it to this node's coordinator
 */
static void detectorSend(detector *st)
{
    TRACE_ENTER();

    RouteList oneHopRoutes, nextHopRoutes;

    routeRead(st->filterNetwork.s_addr, st->filterMask.s_addr, oneHopRoutes, nextHopRoutes);

    long long int curtime;
    struct timeval tp;
    gettimeofday(&tp, NULL);
    curtime=(long long int)tp.tv_sec*1000 + (long long int)tp.tv_usec/1000;

    LOG_DEBUG("node= " << st->localhost.s_addr << " time= " << curtime << " routes= " << nextHopRoutes.size() << " onehoproutes= " << oneHopRoutes.size() << " totalroutes= " << nextHopRoutes.size()+oneHopRoutes.size());

    st->reportnum++;

    updateRoutes(st,oneHopRoutes, nextHopRoutes);

    TRACE_EXIT();
}

static detector *detectorInit(DetectorInit *detinit)
{
    TRACE_ENTER();
    detector *st;

    st=new detector;
    st->iface="";

    st->watcherClientPtr=new Client(detinit->serverName);
    if(st->watcherClientPtr==NULL)
        return NULL;

    st->duration=detinit->duration;
    st->constantUpdates=detinit->constantUpdates;
    st->reportperiod=detinit->reportperiod;
    st->reportnum=0;
    st->iface=detinit->iface;

    st->onehoplayer=detinit->onehoplayer;
    st->onehopcolor=detinit->onehopcolor;

    st->nexthoplayer=detinit->nexthoplayer;
    st->nexthopcolor=st->nexthopcolor;

    st->routeedgewidth=detinit->routeedgewidth;

	st->filterNetwork.s_addr=detinit->filterNetwork.s_addr;
	st->filterMask.s_addr=detinit->filterMask.s_addr;
	st->localhost.s_addr=detinit->localhost.s_addr;

    TRACE_EXIT();
    return st;
}

/*
 * Wait around until we are ready to generate a message, then do it.
 */
static void selectLoop(detector *dt)
{
    TRACE_ENTER();

    time_t startTime=time(NULL);

    while(1)
    {
        usleep(dt->reportperiod*(useconds_t)1000.0);
        detectorSend(dt);

        if (dt->duration)
            if (time(NULL)-startTime>dt->duration)
                break;
    }

    dt->watcherClientPtr->wait();

    TRACE_EXIT();
}

int main(int argc, char *argv[])
{
    TRACE_ENTER();
    detector *dt;
    int ch;
    string logPropsFile("routeFeeder.log.properties");

    DetectorInit detinit;
    detinit.iface="";
    detinit.onehopcolor=Color::green;
    detinit.onehoplayer="One Hop Routing";
    detinit.nexthopcolor=Color::blue;
    detinit.nexthoplayer="Network Routing";
    detinit.reportperiod=2000;
    detinit.duration=0;
    detinit.routeedgewidth=15;

	detinit.filterNetwork.s_addr=0;
	detinit.filterMask.s_addr=0;
	detinit.localhost.s_addr=0;

    while ((ch = getopt(argc, argv, "m:n:h:o:x:t:e:b:i:d:p:w:l:c?")) != -1)
        switch (ch)
        {
            case 'm': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterMask))
                      {
                          fprintf(stderr, "Error parsing filter mask: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'n': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterNetwork))
                      {
                          fprintf(stderr, "Error parsing filter network: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'h': if(-1 == inet_pton(AF_INET, optarg, &detinit.localhost))
                      {
                          fprintf(stderr, "Error parsing localhost address: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'o':
                      detinit.onehopcolor.fromString(optarg);
                      break;
            case 'x':
                      detinit.nexthopcolor.fromString(optarg);
                      break;
            case 't':
                      sscanf(optarg,"%d",&detinit.duration);
                      break;
            case 'e':
                      detinit.onehoplayer=string(optarg);
                      break;
            case 'b':
                      detinit.nexthoplayer=string(optarg);
                      break;
            case 'i':
                      detinit.iface=string(optarg);
                      break;
            case 'd':
                      detinit.serverName=string(optarg);
                      break;
            case 'p':
                      sscanf(optarg,"%d",&detinit.reportperiod);
                      break;
            case 'w':
                      sscanf(optarg, "%d", &detinit.routeedgewidth);
                      break;
            case 'l':
                      logPropsFile=string(optarg);
                      break;
            case 'u':
                      detinit.constantUpdates=true;
                      break;
            case '?':
            default:
                      fprintf(stderr,"%s - poll the linux routing table, and draw the routes in the watcher\n"
                              "-d ipaddr/hostname - specify watcherd address to connect to (duck)\n"
                              "-h ipaddr - this host's address\n"
                              "-m netmask - the mask used to filter the routes (ex. 255.255.255.0)\n"
                              "-n network - the network used to filter the routes (ex. 192.168.1.0)\n"
                              "-p milliseconds - specify the period to poll and report\n"
                              "-i interface - display only routes through this ethernet interface (or any if unspecified)\n"
                              "-e layer - onehop layer name\n"
                              "-b layer - nexthop layer name\n"
                              "-t seconds - Run for this long, then exit\n"
                              "-u - send updates every period. If not set, only send updates when the routes change.\n",
                              // "-c - use connectivity messages instead of edge messages (this disables width and color settings)\n"
                              basename(argv[0])
                             );
                      exit(1);
                      break;
        }

    // init the logging system
    LOAD_LOG_PROPS(logPropsFile);
    LOG_INFO("Logger initialized from file \"" << logPropsFile << "\"");

	// check args, errors, etc before doing real work
	if(detinit.localhost.s_addr == 0)
    {
        fprintf(stderr, "localhost address cannot be blank\n");
        exit(EX_USAGE);
    }
	if(detinit.filterNetwork.s_addr == 0)
	{
        fprintf(stderr, "filter network cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.filterMask.s_addr == 0)
	{
        fprintf(stderr, "filter mask cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.serverName.empty())
	{
        fprintf(stderr, "watcherd hostname cannot be blank\n");
        exit(EX_USAGE);
	}

    dt=detectorInit(&detinit);

    if (dt==NULL)
    {
        fprintf(stderr,"detector init failed, probably could not connect to infrastructure demon.\n");
        exit(1);
    }
    printf("%s: starting\n",argv[0]);
    selectLoop(dt);

    TRACE_EXIT();
    return 0;
}
<commit_msg>routeFeeder: ignore default routes (gateways)<commit_after>/* Copyright 2009 SPARTA, Inc., dba Cobham Analytic Solutions
 *
 * This file is part of WATCHER.
 *
 *     WATCHER is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     WATCHER is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with Watcher.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file routeFeeder.cpp
 * @author Geoff Lawler <geoff.lawler@cobham.com>
 * @date 2009-07-15
 */
#include <stdio.h>
#include <sysexits.h> 	// portablish exit values.
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <string.h>
#include <assert.h>

#include <string>
#include <vector>

#include <libwatcher/client.h>                         // we are a client of the watcher.
#include <libwatcher/edgeMessage.h>         // we may send edgeMessages to the watcher.
#include <libwatcher/connectivityMessage.h> // we may send connectivityMessages to the watcher.
#include <logger.h>

using namespace std;
using namespace watcher;
using namespace watcher::event;

static const char *rcsid __attribute__ ((unused)) = "$Id: routingfeeder.c,v 1.0 2009/04/28 22:08:47 glawler Exp $";

// #define DEBUG 1

/* This is a feeder which polls the routing table,
 * and draws the routing algorithm's edges on the watcher
 *
 *  Copyright (C) 2006,2007,2008,2009 Sparta Inc.  Written by the NIP group, SRD, ISSO
 */

struct Route
{
    unsigned int dst;
    unsigned int nexthop;
    unsigned int mask;
    char iface[16];

    Route(int d, int n, int m, char i[16]) : dst(d), nexthop(n), mask(m) { memcpy(iface, i, sizeof(iface)); }
    Route(const Route &cpy) { dst=cpy.dst; nexthop=cpy.nexthop; mask=cpy.mask; memcpy(iface, cpy.iface, sizeof(iface)); }
    ~Route() { }
    ostream &operator<<(ostream &out) { return out << "dst: " << dst << " nexthop: " << nexthop << " mask: " << mask << " iface: " << (const char *)iface; }

};

bool operator==(const Route &a, const Route &b) {
    return a.dst==b.dst && a.nexthop==b.nexthop && a.mask==b.mask && !strncmp(a.iface, b.iface, sizeof(a.iface));
}

bool operator<(const Route &a, const Route &b) {
    return a.dst < b.dst;
}

typedef vector<Route> RouteList;

/*
   Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask       MTU      Window  IRTT
   eth0    7402A8C0        7C02A8C0        0007    0       0       0       FFFFFFFF   00       0
   eth0    7402A8C0        7202A8C0        0007    0       0       0       FFFFFFFF   00       0
   */

static void routeRead(unsigned int network, unsigned int netmask, RouteList &oneHopRoutes, RouteList &nextHopRoutes)
{
    TRACE_ENTER();

    FILE *fil;
    char line[1024];

    fil=fopen("/proc/net/route","r");
    while(fgets(line,sizeof(line)-1,fil))
    {
        char iface[16];
        int flags,refcnt,use,metric,mtu,window;
        unsigned int dst,nexthop,mask;
        int rc;

        rc=sscanf(line,"%s\t%x\t%x\t%d\t%d\t%d\t%d\t%x\t%o\t%d\n",iface,&dst,&nexthop,&flags,&refcnt,&use,&metric,&mask,&mtu,&window);

        if (rc==10 && (ntohl(dst)!=ntohl(network)) && ((ntohl(dst) & ntohl(netmask)) == ntohl(network))) {
            if (nexthop==0)
                nextHopRoutes.push_back(Route(dst, nexthop, mask, iface));
            else
                oneHopRoutes.push_back(Route(dst, nexthop, mask, iface));
        }
    }

    fclose(fil);

    TRACE_EXIT();
    return;
}

#if DEBUG
static void routeDump(const RouteList &r)
{
    TRACE_ENTER();

    if (r.size()) {
        for (RouteList::const_iterator i=r.begin(); i!=r.end(); i++) {
            ostringstream out;
            out << *i;
        }
        LOG_DEBUG("%s", out.str().c_str());
    }

    TRACE_EXIT();
}
#endif // DEBUG

typedef struct detector
{
    Client *watcherClientPtr;

    useconds_t reportperiod;		/* frequency to generate reports at */
    int reportnum;
    string iface;
    int routeedgewidth;
    Color onehopcolor;
    Color nexthopcolor;

    string nexthoplayer;
    string onehoplayer;

    int duration;			  /* Time to run (in seconds) or 0 to run until broken */

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

    RouteList prevNextHopRoutes;   /* The previous next hop list we saw. */
    RouteList prevOneHopRoutes;    /* the previous one hop list we saw. */

    bool constantUpdates;

} detector;

typedef struct DetectorInit
{
    useconds_t reportperiod;		/* frequency to generate reports at */
    string iface;
    int onehopfamily;
    Color onehopcolor;
    Color nexthopcolor;
    int mouthnum;
    int duration;			  /* Time to run (in seconds) or 0 to run until broken */
    int routeedgewidth;

    string serverName;

    string nexthoplayer;
    string onehoplayer;

    bool constantUpdates;

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

} DetectorInit;

static void updateRoutes(detector *st, RouteList &oneHopRoutes, RouteList &nextHopRoutes)
{
    TRACE_ENTER();

    static vector<MessagePtr> messages;
    if(!messages.empty())
        messages.clear();

    bool sendMessage=false;

    /*
     * If constant updates is true, always send route list. Else only send when the new list differs from the old.
     */
    if (st->constantUpdates || oneHopRoutes!=st->prevOneHopRoutes) {
        ConnectivityMessagePtr message(new ConnectivityMessage);
        message->layer=ONE_HOP_ROUTING_LAYER;
        for (RouteList::const_iterator i=oneHopRoutes.begin(); i!=oneHopRoutes.end(); i++)
            if (st->iface != string(i->iface))
                message->neighbors.push_back(boost::asio::ip::address_v4(i->dst));
        st->prevOneHopRoutes=oneHopRoutes;
        messages.push_back(message);
        sendMessage=true;
    }
    if (st->constantUpdates || nextHopRoutes!=st->prevNextHopRoutes) {
        ConnectivityMessagePtr message(new ConnectivityMessage);
        message->layer=ROUTING_LAYER;
        for (RouteList::const_iterator i=nextHopRoutes.begin(); i!=nextHopRoutes.end(); i++)
            if (st->iface != string(i->iface))
                message->neighbors.push_back(boost::asio::ip::address_v4(i->nexthop));
        st->prevNextHopRoutes=nextHopRoutes;
        messages.push_back(message);
        sendMessage=true;
    }

    if (sendMessage)
        st->watcherClientPtr->sendMessages(messages);

    TRACE_EXIT();
}

/* This is called regularly by the select loop (below)
 * It will create a message, and send it to this node's coordinator
 */
static void detectorSend(detector *st)
{
    TRACE_ENTER();

    RouteList oneHopRoutes, nextHopRoutes;

    routeRead(st->filterNetwork.s_addr, st->filterMask.s_addr, oneHopRoutes, nextHopRoutes);

    long long int curtime;
    struct timeval tp;
    gettimeofday(&tp, NULL);
    curtime=(long long int)tp.tv_sec*1000 + (long long int)tp.tv_usec/1000;

    LOG_DEBUG("node= " << st->localhost.s_addr << " time= " << curtime << " routes= " << nextHopRoutes.size() << " onehoproutes= " << oneHopRoutes.size() << " totalroutes= " << nextHopRoutes.size()+oneHopRoutes.size());

    st->reportnum++;

    updateRoutes(st,oneHopRoutes, nextHopRoutes);

    TRACE_EXIT();
}

static detector *detectorInit(DetectorInit *detinit)
{
    TRACE_ENTER();
    detector *st;

    st=new detector;
    st->iface="";

    st->watcherClientPtr=new Client(detinit->serverName);
    if(st->watcherClientPtr==NULL)
        return NULL;

    st->duration=detinit->duration;
    st->constantUpdates=detinit->constantUpdates;
    st->reportperiod=detinit->reportperiod;
    st->reportnum=0;
    st->iface=detinit->iface;

    st->onehoplayer=detinit->onehoplayer;
    st->onehopcolor=detinit->onehopcolor;

    st->nexthoplayer=detinit->nexthoplayer;
    st->nexthopcolor=st->nexthopcolor;

    st->routeedgewidth=detinit->routeedgewidth;

	st->filterNetwork.s_addr=detinit->filterNetwork.s_addr;
	st->filterMask.s_addr=detinit->filterMask.s_addr;
	st->localhost.s_addr=detinit->localhost.s_addr;

    TRACE_EXIT();
    return st;
}

/*
 * Wait around until we are ready to generate a message, then do it.
 */
static void selectLoop(detector *dt)
{
    TRACE_ENTER();

    time_t startTime=time(NULL);

    while(1)
    {
        usleep(dt->reportperiod*(useconds_t)1000.0);
        detectorSend(dt);

        if (dt->duration)
            if (time(NULL)-startTime>dt->duration)
                break;
    }

    dt->watcherClientPtr->wait();

    TRACE_EXIT();
}

int main(int argc, char *argv[])
{
    TRACE_ENTER();
    detector *dt;
    int ch;
    string logPropsFile("routeFeeder.log.properties");

    DetectorInit detinit;
    detinit.iface="";
    detinit.onehopcolor=Color::green;
    detinit.onehoplayer="One Hop Routing";
    detinit.nexthopcolor=Color::blue;
    detinit.nexthoplayer="Network Routing";
    detinit.reportperiod=2000;
    detinit.duration=0;
    detinit.routeedgewidth=15;

	detinit.filterNetwork.s_addr=0;
	detinit.filterMask.s_addr=0;
	detinit.localhost.s_addr=0;

    while ((ch = getopt(argc, argv, "m:n:h:o:x:t:e:b:i:d:p:w:l:c?")) != -1)
        switch (ch)
        {
            case 'm': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterMask))
                      {
                          fprintf(stderr, "Error parsing filter mask: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'n': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterNetwork))
                      {
                          fprintf(stderr, "Error parsing filter network: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'h': if(-1 == inet_pton(AF_INET, optarg, &detinit.localhost))
                      {
                          fprintf(stderr, "Error parsing localhost address: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'o':
                      detinit.onehopcolor.fromString(optarg);
                      break;
            case 'x':
                      detinit.nexthopcolor.fromString(optarg);
                      break;
            case 't':
                      sscanf(optarg,"%d",&detinit.duration);
                      break;
            case 'e':
                      detinit.onehoplayer=string(optarg);
                      break;
            case 'b':
                      detinit.nexthoplayer=string(optarg);
                      break;
            case 'i':
                      detinit.iface=string(optarg);
                      break;
            case 'd':
                      detinit.serverName=string(optarg);
                      break;
            case 'p':
                      sscanf(optarg,"%d",&detinit.reportperiod);
                      break;
            case 'w':
                      sscanf(optarg, "%d", &detinit.routeedgewidth);
                      break;
            case 'l':
                      logPropsFile=string(optarg);
                      break;
            case 'u':
                      detinit.constantUpdates=true;
                      break;
            case '?':
            default:
                      fprintf(stderr,"%s - poll the linux routing table, and draw the routes in the watcher\n"
                              "-d ipaddr/hostname - specify watcherd address to connect to (duck)\n"
                              "-h ipaddr - this host's address\n"
                              "-m netmask - the mask used to filter the routes (ex. 255.255.255.0)\n"
                              "-n network - the network used to filter the routes (ex. 192.168.1.0)\n"
                              "-p milliseconds - specify the period to poll and report\n"
                              "-i interface - display only routes through this ethernet interface (or any if unspecified)\n"
                              "-e layer - onehop layer name\n"
                              "-b layer - nexthop layer name\n"
                              "-t seconds - Run for this long, then exit\n"
                              "-u - send updates every period. If not set, only send updates when the routes change.\n",
                              // "-c - use connectivity messages instead of edge messages (this disables width and color settings)\n"
                              basename(argv[0])
                             );
                      exit(1);
                      break;
        }

    // init the logging system
    LOAD_LOG_PROPS(logPropsFile);
    LOG_INFO("Logger initialized from file \"" << logPropsFile << "\"");

	// check args, errors, etc before doing real work
	if(detinit.localhost.s_addr == 0)
    {
        fprintf(stderr, "localhost address cannot be blank\n");
        exit(EX_USAGE);
    }
	if(detinit.filterNetwork.s_addr == 0)
	{
        fprintf(stderr, "filter network cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.filterMask.s_addr == 0)
	{
        fprintf(stderr, "filter mask cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.serverName.empty())
	{
        fprintf(stderr, "watcherd hostname cannot be blank\n");
        exit(EX_USAGE);
	}

    dt=detectorInit(&detinit);

    if (dt==NULL)
    {
        fprintf(stderr,"detector init failed, probably could not connect to infrastructure demon.\n");
        exit(1);
    }
    printf("%s: starting\n",argv[0]);
    selectLoop(dt);

    TRACE_EXIT();
    return 0;
}
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include <stdint.h>
#include "croseserver.h"
#include "croseclient.h"
#include "croseisc.h"
#include "ePacketType.h"

TEST( TestRoseNetwork, Constructor )
{
	CRoseServer network;
}

TEST( TestRoseNetwork, TestInit )
{
	CRoseServer network;
	EXPECT_EQ( true, network.Init( "127.0.0.1", 29000 ) );
	EXPECT_EQ( 29000, network.GetPort( ) );
	EXPECT_EQ( "127.0.0.1", network.GetIpAddress( ) );
}

TEST( TestRoseNetwork, TestInitHostLessThanTwo )
{
	CRoseServer network;
	EXPECT_EQ( false, network.Init( "0", 29000 ) );
	EXPECT_NE( 29000, network.GetPort( ) );
	EXPECT_NE( "0", network.GetIpAddress( ) );
}

TEST( TestRoseNetwork, TestConnectIp )
{
	//	std::mutex mutex;
	//	std::condition_variable cv;
	//	bool done = false;

	CRoseServer network;
	EXPECT_EQ( true, network.Init( "63.117.14.24", 80 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	//	EXPECT_CALL( network, OnConnect() )
	//                                .WillOnce(testing::Invoke([&]()->int {
	//                                            std::lock_guard<std::mutex> lock(mutex);
	//                                            done = true;
	//                                            cv.notify_all();
	//                                            return 1; }));

	//	EXPECT_CALL( network, OnConnected() )
	//				.WillOnce(testing::Invoke([&]()->int {
	//				            std::lock_guard<std::mutex> lock(mutex);
	//				            done = true;
	//				            cv.notify_all();
	//				            return 1; }));

	//	std::unique_lock<std::mutex> lock(mutex);
	//	std::unique_lock<std::mutex> lock2(mutex2);
	//	EXPECT_TRUE(cv.wait_for(lock,
	//					std::chrono::seconds(1),
	//					[&done] { return done; })
	//					);
	//	EXPECT_TRUE(cv.wait_for(lock,
	//                                        std::chrono::seconds(1),
	//                                        [&done] { return done; })
	//                                        );
	//	std::this_thread::sleep_for(std::chrono::milliseconds(100));
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestRecv )
{
	CRoseServer network;
	EXPECT_EQ( true, network.Init( "63.117.14.24", 80 ) );
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); // Make sure we wait a little for data to come in
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestReconnect )
{
	CRoseClient network;
	EXPECT_EQ( true, network.Init( "63.117.14.24", 80 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	//EXPECT_NO_FATAL_FAILURE( network.Disconnect( ) );
	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	EXPECT_NO_FATAL_FAILURE( network.Reconnect( ) );
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestConnectHostName )
{
	//	::testing::FLAGS_gmock_verbose = "info";
	//	std::mutex mutex;
	//        std::condition_variable cv;
	//        bool done = false;

	CRoseServer network;
	EXPECT_NO_FATAL_FAILURE( network.Init( "google.com", 80 ) ); // We are going to connect to google's website using hostname.
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	//	EXPECT_CALL( network, OnConnect() ).Times(1);
	//	EXPECT_CALL( network, OnConnected() )
	//                                .WillOnce(testing::Invoke([&]()->int {
	//                                            std::lock_guard<std::mutex> lock(mutex);
	//                                            done = true;
	//                                            cv.notify_all();
	//                                            return 1; }));
	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	//	std::unique_lock<std::mutex> lock(mutex);
	//	EXPECT_TRUE(cv.wait_for(lock,
	//                                        std::chrono::seconds(4),
	//                                        [&done] { return done; })
	//                                        );
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestListen )
{
	//	::testing::FLAGS_gmock_verbose = "info";
	//	std::mutex mutex;
	//        std::condition_variable cv;
	//        bool done = false;

	CRoseServer network;
	EXPECT_EQ( true, network.Init( "127.0.0.1", 29000 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Listen( ) );
	//	EXPECT_CALL( network, OnListening() )
	//                                        .WillOnce( testing::Invoke([&]()->int {
	//                                                        std::lock_guard<std::mutex> lock(mutex);
	//                                                        done = true;
	//                                                        cv.notify_all();
	//                                                        return 1; }));

	//	std::unique_lock<std::mutex> lock(mutex);
	//        EXPECT_TRUE(cv.wait_for(lock, std::chrono::seconds(1), [&done] { return done; }));

	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestListenAndConnect )
{
	//	std::mutex mutex;
	//	std::condition_variable cv;
	//	bool done = false;

	CRoseServer network;
	CRoseClient netConnect;
	EXPECT_EQ( true, network.Init( "127.0.0.1", 29100 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Listen( ) );
	//	EXPECT_CALL( network, OnListening() )
	//					.WillOnce( testing::Invoke([&]()->int {
	//							std::lock_guard<std::mutex> lock(mutex);
	//							done = true;
	//							cv.notify_all();
	//							return 1; }));

	//	std::unique_lock<std::mutex> lock(mutex);
	//	EXPECT_TRUE(cv.wait_for(lock, std::chrono::seconds(1), [&done] { return done; }));

	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	EXPECT_EQ( true, netConnect.Init( "127.0.0.1", 29100 ) );
	EXPECT_NO_FATAL_FAILURE( netConnect.Connect( ) );

	//std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	CPacket* pak = new CPacket( ePacketType::PAKCS_CHAR_LIST_REQ, sizeof( pakChannelList_Req ) );
	pak->pChannelListReq.lServerID = 0x77;
	netConnect.Send( pak->Buffer );

	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); // Change this to condition variables
	EXPECT_NO_FATAL_FAILURE( netConnect.Disconnect( ) );
	EXPECT_NO_FATAL_FAILURE( netConnect.Shutdown( ) );

	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestISCListenAndConnect )
{
        //      std::mutex mutex;
        //      std::condition_variable cv;
        //      bool done = false;

        CRoseServer network ( true );
        CRoseISC netConnect;
        EXPECT_EQ( true, network.Init( "127.0.0.1", 29110 ) ); // We are going to connect to google's website
        EXPECT_NO_FATAL_FAILURE( network.Listen( ) );
        //      EXPECT_CALL( network, OnListening() )
        //                                      .WillOnce( testing::Invoke([&]()->int {
        //                                                      std::lock_guard<std::mutex> lock(mutex);
        //                                                      done = true;
        //                                                      cv.notify_all();
        //                                                      return 1; }));

        //      std::unique_lock<std::mutex> lock(mutex);
        //      EXPECT_TRUE(cv.wait_for(lock, std::chrono::seconds(1), [&done] { return done; }));

        std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
        EXPECT_EQ( true, netConnect.Init( "127.0.0.1", 29110 ) );
        EXPECT_NO_FATAL_FAILURE( netConnect.Connect( ) );

        //std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
        CPacket* pak = new CPacket( ePacketType::PAKCS_CHAR_LIST_REQ, sizeof( pakChannelList_Req ) );
        pak->pChannelListReq.lServerID = 0x77;
        netConnect.Send( pak->Buffer );

        std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); // Change this to condition variables
        EXPECT_NO_FATAL_FAILURE( netConnect.Disconnect( ) );
        EXPECT_NO_FATAL_FAILURE( netConnect.Shutdown( ) );

        EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}
<commit_msg>Updated Uint Tests<commit_after>#include "gtest/gtest.h"

#include <stdint.h>
#include "croseserver.h"
#include "mock/mock_croseclient.h"
#include "croseisc.h"
#include "ePacketType.h"

TEST( TestRoseNetwork, Constructor )
{
	CRoseServer network;
}

TEST( TestRoseNetwork, TestInit )
{
	CRoseServer network;
	EXPECT_EQ( true, network.Init( "127.0.0.1", 29000 ) );
	EXPECT_EQ( 29000, network.GetPort( ) );
	EXPECT_EQ( "127.0.0.1", network.GetIpAddress( ) );
}

TEST( TestRoseNetwork, TestInitHostLessThanTwo )
{
	CRoseServer network;
	EXPECT_EQ( false, network.Init( "0", 29000 ) );
	EXPECT_NE( 29000, network.GetPort( ) );
	EXPECT_NE( "0", network.GetIpAddress( ) );
}

TEST( TestRoseNetwork, TestConnectIp )
{
	//	std::mutex mutex;
	//	std::condition_variable cv;
	//	bool done = false;

	CRoseServer network;
	EXPECT_EQ( true, network.Init( "63.117.14.24", 80 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	//	EXPECT_CALL( network, OnConnect() )
	//                                .WillOnce(testing::Invoke([&]()->int {
	//                                            std::lock_guard<std::mutex> lock(mutex);
	//                                            done = true;
	//                                            cv.notify_all();
	//                                            return 1; }));

	//	EXPECT_CALL( network, OnConnected() )
	//				.WillOnce(testing::Invoke([&]()->int {
	//				            std::lock_guard<std::mutex> lock(mutex);
	//				            done = true;
	//				            cv.notify_all();
	//				            return 1; }));

	//	std::unique_lock<std::mutex> lock(mutex);
	//	std::unique_lock<std::mutex> lock2(mutex2);
	//	EXPECT_TRUE(cv.wait_for(lock,
	//					std::chrono::seconds(1),
	//					[&done] { return done; })
	//					);
	//	EXPECT_TRUE(cv.wait_for(lock,
	//                                        std::chrono::seconds(1),
	//                                        [&done] { return done; })
	//                                        );
	//	std::this_thread::sleep_for(std::chrono::milliseconds(100));
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestRecv )
{
	CRoseServer network;
	EXPECT_EQ( true, network.Init( "63.117.14.24", 80 ) );
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); // Make sure we wait a little for data to come in
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestReconnect )
{
	CRoseClient network;
	EXPECT_EQ( true, network.Init( "63.117.14.24", 80 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	//EXPECT_NO_FATAL_FAILURE( network.Disconnect( ) );
	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	EXPECT_NO_FATAL_FAILURE( network.Reconnect( ) );
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestConnectHostName )
{
	//	::testing::FLAGS_gmock_verbose = "info";
	//	std::mutex mutex;
	//        std::condition_variable cv;
	//        bool done = false;

	CRoseServer network;
	EXPECT_NO_FATAL_FAILURE( network.Init( "google.com", 80 ) ); // We are going to connect to google's website using hostname.
	EXPECT_NO_FATAL_FAILURE( network.Connect( ) );
	//	EXPECT_CALL( network, OnConnect() ).Times(1);
	//	EXPECT_CALL( network, OnConnected() )
	//                                .WillOnce(testing::Invoke([&]()->int {
	//                                            std::lock_guard<std::mutex> lock(mutex);
	//                                            done = true;
	//                                            cv.notify_all();
	//                                            return 1; }));
	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	//	std::unique_lock<std::mutex> lock(mutex);
	//	EXPECT_TRUE(cv.wait_for(lock,
	//                                        std::chrono::seconds(4),
	//                                        [&done] { return done; })
	//                                        );
	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestListen )
{
	//	::testing::FLAGS_gmock_verbose = "info";
	//	std::mutex mutex;
	//        std::condition_variable cv;
	//        bool done = false;

	CRoseServer network;
	EXPECT_EQ( true, network.Init( "127.0.0.1", 29000 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Listen( ) );
	//	EXPECT_CALL( network, OnListening() )
	//                                        .WillOnce( testing::Invoke([&]()->int {
	//                                                        std::lock_guard<std::mutex> lock(mutex);
	//                                                        done = true;
	//                                                        cv.notify_all();
	//                                                        return 1; }));

	//	std::unique_lock<std::mutex> lock(mutex);
	//        EXPECT_TRUE(cv.wait_for(lock, std::chrono::seconds(1), [&done] { return done; }));

	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestListenAndConnect )
{
	//	std::mutex mutex;
	//	std::condition_variable cv;
	//	bool done = false;

	CRoseServer network;
	CRoseClient netConnect;
	EXPECT_EQ( true, network.Init( "127.0.0.1", 29100 ) ); // We are going to connect to google's website
	EXPECT_NO_FATAL_FAILURE( network.Listen( ) );
	//	EXPECT_CALL( network, OnListening() )
	//					.WillOnce( testing::Invoke([&]()->int {
	//							std::lock_guard<std::mutex> lock(mutex);
	//							done = true;
	//							cv.notify_all();
	//							return 1; }));

	//	std::unique_lock<std::mutex> lock(mutex);
	//	EXPECT_TRUE(cv.wait_for(lock, std::chrono::seconds(1), [&done] { return done; }));

	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	EXPECT_EQ( true, netConnect.Init( "127.0.0.1", 29100 ) );
	EXPECT_NO_FATAL_FAILURE( netConnect.Connect( ) );

	//std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	CPacket* pak = new CPacket( ePacketType::PAKCS_CHAR_LIST_REQ, sizeof( pakChannelList_Req ) );
	pak->pChannelListReq.lServerID = 0x77;
	netConnect.Send( pak->Buffer );

	std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); // Change this to condition variables
	EXPECT_NO_FATAL_FAILURE( netConnect.Disconnect( ) );
	EXPECT_NO_FATAL_FAILURE( netConnect.Shutdown( ) );

	std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );

	EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestListenAndConnect2 )
{
        CRoseServer network;
        CRoseClient_Mock netConnect;
        EXPECT_EQ( true, network.Init( "127.0.0.1", 29110 ) );
        EXPECT_NO_FATAL_FAILURE( network.Listen( ) );

        std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
        EXPECT_EQ( true, netConnect.Init( "127.0.0.1", 29110 ) );
        EXPECT_NO_FATAL_FAILURE( netConnect.Connect( ) );

        //std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
	CPacket* pak = new CPacket( ePacketType::PAKCS_ACCEPT_REQ );
        netConnect.Send( pak );

        CPacket* pak2 = new CPacket( ePacketType::PAKCS_CHAR_LIST_REQ, sizeof( pakChannelList_Req ) );
        pak2->pChannelListReq.lServerID = 0x77;
        netConnect.Send( pak2 );

	CPacket* pak3 = new CPacket( ePacketType::PAKCS_ALIVE );
        netConnect.Send( pak3 );

        std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); // Change this to condition variables
        EXPECT_NO_FATAL_FAILURE( netConnect.Disconnect( ) );
        EXPECT_NO_FATAL_FAILURE( netConnect.Shutdown( ) );

        EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}

TEST( TestRoseNetwork, TestISCListenAndConnect )
{
        //      std::mutex mutex;
        //      std::condition_variable cv;
        //      bool done = false;

        CRoseServer network ( true );
        CRoseISC netConnect;
        EXPECT_EQ( true, network.Init( "127.0.0.1", 29110 ) ); // We are going to connect to google's website
        EXPECT_NO_FATAL_FAILURE( network.Listen( ) );
        //      EXPECT_CALL( network, OnListening() )
        //                                      .WillOnce( testing::Invoke([&]()->int {
        //                                                      std::lock_guard<std::mutex> lock(mutex);
        //                                                      done = true;
        //                                                      cv.notify_all();
        //                                                      return 1; }));

        //      std::unique_lock<std::mutex> lock(mutex);
        //      EXPECT_TRUE(cv.wait_for(lock, std::chrono::seconds(1), [&done] { return done; }));

        std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
        EXPECT_EQ( true, netConnect.Init( "127.0.0.1", 29110 ) );
        EXPECT_NO_FATAL_FAILURE( netConnect.Connect( ) );

        //std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) );
        CPacket* pak = new CPacket( ePacketType::PAKCS_CHAR_LIST_REQ, sizeof( pakChannelList_Req ) );
        pak->pChannelListReq.lServerID = 0x77;
        netConnect.Send( pak );

        std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); // Change this to condition variables
        EXPECT_NO_FATAL_FAILURE( netConnect.Disconnect( ) );
        EXPECT_NO_FATAL_FAILURE( netConnect.Shutdown( ) );

        EXPECT_NO_FATAL_FAILURE( network.Shutdown( ) );
}
<|endoftext|>


<commit_before>/* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of NVIDIA CORPORATION nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <libconfig.h++>
#include <yaml-cpp/yaml.h>
#include <cassert>

namespace config
{

class CompoundConfigNode
{
 private:
  libconfig::Setting* LNode;
  YAML::Node YNode;

 public:
  CompoundConfigNode(){}
  CompoundConfigNode(libconfig::Setting* _lnode, YAML::Node _ynode);

  libconfig::Setting& getLNode() {return *LNode;}
  YAML::Node getYNode() {return YNode;}

  CompoundConfigNode lookup(const char *path) const;
  inline CompoundConfigNode lookup(const std::string &path) const
  { return(lookup(path.c_str())); }

  bool lookupValue(const char *name, bool &value) const;
  bool lookupValue(const char *name, int &value) const;
  bool lookupValue(const char *name, unsigned int &value) const;
  bool lookupValue(const char *name, long long &value) const;
  bool lookupValue(const char *name, unsigned long long &value) const;
  bool lookupValue(const char *name, double &value) const;
  bool lookupValue(const char *name, float &value) const;
  bool lookupValue(const char *name, const char *&value) const;
  bool lookupValue(const char *name, std::string &value) const;

  inline bool lookupValue(const std::string &name, bool &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, int &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, unsigned int &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, long long &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name,
                          unsigned long long &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, double &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, float &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, const char *&value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, std::string &value) const
  { return(lookupValue(name.c_str(), value)); }

  bool exists(const char *name) const;

  inline bool exists(const std::string &name) const
  { return(exists(name.c_str())); }

  bool lookupArrayValue(const char* name, std::vector<std::string> &vectorValue) const;

  inline bool lookupArrayValue(const std::string &name, std::vector<std::string> &vectorValue) const
  { return(lookupArrayValue(name.c_str(), vectorValue));}

  bool isList() const;
  bool isArray() const;
  int getLength() const;

  CompoundConfigNode operator [](int idx) const;

  bool getArrayValue(std::vector<std::string> &vectorValue);
  // iterate through all maps and get the keys within a node
  bool getMapKeys(std::vector<std::string> &mapKeys);

};

class CompoundConfig
{
 private:
  bool useLConfig;
  libconfig::Config LConfig;
  YAML::Node YConfig;
  CompoundConfigNode root;

 public:
  CompoundConfig(){assert(false);}
  CompoundConfig(const char* inputFile);
  CompoundConfig(char* inputFile) : CompoundConfig((const char*) inputFile) {}
  CompoundConfig(std::vector<std::string> inputFiles);

  ~CompoundConfig(){}

  libconfig::Config& getLConfig();
  YAML::Node& getYConfig();
  CompoundConfigNode getRoot() const;

  bool hasLConfig() { return useLConfig;}
};

  uint32_t parseElementSize(std::string name);
  std::string parseName(std::string name);

} // namespace config
<commit_msg>[CompoundConfigNode] Avoid uninitialized warning<commit_after>/* Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of NVIDIA CORPORATION nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <libconfig.h++>
#include <yaml-cpp/yaml.h>
#include <cassert>

namespace config
{

class CompoundConfigNode
{
 private:
  libconfig::Setting* LNode = nullptr;
  YAML::Node YNode;

 public:
  CompoundConfigNode(){}
  CompoundConfigNode(libconfig::Setting* _lnode, YAML::Node _ynode);

  libconfig::Setting& getLNode() {return *LNode;}
  YAML::Node getYNode() {return YNode;}

  CompoundConfigNode lookup(const char *path) const;
  inline CompoundConfigNode lookup(const std::string &path) const
  { return(lookup(path.c_str())); }

  bool lookupValue(const char *name, bool &value) const;
  bool lookupValue(const char *name, int &value) const;
  bool lookupValue(const char *name, unsigned int &value) const;
  bool lookupValue(const char *name, long long &value) const;
  bool lookupValue(const char *name, unsigned long long &value) const;
  bool lookupValue(const char *name, double &value) const;
  bool lookupValue(const char *name, float &value) const;
  bool lookupValue(const char *name, const char *&value) const;
  bool lookupValue(const char *name, std::string &value) const;

  inline bool lookupValue(const std::string &name, bool &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, int &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, unsigned int &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, long long &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name,
                          unsigned long long &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, double &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, float &value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, const char *&value) const
  { return(lookupValue(name.c_str(), value)); }

  inline bool lookupValue(const std::string &name, std::string &value) const
  { return(lookupValue(name.c_str(), value)); }

  bool exists(const char *name) const;

  inline bool exists(const std::string &name) const
  { return(exists(name.c_str())); }

  bool lookupArrayValue(const char* name, std::vector<std::string> &vectorValue) const;

  inline bool lookupArrayValue(const std::string &name, std::vector<std::string> &vectorValue) const
  { return(lookupArrayValue(name.c_str(), vectorValue));}

  bool isList() const;
  bool isArray() const;
  int getLength() const;

  CompoundConfigNode operator [](int idx) const;

  bool getArrayValue(std::vector<std::string> &vectorValue);
  // iterate through all maps and get the keys within a node
  bool getMapKeys(std::vector<std::string> &mapKeys);

};

class CompoundConfig
{
 private:
  bool useLConfig;
  libconfig::Config LConfig;
  YAML::Node YConfig;
  CompoundConfigNode root;

 public:
  CompoundConfig(){assert(false);}
  CompoundConfig(const char* inputFile);
  CompoundConfig(char* inputFile) : CompoundConfig((const char*) inputFile) {}
  CompoundConfig(std::vector<std::string> inputFiles);

  ~CompoundConfig(){}

  libconfig::Config& getLConfig();
  YAML::Node& getYConfig();
  CompoundConfigNode getRoot() const;

  bool hasLConfig() { return useLConfig;}
};

  uint32_t parseElementSize(std::string name);
  std::string parseName(std::string name);

} // namespace config
<|endoftext|>


<commit_before>//
// Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
//

#include <sys/types.h>
#include <unistd.h>

#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/host_name.hpp>
#include <boost/program_options.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

#include <base/task.h>
#include <base/logging.h>
#include <sandesh/sandesh_types.h>
#include <sandesh/sandesh.h>
#include <sandesh/common/vns_constants.h>
#include <sandesh/common/vns_types.h>
#include <sandesh/common/flow_types.h>

namespace opt = boost::program_options;

class MockGenerator {
public:
    MockGenerator(std::string &hostname, std::string &module_name,
                  std::string &node_type_name,
                  std::string &instance_id,
                  int http_server_port, int start_vn, int end_vn, int other_vn,
                  int num_vns, int vm_iterations,
                  std::vector<std::string> &collectors,
                  std::vector<uint32_t> &ip_vns,
                  int ip_start_index, int num_flows_per_vm,
                  EventManager *evm) :
        hostname_(hostname),
        module_name_(module_name),
        node_type_name_(node_type_name),
        instance_id_(instance_id),
        http_server_port_(http_server_port),
        start_vn_(start_vn),
        end_vn_(end_vn),
        other_vn_(other_vn),
        num_vns_(num_vns),
        vm_iterations_(vm_iterations),
        collectors_(collectors),
        ip_vns_(ip_vns),
        ip_start_index_(ip_start_index),
        num_flows_per_vm_(num_flows_per_vm),
        rgen_(std::time(0)),
        u_rgen_(&rgen_),
        evm_(evm) {
    }

    bool Run() {
        // Initialize Sandesh
        Sandesh::CollectorSubFn csf = 0;
        Sandesh::InitGenerator(module_name_, hostname_,
            node_type_name_, instance_id_, evm_, http_server_port_,
            csf, collectors_, NULL);
        // Enqueue send flow task
        TaskScheduler *scheduler = TaskScheduler::GetInstance();
        SendFlowTask *ftask(new SendFlowTask(this,
            scheduler->GetTaskId("mockgen::SendFlowTask"), -1));
        scheduler->Enqueue(ftask);
        return true;
    }

private:

    class SendFlowTask : public Task {
    public:
        SendFlowTask(MockGenerator *mock_generator,
            int task_id, int task_instance) :
            Task(task_id, task_instance),
            mgen_(mock_generator) {
        }

        bool Run() {
            // Populate flows if not done
            if (mgen_->flows_.empty()) {
                int other_vn = mgen_->other_vn_;
                for (int vn = mgen_->start_vn_; vn < mgen_->end_vn_; vn++) {
                    for (int nvm = 0; nvm < mgen_->vm_iterations_; nvm++) {
                        for (int nflow = 0; nflow < mgen_->num_flows_per_vm_;
                             nflow++) {
                            uint64_t init_packets(mgen_->dFlowPktsPerSec(
                                mgen_->rgen_));
                            uint64_t init_bytes(init_packets *
                                mgen_->dBytesPerPacket(mgen_->rgen_));
                            uint32_t sourceip(mgen_->ip_vns_[vn] +
                                mgen_->ip_start_index_ + nvm);
                            uint32_t destip(mgen_->ip_vns_[other_vn] +
                                mgen_->ip_start_index_ + nvm);
                            FlowDataIpv4 flow_data;
                            boost::uuids::uuid flowuuid(mgen_->u_rgen_());
                            flow_data.set_flowuuid(to_string(flowuuid));
                            flow_data.set_direction_ing(mgen_->dDirection(
                                mgen_->rgen_));
                            std::string sourcevn(mgen_->kVnPrefix +
                                integerToString(vn));
                            flow_data.set_sourcevn(sourcevn);
                            std::string destvn(mgen_->kVnPrefix +
                                integerToString(other_vn));
                            flow_data.set_destvn(destvn);
                            flow_data.set_sourceip(sourceip);
                            flow_data.set_destip(destip);
                            flow_data.set_sport(mgen_->dPort(mgen_->rgen_));
                            flow_data.set_dport(mgen_->dPort(mgen_->rgen_));
                            flow_data.set_protocol(mgen_->kProtocols[
                                mgen_->dProtocols(mgen_->rgen_)]);
                            flow_data.set_setup_time(UTCTimestampUsec());
                            flow_data.set_packets(init_packets);
                            flow_data.set_bytes(init_bytes);
                            flow_data.set_diff_packets(init_packets);
                            flow_data.set_diff_bytes(init_bytes);
                            mgen_->flows_.push_back(flow_data);
                        }
                    }
                    other_vn = (other_vn + 1) % mgen_->num_vns_;
                }
            }
            // Send the flows periodically
            int lflow_cnt = 0;
            for (std::vector<FlowDataIpv4>::iterator it = mgen_->flows_.begin() +
                 mgen_->flow_counter_; it != mgen_->flows_.end(); ++it) {
                FlowDataIpv4 &flow_data(*it);
                uint64_t new_packets(mgen_->dFlowPktsPerSec(mgen_->rgen_));
                uint64_t new_bytes(new_packets *
                    mgen_->dBytesPerPacket(mgen_->rgen_));
                uint64_t old_packets(flow_data.get_packets());
                uint64_t old_bytes(flow_data.get_bytes());
                flow_data.set_packets(old_packets + new_packets);
                flow_data.set_bytes(old_bytes + new_bytes);
                flow_data.set_diff_packets(new_packets);
                flow_data.set_diff_bytes(new_bytes);
                FLOW_DATA_IPV4_OBJECT_SEND(flow_data);
                lflow_cnt++;
                mgen_->flow_counter_++;
                if (lflow_cnt == mgen_->kNumFlowsInIteration) {
                    return false;
                }
            }
            // Completed iteration, reset flow counter
            mgen_->flow_counter_ = 0;
            return false;
        }

    private:
        MockGenerator *mgen_;
    };

    const static std::string kVnPrefix;
    const static std::string kVmPrefix;
    const static int kBytesPerPacket = 1024;
    const static int kOtherVnPktsPerSec = 1000;
    const static int kUveMsgIntvlInSec = 10;
    const static int kNumFlowsInIteration = 145 * 10;
    const static int kFlowMsgIntvlInSec = 1;
    const static int kFlowPktsPerSec = 100;

    const static boost::random::uniform_int_distribution<>
        dBytesPerPacket;
    const static boost::random::uniform_int_distribution<>
        dOtherVnPktsPerSec;
    const static boost::random::uniform_int_distribution<>
        dFlowPktsPerSec;
    const static boost::random::uniform_int_distribution<>
        dDirection;
    const static boost::random::uniform_int_distribution<>
        dPort;
    const static std::vector<int> kProtocols;
    const static boost::random::uniform_int_distribution<>
        dProtocols;

    const std::string hostname_;
    const std::string module_name_;
    const std::string node_type_name_;
    const std::string instance_id_;
    const int http_server_port_;
    const int start_vn_;
    const int end_vn_;
    const int other_vn_;
    const int num_vns_;
    const int vm_iterations_;
    const std::vector<std::string> collectors_;
    const std::vector<uint32_t> ip_vns_;
    const int ip_start_index_;
    const int num_flows_per_vm_;
    std::vector<FlowDataIpv4> flows_;
    static int flow_counter_;
    boost::random::mt19937 rgen_;
    boost::uuids::random_generator u_rgen_;
    EventManager *evm_;

    friend class SendFlowTask;
};

const std::string MockGenerator::kVnPrefix("default-domain:mock-gen-test:vn");
const std::string MockGenerator::kVmPrefix("vm");
const boost::random::uniform_int_distribution<>
    MockGenerator::dBytesPerPacket(1, MockGenerator::kBytesPerPacket);
const boost::random::uniform_int_distribution<>
    MockGenerator::dOtherVnPktsPerSec(1, MockGenerator::kOtherVnPktsPerSec);
const boost::random::uniform_int_distribution<>
    MockGenerator::dFlowPktsPerSec(1, MockGenerator::kFlowPktsPerSec);
const boost::random::uniform_int_distribution<>
    MockGenerator::dDirection(0, 1);
const boost::random::uniform_int_distribution<>
    MockGenerator::dPort(0, 65535);
const std::vector<int> MockGenerator::kProtocols = boost::assign::list_of
    (6)(17)(1);
const boost::random::uniform_int_distribution<>
    MockGenerator::dProtocols(0, MockGenerator::kProtocols.size() - 1);
int MockGenerator::flow_counter_(0);

int main(int argc, char *argv[]) {
    opt::options_description desc("Command line options");
    desc.add_options()
        ("help", "help message")
        ("collectors", opt::value<std::vector<std::string> >()->multitoken(
            )->default_value(std::vector<std::string>(1, "127.0.0.1:8086"),
                             "127.0.0.1:8086"),
         "List of Collectors addresses in ip:port format")
        ("num_instances_per_generator", opt::value<int>()->default_value(10),
         "Number of instances (virtual machines) per generator")
        ("num_networks", opt::value<int>()->default_value(100),
         "Number of virtual networks")
        ("num_flows_per_instance", opt::value<int>()->default_value(10),
         "Number of flows per instance")
        ("start_ip_address",
         opt::value<std::string>()->default_value("1.0.0.1"),
         "Start IP address to be used for instances")
        ("http_server_port", opt::value<int>()->default_value(-1),
         "HTTP server port")
        ("generator_id", opt::value<int>()->default_value(0),
         "Generator Id")
        ("num_generators", opt::value<int>()->default_value(1),
         "Number of generators");

    opt::variables_map var_map;
    opt::store(opt::parse_command_line(argc, argv, desc), var_map);
    opt::notify(var_map);

    if (var_map.count("help")) {
        std::cout << desc << std::endl;
        exit(0);
    }

    LoggingInit();

    int gen_id(var_map["generator_id"].as<int>());
    int ngens(var_map["num_generators"].as<int>());
    int pid(getpid());
    int num_instances(var_map["num_instances_per_generator"].as<int>());
    int num_networks(var_map["num_networks"].as<int>());
    Module::type module(Module::VROUTER_AGENT);
    std::string moduleid(g_vns_constants.ModuleNames.find(module)->second);
    NodeType::type node_type(
        g_vns_constants.Module2NodeType.find(module)->second);
    std::string node_type_name(
        g_vns_constants.NodeTypeNames.find(node_type)->second);
    int http_server_port(var_map["http_server_port"].as<int>());
    std::vector<std::string> collectors(
        var_map["collectors"].as<std::vector<std::string> >());

    boost::system::error_code ec;
    std::string hostname(boost::asio::ip::host_name(ec));
    if (ec) {
        LOG(ERROR, "Hostname FAILED: " << ec);
        exit(1);
    }
    hostname += "-" + integerToString(pid);
    int gen_factor = num_networks / num_instances;
    if (gen_factor == 0) {
        LOG(ERROR, "Number of virtual networks(" << num_networks << ") should "
            "be greater than number of instances per generator(" <<
            num_instances << ")");
        exit(1);
    }
    int start_vn((gen_id % gen_factor) * num_instances);
    int end_vn(((gen_id % gen_factor) + 1) * num_instances);
    int other_vn_adj(num_networks / 2);
    int other_vn;
    if (gen_id >= other_vn_adj) {
        other_vn = gen_id - other_vn_adj;
    } else {
        other_vn = gen_id + other_vn_adj;
    }
    int instance_iterations((num_instances + num_networks - 1) / num_networks);
    int num_ips_per_vn(((ngens * num_instances) + num_networks - 1) /
            num_networks);
    std::string start_ip(var_map["start_ip_address"].as<std::string>());
    boost::asio::ip::address_v4 start_ip_address(
        boost::asio::ip::address_v4::from_string(start_ip.c_str(), ec));
    if (ec) {
        LOG(ERROR, "IP Address (" << start_ip << ") FAILED: " << ec);
        exit(1);
    }
    std::vector<uint32_t> ip_vns;
    for (int num = 0; num < num_networks; num++) {
        ip_vns.push_back(start_ip_address.to_ulong() +
                         num_ips_per_vn * num);
    }
    int start_ip_index(gen_id * num_instances / num_networks);

    EventManager evm;
    int num_flows_per_instance(var_map["num_flows_per_instance"].as<int>());
    std::string instance_id(integerToString(gen_id));
    MockGenerator mock_generator(hostname, moduleid, node_type_name,
        instance_id, http_server_port, start_vn, end_vn, other_vn,
        num_networks, instance_iterations, collectors, ip_vns, start_ip_index,
        num_flows_per_instance, &evm);
    mock_generator.Run();
    evm.Run();
    return 0;
}
<commit_msg>Add num_flows_in_iteration parameter to mock_generator to control the speed of sending flow messages<commit_after>//
// Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
//

#include <sys/types.h>
#include <unistd.h>

#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/host_name.hpp>
#include <boost/program_options.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

#include <base/task.h>
#include <base/logging.h>
#include <sandesh/sandesh_types.h>
#include <sandesh/sandesh.h>
#include <sandesh/common/vns_constants.h>
#include <sandesh/common/vns_types.h>
#include <sandesh/common/flow_types.h>

namespace opt = boost::program_options;

class MockGenerator {
public:
    const static int kNumFlowsInIteration;

    MockGenerator(std::string &hostname, std::string &module_name,
                  std::string &node_type_name,
                  std::string &instance_id,
                  int http_server_port, int start_vn, int end_vn, int other_vn,
                  int num_vns, int vm_iterations,
                  std::vector<std::string> &collectors,
                  std::vector<uint32_t> &ip_vns,
                  int ip_start_index, int num_flows_per_vm,
                  int num_flows_in_iteration,
                  EventManager *evm) :
        hostname_(hostname),
        module_name_(module_name),
        node_type_name_(node_type_name),
        instance_id_(instance_id),
        http_server_port_(http_server_port),
        start_vn_(start_vn),
        end_vn_(end_vn),
        other_vn_(other_vn),
        num_vns_(num_vns),
        vm_iterations_(vm_iterations),
        collectors_(collectors),
        ip_vns_(ip_vns),
        ip_start_index_(ip_start_index),
        num_flows_per_vm_(num_flows_per_vm),
        num_flows_in_iteration_(num_flows_in_iteration),
        rgen_(std::time(0)),
        u_rgen_(&rgen_),
        evm_(evm) {
    }

    bool Run() {
        // Initialize Sandesh
        Sandesh::CollectorSubFn csf = 0;
        Sandesh::InitGenerator(module_name_, hostname_,
            node_type_name_, instance_id_, evm_, http_server_port_,
            csf, collectors_, NULL);
        // Enqueue send flow task
        TaskScheduler *scheduler = TaskScheduler::GetInstance();
        SendFlowTask *ftask(new SendFlowTask(this,
            scheduler->GetTaskId("mockgen::SendFlowTask"), -1));
        scheduler->Enqueue(ftask);
        return true;
    }

private:

    class SendFlowTask : public Task {
    public:
        SendFlowTask(MockGenerator *mock_generator,
            int task_id, int task_instance) :
            Task(task_id, task_instance),
            mgen_(mock_generator) {
        }

        bool Run() {
            // Populate flows if not done
            if (mgen_->flows_.empty()) {
                int other_vn = mgen_->other_vn_;
                for (int vn = mgen_->start_vn_; vn < mgen_->end_vn_; vn++) {
                    for (int nvm = 0; nvm < mgen_->vm_iterations_; nvm++) {
                        for (int nflow = 0; nflow < mgen_->num_flows_per_vm_;
                             nflow++) {
                            uint64_t init_packets(mgen_->dFlowPktsPerSec(
                                mgen_->rgen_));
                            uint64_t init_bytes(init_packets *
                                mgen_->dBytesPerPacket(mgen_->rgen_));
                            uint32_t sourceip(mgen_->ip_vns_[vn] +
                                mgen_->ip_start_index_ + nvm);
                            uint32_t destip(mgen_->ip_vns_[other_vn] +
                                mgen_->ip_start_index_ + nvm);
                            FlowDataIpv4 flow_data;
                            boost::uuids::uuid flowuuid(mgen_->u_rgen_());
                            flow_data.set_flowuuid(to_string(flowuuid));
                            flow_data.set_direction_ing(mgen_->dDirection(
                                mgen_->rgen_));
                            std::string sourcevn(mgen_->kVnPrefix +
                                integerToString(vn));
                            flow_data.set_sourcevn(sourcevn);
                            std::string destvn(mgen_->kVnPrefix +
                                integerToString(other_vn));
                            flow_data.set_destvn(destvn);
                            flow_data.set_sourceip(sourceip);
                            flow_data.set_destip(destip);
                            flow_data.set_sport(mgen_->dPort(mgen_->rgen_));
                            flow_data.set_dport(mgen_->dPort(mgen_->rgen_));
                            flow_data.set_protocol(mgen_->kProtocols[
                                mgen_->dProtocols(mgen_->rgen_)]);
                            flow_data.set_setup_time(UTCTimestampUsec());
                            flow_data.set_packets(init_packets);
                            flow_data.set_bytes(init_bytes);
                            flow_data.set_diff_packets(init_packets);
                            flow_data.set_diff_bytes(init_bytes);
                            mgen_->flows_.push_back(flow_data);
                        }
                    }
                    other_vn = (other_vn + 1) % mgen_->num_vns_;
                }
            }
            // Send the flows periodically
            int lflow_cnt = 0;
            for (std::vector<FlowDataIpv4>::iterator it = mgen_->flows_.begin() +
                 mgen_->flow_counter_; it != mgen_->flows_.end(); ++it) {
                FlowDataIpv4 &flow_data(*it);
                uint64_t new_packets(mgen_->dFlowPktsPerSec(mgen_->rgen_));
                uint64_t new_bytes(new_packets *
                    mgen_->dBytesPerPacket(mgen_->rgen_));
                uint64_t old_packets(flow_data.get_packets());
                uint64_t old_bytes(flow_data.get_bytes());
                flow_data.set_packets(old_packets + new_packets);
                flow_data.set_bytes(old_bytes + new_bytes);
                flow_data.set_diff_packets(new_packets);
                flow_data.set_diff_bytes(new_bytes);
                FLOW_DATA_IPV4_OBJECT_SEND(flow_data);
                lflow_cnt++;
                mgen_->flow_counter_++;
                if (lflow_cnt == mgen_->num_flows_in_iteration_) {
                    return false;
                }
            }
            // Completed iteration, reset flow counter
            mgen_->flow_counter_ = 0;
            return false;
        }

    private:
        MockGenerator *mgen_;
    };

    const static std::string kVnPrefix;
    const static std::string kVmPrefix;
    const static int kBytesPerPacket = 1024;
    const static int kOtherVnPktsPerSec = 1000;
    const static int kUveMsgIntvlInSec = 10;
    const static int kFlowMsgIntvlInSec = 1;
    const static int kFlowPktsPerSec = 100;

    const static boost::random::uniform_int_distribution<>
        dBytesPerPacket;
    const static boost::random::uniform_int_distribution<>
        dOtherVnPktsPerSec;
    const static boost::random::uniform_int_distribution<>
        dFlowPktsPerSec;
    const static boost::random::uniform_int_distribution<>
        dDirection;
    const static boost::random::uniform_int_distribution<>
        dPort;
    const static std::vector<int> kProtocols;
    const static boost::random::uniform_int_distribution<>
        dProtocols;

    const std::string hostname_;
    const std::string module_name_;
    const std::string node_type_name_;
    const std::string instance_id_;
    const int http_server_port_;
    const int start_vn_;
    const int end_vn_;
    const int other_vn_;
    const int num_vns_;
    const int vm_iterations_;
    const std::vector<std::string> collectors_;
    const std::vector<uint32_t> ip_vns_;
    const int ip_start_index_;
    const int num_flows_per_vm_;
    const int num_flows_in_iteration_;
    std::vector<FlowDataIpv4> flows_;
    static int flow_counter_;
    boost::random::mt19937 rgen_;
    boost::uuids::random_generator u_rgen_;
    EventManager *evm_;

    friend class SendFlowTask;
};

const std::string MockGenerator::kVnPrefix("default-domain:mock-gen-test:vn");
const std::string MockGenerator::kVmPrefix("vm");
const boost::random::uniform_int_distribution<>
    MockGenerator::dBytesPerPacket(1, MockGenerator::kBytesPerPacket);
const boost::random::uniform_int_distribution<>
    MockGenerator::dOtherVnPktsPerSec(1, MockGenerator::kOtherVnPktsPerSec);
const boost::random::uniform_int_distribution<>
    MockGenerator::dFlowPktsPerSec(1, MockGenerator::kFlowPktsPerSec);
const boost::random::uniform_int_distribution<>
    MockGenerator::dDirection(0, 1);
const boost::random::uniform_int_distribution<>
    MockGenerator::dPort(0, 65535);
const std::vector<int> MockGenerator::kProtocols = boost::assign::list_of
    (6)(17)(1);
const boost::random::uniform_int_distribution<>
    MockGenerator::dProtocols(0, MockGenerator::kProtocols.size() - 1);
int MockGenerator::flow_counter_(0);
const int MockGenerator::kNumFlowsInIteration(145 * 10);

int main(int argc, char *argv[]) {
    opt::options_description desc("Command line options");
    desc.add_options()
        ("help", "help message")
        ("collectors", opt::value<std::vector<std::string> >()->multitoken(
            )->default_value(std::vector<std::string>(1, "127.0.0.1:8086"),
                             "127.0.0.1:8086"),
         "List of Collectors addresses in ip:port format")
        ("num_instances_per_generator", opt::value<int>()->default_value(10),
         "Number of instances (virtual machines) per generator")
        ("num_networks", opt::value<int>()->default_value(100),
         "Number of virtual networks")
        ("num_flows_per_instance", opt::value<int>()->default_value(10),
         "Number of flows per instance")
        ("start_ip_address",
         opt::value<std::string>()->default_value("1.0.0.1"),
         "Start IP address to be used for instances")
        ("http_server_port", opt::value<int>()->default_value(-1),
         "HTTP server port")
        ("generator_id", opt::value<int>()->default_value(0),
         "Generator Id")
        ("num_generators", opt::value<int>()->default_value(1),
         "Number of generators")
        ("num_flows_in_iteration", opt::value<int>()->default_value(
             MockGenerator::kNumFlowsInIteration),
         "Number of flow messages to send in one iteration");

    opt::variables_map var_map;
    opt::store(opt::parse_command_line(argc, argv, desc), var_map);
    opt::notify(var_map);

    if (var_map.count("help")) {
        std::cout << desc << std::endl;
        exit(0);
    }

    LoggingInit();

    int gen_id(var_map["generator_id"].as<int>());
    int ngens(var_map["num_generators"].as<int>());
    int pid(getpid());
    int num_instances(var_map["num_instances_per_generator"].as<int>());
    int num_networks(var_map["num_networks"].as<int>());
    Module::type module(Module::VROUTER_AGENT);
    std::string moduleid(g_vns_constants.ModuleNames.find(module)->second);
    NodeType::type node_type(
        g_vns_constants.Module2NodeType.find(module)->second);
    std::string node_type_name(
        g_vns_constants.NodeTypeNames.find(node_type)->second);
    int http_server_port(var_map["http_server_port"].as<int>());
    std::vector<std::string> collectors(
        var_map["collectors"].as<std::vector<std::string> >());

    boost::system::error_code ec;
    std::string hostname(boost::asio::ip::host_name(ec));
    if (ec) {
        LOG(ERROR, "Hostname FAILED: " << ec);
        exit(1);
    }
    hostname += "-" + integerToString(pid);
    int gen_factor = num_networks / num_instances;
    if (gen_factor == 0) {
        LOG(ERROR, "Number of virtual networks(" << num_networks << ") should "
            "be greater than number of instances per generator(" <<
            num_instances << ")");
        exit(1);
    }
    int start_vn((gen_id % gen_factor) * num_instances);
    int end_vn(((gen_id % gen_factor) + 1) * num_instances);
    int other_vn_adj(num_networks / 2);
    int other_vn;
    if (gen_id >= other_vn_adj) {
        other_vn = gen_id - other_vn_adj;
    } else {
        other_vn = gen_id + other_vn_adj;
    }
    int instance_iterations((num_instances + num_networks - 1) / num_networks);
    int num_ips_per_vn(((ngens * num_instances) + num_networks - 1) /
            num_networks);
    std::string start_ip(var_map["start_ip_address"].as<std::string>());
    boost::asio::ip::address_v4 start_ip_address(
        boost::asio::ip::address_v4::from_string(start_ip.c_str(), ec));
    if (ec) {
        LOG(ERROR, "IP Address (" << start_ip << ") FAILED: " << ec);
        exit(1);
    }
    std::vector<uint32_t> ip_vns;
    for (int num = 0; num < num_networks; num++) {
        ip_vns.push_back(start_ip_address.to_ulong() +
                         num_ips_per_vn * num);
    }
    int start_ip_index(gen_id * num_instances / num_networks);

    EventManager evm;
    int num_flows_per_instance(var_map["num_flows_per_instance"].as<int>());
    int num_flows_in_iteration(var_map["num_flows_in_iteration"].as<int>());
    std::string instance_id(integerToString(gen_id));
    MockGenerator mock_generator(hostname, moduleid, node_type_name,
        instance_id, http_server_port, start_vn, end_vn, other_vn,
        num_networks, instance_iterations, collectors, ip_vns, start_ip_index,
        num_flows_per_instance, num_flows_in_iteration, &evm);
    mock_generator.Run();
    evm.Run();
    return 0;
}
<|endoftext|>


<commit_before>#include "common/libicu.h"

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <vector>
#include <iostream>
#include <memory>

#include "zorbatypes/collation_manager.h"

namespace zorba {

  XQPCollator::XQPCollator(Collator* aCollator)
    : theCollator(aCollator) {}

  XQPCollator::~XQPCollator()
  {
    delete theCollator;
  }

  XQPCollator*
  CollationFactory::createCollator(const std::string& aCollationURI)
  {
    if (aCollationURI == "http://www.w3.org/2005/xpath-functions/collation/codepoint")
    {
      Collator* lCollator;
      UErrorCode lError = U_ZERO_ERROR;
      lCollator = Collator::createInstance(Locale("root"), lError);
      assert(lError == U_ZERO_ERROR);
      lCollator->setStrength(Collator::PRIMARY);
      return new XQPCollator(lCollator);
    }

    size_t lStartURI = aCollationURI.find("http://www.flworfound.org/collations/");
    if ( lStartURI == std::string::npos )
      return 0;

    // e.g. PRIMARY/en/US
    std::string lCollationIdentifier = aCollationURI.substr(37, aCollationURI.size() - 37);

    // the vector will contain the strength, language, and optional country code
    std::vector<std::string> lSplitVec;;
    boost::split( lSplitVec, lCollationIdentifier, boost::algorithm::is_any_of("/") );

    if ( lSplitVec.size() < 2 )
      return 0;

    Collator* lCollator;
    UErrorCode lError = U_ZERO_ERROR;
    if ( lSplitVec.size() == 2 ) {
      lCollator = Collator::createInstance(Locale(lSplitVec[1].c_str()), lError);
    } else {
      lCollator = Collator::createInstance(Locale(lSplitVec[1].c_str(), lSplitVec[2].c_str()), lError);
    }

    if( U_FAILURE(lError) ) {
      return 0;
    }

    if (lSplitVec[0].compare("PRIMARY") == 0) {
      lCollator->setStrength(Collator::PRIMARY);
    } else if (lSplitVec[0].compare("SECONDARY") == 0) {
      lCollator->setStrength(Collator::SECONDARY);
    } else if (lSplitVec[0].compare("TERTIARY") == 0) {
      lCollator->setStrength(Collator::TERTIARY);
    } else if (lSplitVec[0].compare("QUATERNARY") == 0) {
      lCollator->setStrength(Collator::QUATERNARY);
    } else if (lSplitVec[0].compare("IDENTICAL") == 0) {
      lCollator->setStrength(Collator::IDENTICAL);
    } else {
      return 0;
    }

    return new XQPCollator(lCollator);
  }

  XQPCollator*
  CollationFactory::createCollator()
  {
    UErrorCode lError = U_ZERO_ERROR;
    Collator* lCollator = Collator::createInstance(Locale("en", "US"), lError);
    if( U_FAILURE(lError) ) {
      assert(false);
    }
    lCollator->setStrength(Collator::IDENTICAL);

    return new XQPCollator(lCollator);
  }

  CollationFactory::CollationFactory()
    : theRootCollator(0)
  {
    theRootCollator = createCollator();
  }

  CollationFactory::~CollationFactory()
  {
    if ( theRootCollator )
      delete theRootCollator;
  }

} /* namespace xqp */
<commit_msg>identical comparison for the default collation<commit_after>#include "common/libicu.h"

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <vector>
#include <iostream>
#include <memory>

#include "zorbatypes/collation_manager.h"

namespace zorba {

  XQPCollator::XQPCollator(Collator* aCollator)
    : theCollator(aCollator) {}

  XQPCollator::~XQPCollator()
  {
    delete theCollator;
  }

  XQPCollator*
  CollationFactory::createCollator(const std::string& aCollationURI)
  {
    if (aCollationURI == "http://www.w3.org/2005/xpath-functions/collation/codepoint")
    {
      Collator* lCollator;
      UErrorCode lError = U_ZERO_ERROR;
      lCollator = Collator::createInstance(Locale("root"), lError);
      assert(lError == U_ZERO_ERROR);
      lCollator->setStrength(Collator::IDENTICAL);
      return new XQPCollator(lCollator);
    }

    size_t lStartURI = aCollationURI.find("http://www.flworfound.org/collations/");
    if ( lStartURI == std::string::npos )
      return 0;

    // e.g. PRIMARY/en/US
    std::string lCollationIdentifier = aCollationURI.substr(37, aCollationURI.size() - 37);

    // the vector will contain the strength, language, and optional country code
    std::vector<std::string> lSplitVec;;
    boost::split( lSplitVec, lCollationIdentifier, boost::algorithm::is_any_of("/") );

    if ( lSplitVec.size() < 2 )
      return 0;

    Collator* lCollator;
    UErrorCode lError = U_ZERO_ERROR;
    if ( lSplitVec.size() == 2 ) {
      lCollator = Collator::createInstance(Locale(lSplitVec[1].c_str()), lError);
    } else {
      lCollator = Collator::createInstance(Locale(lSplitVec[1].c_str(), lSplitVec[2].c_str()), lError);
    }

    if( U_FAILURE(lError) ) {
      return 0;
    }

    if (lSplitVec[0].compare("PRIMARY") == 0) {
      lCollator->setStrength(Collator::PRIMARY);
    } else if (lSplitVec[0].compare("SECONDARY") == 0) {
      lCollator->setStrength(Collator::SECONDARY);
    } else if (lSplitVec[0].compare("TERTIARY") == 0) {
      lCollator->setStrength(Collator::TERTIARY);
    } else if (lSplitVec[0].compare("QUATERNARY") == 0) {
      lCollator->setStrength(Collator::QUATERNARY);
    } else if (lSplitVec[0].compare("IDENTICAL") == 0) {
      lCollator->setStrength(Collator::IDENTICAL);
    } else {
      return 0;
    }

    return new XQPCollator(lCollator);
  }

  XQPCollator*
  CollationFactory::createCollator()
  {
    UErrorCode lError = U_ZERO_ERROR;
    Collator* lCollator = Collator::createInstance(Locale("en", "US"), lError);
    if( U_FAILURE(lError) ) {
      assert(false);
    }
    lCollator->setStrength(Collator::IDENTICAL);

    return new XQPCollator(lCollator);
  }

  CollationFactory::CollationFactory()
    : theRootCollator(0)
  {
    theRootCollator = createCollator();
  }

  CollationFactory::~CollationFactory()
  {
    if ( theRootCollator )
      delete theRootCollator;
  }

} /* namespace xqp */
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_PROB_UNIFORM_LCDF_HPP
#define STAN_MATH_PRIM_PROB_UNIFORM_LCDF_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/max_size.hpp>
#include <stan/math/prim/fun/promote_scalar.hpp>
#include <stan/math/prim/fun/size_zero.hpp>
#include <stan/math/prim/fun/to_ref.hpp>
#include <stan/math/prim/fun/value_of.hpp>
#include <stan/math/prim/functor/operands_and_partials.hpp>
#include <cmath>

namespace stan {
namespace math {

template <typename T_y, typename T_low, typename T_high>
return_type_t<T_y, T_low, T_high> uniform_lcdf(const T_y& y, const T_low& alpha,
                                               const T_high& beta) {
  using T_partials_return = partials_return_t<T_y, T_low, T_high>;
  using T_y_ref = ref_type_if_t<!is_constant<T_y>::value, T_y>;
  using T_alpha_ref = ref_type_if_t<!is_constant<T_low>::value, T_low>;
  using T_beta_ref = ref_type_if_t<!is_constant<T_high>::value, T_high>;
  static const char* function = "uniform_lcdf";
  check_consistent_sizes(function, "Random variable", y,
                         "Lower bound parameter", alpha,
                         "Upper bound parameter", beta);
  T_y_ref y_ref = y;
  T_alpha_ref alpha_ref = alpha;
  T_beta_ref beta_ref = beta;

  const auto& y_col = as_column_vector_or_scalar(y_ref);
  const auto& alpha_col = as_column_vector_or_scalar(alpha_ref);
  const auto& beta_col = as_column_vector_or_scalar(beta_ref);

  const auto& y_arr = as_array_or_scalar(y_col);
  const auto& alpha_arr = as_array_or_scalar(alpha_col);
  const auto& beta_arr = as_array_or_scalar(beta_col);

  ref_type_t<decltype(value_of(y_arr))> y_val = value_of(y_arr);
  ref_type_t<decltype(value_of(alpha_arr))> alpha_val = value_of(alpha_arr);
  ref_type_t<decltype(value_of(beta_arr))> beta_val = value_of(beta_arr);

  check_not_nan(function, "Random variable", y_val);
  check_finite(function, "Lower bound parameter", alpha_val);
  check_finite(function, "Upper bound parameter", beta_val);
  check_greater(function, "Upper bound parameter", beta_val, alpha_val);

  if (size_zero(y, alpha, beta)) {
    return 0;
  }

  if (sum(promote_scalar<int>(y_val < alpha_val))
      || sum(promote_scalar<int>(beta_val < y_val))) {
    return negative_infinity();
  }

  operands_and_partials<T_y_ref, T_alpha_ref, T_beta_ref> ops_partials(
      y_ref, alpha_ref, beta_ref);

  const auto& b_minus_a
      = to_ref_if<!is_constant_all<T_y, T_low, T_high>::value>(beta_val
                                                               - alpha_val);
  const auto& y_minus_alpha
      = to_ref_if<!is_constant_all<T_y, T_low>::value>(y_val - alpha_val);
  const auto& cdf_log_n = y_minus_alpha / b_minus_a;
  T_partials_return cdf_log = sum(log(cdf_log_n));

  if (!is_constant_all<T_y>::value) {
    if(!is_vector<T_y>::value &&
           is_vector<T_high>::value &&
           !is_vector<T_low>::value) {
      ops_partials.edge1_.partials_ = size(beta) * inv(y_minus_alpha);
    } else {
      ops_partials.edge1_.partials_ = inv(y_minus_alpha);
    }
  }
  if (!is_constant_all<T_low>::value) {
    ops_partials.edge2_.partials_
        = (y_val - beta_val) / (b_minus_a * y_minus_alpha);
  }
  if (!is_constant_all<T_high>::value) {
    if (is_vector<T_y>::value && !is_vector<T_low>::value
        && !is_vector<T_high>::value) {
      ops_partials.edge3_.partials_
          = inv(-b_minus_a) * size(y);
    } else {
      ops_partials.edge3_.partials_ = inv(-b_minus_a);
    }
  }
  return ops_partials.build(cdf_log);
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef STAN_MATH_PRIM_PROB_UNIFORM_LCDF_HPP
#define STAN_MATH_PRIM_PROB_UNIFORM_LCDF_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/constants.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/max_size.hpp>
#include <stan/math/prim/fun/promote_scalar.hpp>
#include <stan/math/prim/fun/size_zero.hpp>
#include <stan/math/prim/fun/to_ref.hpp>
#include <stan/math/prim/fun/value_of.hpp>
#include <stan/math/prim/functor/operands_and_partials.hpp>
#include <cmath>

namespace stan {
namespace math {

template <typename T_y, typename T_low, typename T_high>
return_type_t<T_y, T_low, T_high> uniform_lcdf(const T_y& y, const T_low& alpha,
                                               const T_high& beta) {
  using T_partials_return = partials_return_t<T_y, T_low, T_high>;
  using T_y_ref = ref_type_if_t<!is_constant<T_y>::value, T_y>;
  using T_alpha_ref = ref_type_if_t<!is_constant<T_low>::value, T_low>;
  using T_beta_ref = ref_type_if_t<!is_constant<T_high>::value, T_high>;
  static const char* function = "uniform_lcdf";
  check_consistent_sizes(function, "Random variable", y,
                         "Lower bound parameter", alpha,
                         "Upper bound parameter", beta);
  T_y_ref y_ref = y;
  T_alpha_ref alpha_ref = alpha;
  T_beta_ref beta_ref = beta;

  const auto& y_col = as_column_vector_or_scalar(y_ref);
  const auto& alpha_col = as_column_vector_or_scalar(alpha_ref);
  const auto& beta_col = as_column_vector_or_scalar(beta_ref);

  const auto& y_arr = as_array_or_scalar(y_col);
  const auto& alpha_arr = as_array_or_scalar(alpha_col);
  const auto& beta_arr = as_array_or_scalar(beta_col);

  ref_type_t<decltype(value_of(y_arr))> y_val = value_of(y_arr);
  ref_type_t<decltype(value_of(alpha_arr))> alpha_val = value_of(alpha_arr);
  ref_type_t<decltype(value_of(beta_arr))> beta_val = value_of(beta_arr);

  check_not_nan(function, "Random variable", y_val);
  check_finite(function, "Lower bound parameter", alpha_val);
  check_finite(function, "Upper bound parameter", beta_val);
  check_greater(function, "Upper bound parameter", beta_val, alpha_val);

  if (size_zero(y, alpha, beta)) {
    return 0;
  }

  if (sum(promote_scalar<int>(y_val < alpha_val))
      || sum(promote_scalar<int>(beta_val < y_val))) {
    return negative_infinity();
  }

  operands_and_partials<T_y_ref, T_alpha_ref, T_beta_ref> ops_partials(
      y_ref, alpha_ref, beta_ref);

  const auto& b_minus_a
      = to_ref_if<!is_constant_all<T_y, T_low, T_high>::value>(beta_val
                                                               - alpha_val);
  const auto& y_minus_alpha
      = to_ref_if<!is_constant_all<T_y, T_low>::value>(y_val - alpha_val);
  const auto& cdf_log_n = y_minus_alpha / b_minus_a;
  T_partials_return cdf_log = sum(log(cdf_log_n));

  if (!is_constant_all<T_y>::value) {
    if (!is_vector<T_y>::value && is_vector<T_high>::value
        && !is_vector<T_low>::value) {
      ops_partials.edge1_.partials_ = size(beta) * inv(y_minus_alpha);
    } else {
      ops_partials.edge1_.partials_ = inv(y_minus_alpha);
    }
  }
  if (!is_constant_all<T_low>::value) {
    ops_partials.edge2_.partials_
        = (y_val - beta_val) / (b_minus_a * y_minus_alpha);
  }
  if (!is_constant_all<T_high>::value) {
    if (is_vector<T_y>::value && !is_vector<T_low>::value
        && !is_vector<T_high>::value) {
      ops_partials.edge3_.partials_ = inv(-b_minus_a) * size(y);
    } else {
      ops_partials.edge3_.partials_ = inv(-b_minus_a);
    }
  }
  return ops_partials.build(cdf_log);
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>