upgrade to new schema: flights() payloads()

pull/1/merge
Daniel Richman 2012-08-12 14:57:39 +01:00
rodzic 7752c8341f
commit 336171deea
8 zmienionych plików z 171 dodań i 34 usunięć

Wyświetl plik

@ -1,6 +0,0 @@
/* Copyright 2011 (C) Daniel Richman; GNU GPL 3 */
function (doc) {
if (doc.type == "flight")
emit(doc.end, null);
}

Wyświetl plik

@ -192,7 +192,11 @@ Json::Value *Database::view(const string &design_doc, const string &view_name,
string Database::json_query_value(Json::Value &value) string Database::json_query_value(Json::Value &value)
{ {
Json::FastWriter writer; Json::FastWriter writer;
return writer.write(value); string str = writer.write(value);
int final = str.length() - 1;
if (final >= 0 && str[final] == '\n')
str.erase(final);
return str;
} }
} /* namespace CouchDB */ } /* namespace CouchDB */

Wyświetl plik

@ -246,13 +246,59 @@ string Uploader::listener_info(const Json::Value &data, int time_created)
vector<Json::Value> *Uploader::flights() vector<Json::Value> *Uploader::flights()
{ {
map<string,string> options; map<string,string> options;
ostringstream timefmt;
timefmt << time(NULL); Json::Value startkey(Json::arrayValue);
startkey.append((unsigned int) time(NULL));
options["include_docs"] = "true"; options["include_docs"] = "true";
options["startkey"] = timefmt.str(); options["startkey"] = CouchDB::Database::json_query_value(startkey);
Json::Value *response = database.view("uploader_v1", "flights", options); Json::Value *response =
database.view("flight", "end_start_including_payloads", options);
auto_ptr<Json::Value> response_destroyer(response);
vector<Json::Value> *result = new vector<Json::Value>;
auto_ptr< vector<Json::Value> > result_destroyer(result);
const Json::Value &rows = (*response)["rows"];
Json::Value::const_iterator it;
result->reserve(rows.size());
Json::Value *current_pcfg_list = NULL;
for (it = rows.begin(); it != rows.end(); it++)
{
const Json::Value &row = *it;
const Json::Value &key = row["key"], &doc = row["doc"];
bool is_pcfg = (key[2u].asInt() == 1);
if (!is_pcfg)
{
result->push_back(doc);
/* copies the doc */
Json::Value &doc_copy = result->back();
doc_copy["_payload_docs"] = Json::Value(Json::arrayValue);
current_pcfg_list = &(doc_copy["_payload_docs"]);
}
else
{
current_pcfg_list->append(doc);
}
}
result_destroyer.release();
return result;
}
vector<Json::Value> *Uploader::payloads()
{
map<string,string> options;
options["include_docs"] = "true";
Json::Value *response =
database.view("payload_configuration", "name_time_created", options);
auto_ptr<Json::Value> response_destroyer(response); auto_ptr<Json::Value> response_destroyer(response);
vector<Json::Value> *result = new vector<Json::Value>; vector<Json::Value> *result = new vector<Json::Value>;
@ -269,7 +315,6 @@ vector<Json::Value> *Uploader::flights()
} }
result_destroyer.release(); result_destroyer.release();
return result; return result;
} }

Wyświetl plik

@ -54,6 +54,7 @@ public:
string listener_telemetry(const Json::Value &data, int time_created=-1); string listener_telemetry(const Json::Value &data, int time_created=-1);
string listener_info(const Json::Value &data, int time_created=-1); string listener_info(const Json::Value &data, int time_created=-1);
vector<Json::Value> *flights(); vector<Json::Value> *flights();
vector<Json::Value> *payloads();
}; };
} /* namespace habitat */ } /* namespace habitat */

Wyświetl plik

@ -108,6 +108,19 @@ string UploaderFlights::describe()
return "Uploader.flights()"; return "Uploader.flights()";
} }
void UploaderPayloads::apply(UploaderThread &uthr)
{
check(uthr.uploader.get());
auto_ptr< vector<Json::Value> > payloads;
payloads.reset(uthr.uploader->payloads());
uthr.got_payloads(*payloads);
}
string UploaderPayloads::describe()
{
return "Uploader.payloads()";
}
void UploaderShutdown::apply(UploaderThread &uthr) void UploaderShutdown::apply(UploaderThread &uthr)
{ {
throw this; throw this;
@ -176,6 +189,11 @@ void UploaderThread::flights()
queue_action(new UploaderFlights()); queue_action(new UploaderFlights());
} }
void UploaderThread::payloads()
{
queue_action(new UploaderPayloads());
}
void UploaderThread::shutdown() void UploaderThread::shutdown()
{ {
/* Borrow the SimpleThread mutex to make queued_shutdown access safe */ /* Borrow the SimpleThread mutex to make queued_shutdown access safe */
@ -260,4 +278,9 @@ void UploaderThread::got_flights(const vector<Json::Value> &flights)
log("Default action: got_flights; discarding."); log("Default action: got_flights; discarding.");
} }
void UploaderThread::got_payloads(const vector<Json::Value> &payloads)
{
log("Default action: got_payloads; discarding.");
}
} /* namespace habitat */ } /* namespace habitat */

Wyświetl plik

@ -125,6 +125,15 @@ public:
string describe(); string describe();
}; };
class UploaderPayloads : public UploaderAction
{
void apply(UploaderThread &uthr);
friend class UploaderThread;
public:
string describe();
};
class UploaderShutdown : public UploaderAction class UploaderShutdown : public UploaderAction
{ {
void apply(UploaderThread &uthr); void apply(UploaderThread &uthr);
@ -150,6 +159,7 @@ class UploaderThread : public EZ::SimpleThread
friend class UploaderListenerTelemetry; friend class UploaderListenerTelemetry;
friend class UploaderListenerInfo; friend class UploaderListenerInfo;
friend class UploaderFlights; friend class UploaderFlights;
friend class UploaderPayloads;
public: public:
UploaderThread(); UploaderThread();
@ -166,6 +176,7 @@ public:
void listener_telemetry(const Json::Value &data, int time_created=-1); void listener_telemetry(const Json::Value &data, int time_created=-1);
void listener_info(const Json::Value &data, int time_created=-1); void listener_info(const Json::Value &data, int time_created=-1);
void flights(); void flights();
void payloads();
void shutdown(); void shutdown();
void *run(); void *run();
@ -179,6 +190,7 @@ public:
virtual void caught_exception(const runtime_error &error); virtual void caught_exception(const runtime_error &error);
virtual void caught_exception(const invalid_argument &error); virtual void caught_exception(const invalid_argument &error);
virtual void got_flights(const vector<Json::Value> &flights); virtual void got_flights(const vector<Json::Value> &flights);
virtual void got_payloads(const vector<Json::Value> &payloads);
}; };
} /* namespace habitat */ } /* namespace habitat */

Wyświetl plik

@ -12,11 +12,8 @@ import collections
import time import time
import uuid import uuid
import copy import copy
import random
try: import xml.etree.cElementTree as ET
import elementtree.ElementTree
except:
elementtree = None
class ProxyException: class ProxyException:
def __init__(self, name, what=None): def __init__(self, name, what=None):
@ -151,12 +148,9 @@ class Proxy:
self._check_valgrind() self._check_valgrind()
def _check_valgrind(self): def _check_valgrind(self):
if elementtree == None:
raise AssertionError("Need elementtree in order to check Valgrind")
if self.xmlfile: if self.xmlfile:
self.xmlfile.seek(0) self.xmlfile.seek(0)
tree = elementtree.ElementTree.parse(self.xmlfile) tree = ET.parse(self.xmlfile)
assert tree.find("error") == None assert tree.find("error") == None
def payload_telemetry(self, data, *args): def payload_telemetry(self, data, *args):
@ -171,10 +165,13 @@ class Proxy:
def flights(self): def flights(self):
return self._proxy(["flights"]) return self._proxy(["flights"])
def payloads(self):
return self._proxy(["payloads"])
def reset(self): def reset(self):
return self._proxy(["reset"]) return self._proxy(["reset"])
temp_port = 51205 temp_port = 55205
def next_temp_port(): def next_temp_port():
global temp_port global temp_port
@ -716,10 +713,30 @@ class TestCPPConnector:
raise AssertionError("Did not raise UnmergeableError") raise AssertionError("Did not raise UnmergeableError")
def test_flights(self): def test_flights(self):
flights= [{"_id": "flight_{0}".format(i), "a flight": i} rows = []
for i in xrange(100)] expect_result = []
rows = [{"id": doc["_id"], "key": None, "value": None, "doc": doc} pcfgs = []
for doc in flights]
for i in xrange(100):
pcfgs.append({"_id": "pcfg_{0}".format(i),
"type": "payload_configuration", "i": i})
for i in xrange(100):
payloads = random.sample(pcfgs, random.randint(1, 5))
doc = {"_id": "flight_{0}", "type": "flight", "i": i,
"payloads": [p["_id"] for p in payloads]}
start = self.callbacks.time_project(1000 + i)
end = self.callbacks.time_project(2000 + i)
rows.append({"id": doc["_id"], "key": [end, start, 0],
"value": None, "doc": doc})
for p in payloads:
rows.append({"id": doc["_id"], "key": [end, start, 1],
"value": {"_id": p["_id"]}, "doc": p})
doc = copy.deepcopy(doc)
doc["_payload_docs"] = payloads
expect_result.append(doc)
fake_view_response = \ fake_view_response = \
{"total_rows": len(rows), "offset": 0, "rows": rows} {"total_rows": len(rows), "offset": 0, "rows": rows}
@ -728,17 +745,39 @@ class TestCPPConnector:
self.callbacks.advance_time(1925) self.callbacks.advance_time(1925)
view_time = self.callbacks.time_project(1925) view_time = self.callbacks.time_project(1925)
options = "include%5Fdocs=true&startkey=" + str(view_time) view_path = "_design/flight/_view/end%5Fstart%5Fincluding%5Fpayloads"
options = "include%5Fdocs=true&startkey=%5B{0}%5D".format(view_time)
self.couchdb.expect_request( self.couchdb.expect_request(
path=self.db_path + "_design/uploader%5Fv1/_view/flights?" + options, path=self.db_path + view_path + "?" + options,
code=200, code=200,
respond_json=copy.deepcopy(fake_view_response) respond_json=copy.deepcopy(fake_view_response)
) )
self.couchdb.run() self.couchdb.run()
result = self.uploader.flights() result = self.uploader.flights()
assert result == flights assert result == expect_result
def test_payloads(self):
payloads = [{"_id": "pcfg_{0}".format(i), "a flight": i}
for i in xrange(100)]
rows = [{"id": doc["_id"], "key": None, "value": None, "doc": doc}
for doc in payloads]
fake_view_response = \
{"total_rows": len(rows), "offset": 0, "rows": rows}
view_path = "_design/payload%5Fconfiguration/_view/name%5Ftime%5Fcreated"
options = "include%5Fdocs=true"
self.couchdb.expect_request(
path=self.db_path + view_path + "?" + options,
code=200,
respond_json=copy.deepcopy(fake_view_response)
)
self.couchdb.run()
result = self.uploader.payloads()
assert result == payloads
class TestCPPConnectorThreaded(TestCPPConnector): class TestCPPConnectorThreaded(TestCPPConnector):
command = "tests/cpp_connector_threaded" command = "tests/cpp_connector_threaded"

Wyświetl plik

@ -28,7 +28,7 @@ public:
}; };
static Json::Value proxy_callback(const string &name, const Json::Value &args); static Json::Value proxy_callback(const string &name, const Json::Value &args);
static Json::Value repackage_flights(const vector<Json::Value> &flights); static Json::Value vector_to_json(const vector<Json::Value> &vect);
static void report_result(const Json::Value &arg1, static void report_result(const Json::Value &arg1,
const Json::Value &arg2=Json::Value::null, const Json::Value &arg2=Json::Value::null,
const Json::Value &arg3=Json::Value::null); const Json::Value &arg3=Json::Value::null);
@ -57,7 +57,10 @@ class TestUploaderThread : public habitat::UploaderThread
{ report_result("error", "invalid_argument", error.what()); } { report_result("error", "invalid_argument", error.what()); }
void got_flights(const vector<Json::Value> &flights) void got_flights(const vector<Json::Value> &flights)
{ report_result("return", repackage_flights(flights)); } { report_result("return", vector_to_json(flights)); }
void got_payloads(const vector<Json::Value> &payloads)
{ report_result("return", vector_to_json(payloads)); }
}; };
typedef TestUploaderThread TestSubject; typedef TestUploaderThread TestSubject;
@ -71,6 +74,7 @@ static r_string proxy_listener_info(TestSubject *u, Json::Value command);
static r_string proxy_listener_telemetry(TestSubject *u, Json::Value command); static r_string proxy_listener_telemetry(TestSubject *u, Json::Value command);
static r_string proxy_payload_telemetry(TestSubject *u, Json::Value command); static r_string proxy_payload_telemetry(TestSubject *u, Json::Value command);
static r_json proxy_flights(TestSubject *u); static r_json proxy_flights(TestSubject *u);
static r_json proxy_payloads(TestSubject *u);
static EZ::cURLGlobal cgl; static EZ::cURLGlobal cgl;
static EZ::Mutex cout_lock; static EZ::Mutex cout_lock;
@ -135,6 +139,8 @@ int main(int argc, char **argv)
return_value = proxy_payload_telemetry(u.get(), command); return_value = proxy_payload_telemetry(u.get(), command);
else if (command_name == "flights") else if (command_name == "flights")
return_value = proxy_flights(u.get()); return_value = proxy_flights(u.get());
else if (command_name == "payloads")
return_value = proxy_payloads(u.get());
else else
throw runtime_error("invalid command name"); throw runtime_error("invalid command name");
@ -173,6 +179,8 @@ int main(int argc, char **argv)
proxy_payload_telemetry(&thread, command); proxy_payload_telemetry(&thread, command);
else if (command_name == "flights") else if (command_name == "flights")
proxy_flights(&thread); proxy_flights(&thread);
else if (command_name == "payloads")
proxy_payloads(&thread);
else if (command_name == "return") else if (command_name == "return")
callback_responses.put(command); callback_responses.put(command);
#endif #endif
@ -330,17 +338,28 @@ static r_json proxy_flights(TestSubject *u)
#ifndef THREADED #ifndef THREADED
vector<Json::Value> *result = u->flights(); vector<Json::Value> *result = u->flights();
auto_ptr< vector<Json::Value> > destroyer(result); auto_ptr< vector<Json::Value> > destroyer(result);
return repackage_flights(*result); return vector_to_json(*result);
#else #else
u->flights(); u->flights();
#endif #endif
} }
static Json::Value repackage_flights(const vector<Json::Value> &flights) static r_json proxy_payloads(TestSubject *u)
{
#ifndef THREADED
vector<Json::Value> *result = u->payloads();
auto_ptr< vector<Json::Value> > destroyer(result);
return vector_to_json(*result);
#else
u->payloads();
#endif
}
static Json::Value vector_to_json(const vector<Json::Value> &vect)
{ {
Json::Value list(Json::arrayValue); Json::Value list(Json::arrayValue);
vector<Json::Value>::const_iterator it; vector<Json::Value>::const_iterator it;
for (it = flights.begin(); it != flights.end(); it++) for (it = vect.begin(); it != vect.end(); it++)
list.append(*it); list.append(*it);
return list; return list;
} }