|
|
@@ -12,6 +12,8 @@ extern "C" {
|
|
|
#include <netinet/in.h>
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
+#include <sys/time.h>
|
|
|
+
|
|
|
#include <fstream>
|
|
|
#include <vector>
|
|
|
#include <set>
|
|
|
@@ -42,6 +44,17 @@ void besetdump(const BESet &bes, ostream &os)
|
|
|
os << dec << "\n";
|
|
|
}
|
|
|
|
|
|
+void besetfree(BESet &bes)
|
|
|
+{
|
|
|
+ BESet::iterator besit;
|
|
|
+
|
|
|
+ for (besit = bes.begin(); besit != bes.end(); ++besit) {
|
|
|
+ bufferevent_free(*besit);
|
|
|
+ }
|
|
|
+
|
|
|
+ bes.clear();
|
|
|
+}
|
|
|
+
|
|
|
void bemapdump(const BEMap &bem, ostream &os)
|
|
|
{
|
|
|
BEMap::const_iterator bemit;
|
|
|
@@ -53,6 +66,17 @@ void bemapdump(const BEMap &bem, ostream &os)
|
|
|
os << dec << "\n";
|
|
|
}
|
|
|
|
|
|
+void bemapfree(BEMap &bem)
|
|
|
+{
|
|
|
+ BEMap::iterator bemit;
|
|
|
+
|
|
|
+ for (bemit = bem.begin(); bemit != bem.end(); ++bemit) {
|
|
|
+ bufferevent_free(bemit->first);
|
|
|
+ }
|
|
|
+
|
|
|
+ bem.clear();
|
|
|
+}
|
|
|
+
|
|
|
struct Statuses {
|
|
|
BESet idle;
|
|
|
BEMap working;
|
|
|
@@ -64,6 +88,11 @@ struct Statuses {
|
|
|
os << " working (" << working.size() << "):\n";
|
|
|
bemapdump(working, os);
|
|
|
}
|
|
|
+
|
|
|
+ void free(void) {
|
|
|
+ besetfree(idle);
|
|
|
+ bemapfree(working);
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
struct FactorDecomp {
|
|
|
@@ -78,11 +107,15 @@ static struct ControllerState {
|
|
|
FactorDecomp p, q;
|
|
|
ZZ base, target;
|
|
|
bool working;
|
|
|
+ struct timeval started_working;
|
|
|
vector<SubproblemProgress> subproblems_p, subproblems_q;
|
|
|
Statuses dpnodes, workers;
|
|
|
unsigned int num_unsolved_subproblems;
|
|
|
+ unsigned int problems_remaining;
|
|
|
+ struct evconnlistener *listener;
|
|
|
|
|
|
- ControllerState() : working(false), num_unsolved_subproblems(0) {}
|
|
|
+ ControllerState() : working(false), num_unsolved_subproblems(0),
|
|
|
+ problems_remaining(0), listener(NULL) {}
|
|
|
|
|
|
// Reset the state for a new problem with the same modulus
|
|
|
void reset(void) {
|
|
|
@@ -92,6 +125,8 @@ static struct ControllerState {
|
|
|
subproblems_p.clear();
|
|
|
subproblems_q.clear();
|
|
|
num_unsolved_subproblems = 0;
|
|
|
+ started_working.tv_sec = 0;
|
|
|
+ started_working.tv_usec = 0;
|
|
|
}
|
|
|
|
|
|
// Dump the state for debug purposes
|
|
|
@@ -214,7 +249,7 @@ struct SubproblemProgress : Subproblem {
|
|
|
bufferevent_write(bev, ipports[i].ipport, 6);
|
|
|
}
|
|
|
#ifdef DEBUG
|
|
|
- cerr << "Added worker " << bev << "to subproblem "
|
|
|
+ cerr << "Added worker " << bev << " to subproblem "
|
|
|
<< problemid << "\n";
|
|
|
#endif
|
|
|
}
|
|
|
@@ -358,12 +393,22 @@ static void computation_complete(void)
|
|
|
}
|
|
|
ZZ& expon = exp_p;
|
|
|
|
|
|
+ struct timeval ended_working;
|
|
|
+ gettimeofday(&ended_working, NULL);
|
|
|
+ unsigned long long computation_length_ms =
|
|
|
+ (ended_working.tv_sec - ctrlstate.started_working.tv_sec) * 1000 +
|
|
|
+ (ended_working.tv_usec - ctrlstate.started_working.tv_usec) / 1000;
|
|
|
+ char length_buf[50];
|
|
|
+ sprintf(length_buf, "%lld.%03lld s", computation_length_ms / 1000,
|
|
|
+ computation_length_ms % 1000);
|
|
|
+
|
|
|
cout << "expon = " << expon << "\n";
|
|
|
ZZ base_exp = PowerMod(ctrlstate.base, expon, ctrlstate.rho);
|
|
|
if (base_exp == ctrlstate.target) {
|
|
|
- cout << "CORRECT!\n";
|
|
|
+ cout << "CORRECT in " << length_buf << "\n";
|
|
|
} else {
|
|
|
- cout << "INCORRECT:\nbase^exp = " << base_exp << "\n";
|
|
|
+ cout << "INCORRECT in " << length_buf << ":\n";
|
|
|
+ cout << "base^exp = " << base_exp << "\n";
|
|
|
cout << "target = " << ctrlstate.target << "\n";
|
|
|
}
|
|
|
|
|
|
@@ -429,6 +474,14 @@ static vector<SubproblemProgress> decomp(const ZZ_p &base, const ZZ_p &target,
|
|
|
|
|
|
static int generate_problem(struct event_base *evbase)
|
|
|
{
|
|
|
+ // If there are no more problems to generate, close the listener
|
|
|
+ if (ctrlstate.problems_remaining == 0) {
|
|
|
+ evconnlistener_free(ctrlstate.listener);
|
|
|
+ ctrlstate.dpnodes.free();
|
|
|
+ ctrlstate.workers.free();
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
// If there's already a problem on the go, don't generate another one
|
|
|
if (ctrlstate.working == true) {
|
|
|
return -1;
|
|
|
@@ -443,6 +496,7 @@ static int generate_problem(struct event_base *evbase)
|
|
|
do {
|
|
|
ZZ_p base = power(random_ZZ_p(), 2);
|
|
|
ZZ_p target = power(random_ZZ_p(), 2);
|
|
|
+ gettimeofday(&ctrlstate.started_working, NULL);
|
|
|
ctrlstate.base = rep(base);
|
|
|
ctrlstate.target = rep(target);
|
|
|
|
|
|
@@ -458,6 +512,8 @@ static int generate_problem(struct event_base *evbase)
|
|
|
|
|
|
schedule();
|
|
|
|
|
|
+ --ctrlstate.problems_remaining;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -552,7 +608,6 @@ static void controller_dpnode_reader(struct bufferevent *bev, void *ctx)
|
|
|
if (ctrlstate.num_unsolved_subproblems == 0) {
|
|
|
computation_complete();
|
|
|
generate_problem(bufferevent_get_base(bev));
|
|
|
- ctrlstate.dump(cerr);
|
|
|
}
|
|
|
schedule();
|
|
|
}
|
|
|
@@ -683,8 +738,8 @@ static void controller_accept_cb(struct evconnlistener *listener,
|
|
|
// Create a new controller socket. bindport is the port to bind to (in
|
|
|
// host byte order), or 0 if any port will do. ip and boundport are set
|
|
|
// to the IP and port of the socket, in network byte order.
|
|
|
-void *controller_create(struct event_base *evbase, unsigned short bindport,
|
|
|
- unsigned int *ip, unsigned short *boundport)
|
|
|
+struct evconnlistener *controller_create(struct event_base *evbase,
|
|
|
+ unsigned short bindport, unsigned int *ip, unsigned short *boundport)
|
|
|
{
|
|
|
return listener_create(evbase, bindport, controller_accept_cb, NULL,
|
|
|
ip, boundport, false);
|
|
|
@@ -715,10 +770,12 @@ int main(int argc, char **argv)
|
|
|
unsigned int myip;
|
|
|
unsigned short myport;
|
|
|
|
|
|
- controller_create(evbase, bindport, &myip, &myport);
|
|
|
+ ctrlstate.listener = controller_create(evbase, bindport, &myip, &myport);
|
|
|
struct in_addr myaddr = { myip };
|
|
|
printf("Bound to %s:%d\n", inet_ntoa(myaddr), ntohs(myport));
|
|
|
|
|
|
+ ctrlstate.problems_remaining = 2;
|
|
|
+
|
|
|
// Kick off the first problem to solve
|
|
|
generate_problem(evbase);
|
|
|
|