add handling of Agent assignments to Assignment, DS, AC

This commit is contained in:
Stephen Birarda 2013-09-13 11:14:00 -07:00
parent 3441199f0b
commit d089991237
8 changed files with 84 additions and 26 deletions

View file

@ -8,9 +8,17 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
find_package(Qt5Network REQUIRED)
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE)
qt5_use_modules(${TARGET_NAME} Network)
# include glm
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} ${ROOT_DIR})
# link in the shared library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})

View file

@ -25,11 +25,11 @@ void Agent::run(QUrl scriptURL) {
NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT);
NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AVATAR_MIXER, 1);
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkAccessManager manager;
qDebug() << "Attemping download of " << scriptURL;
qDebug() << "Attemping download of " << scriptURL << "\n";
QNetworkReply* reply = manager->get(QNetworkRequest(scriptURL));
QNetworkReply* reply = manager.get(QNetworkRequest(scriptURL));
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
@ -47,15 +47,14 @@ void Agent::run(QUrl scriptURL) {
QScriptValue agentValue = engine.newQObject(this);
engine.globalObject().setProperty("Agent", agentValue);
qDebug() << "Downloaded script:" << scriptString;
qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString();
qDebug() << "Downloaded script:" << scriptString << "\n";
qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString() << "\n";
timeval thisSend;
timeval lastDomainServerCheckIn = {};
int numMicrosecondsSleep = 0;
const float DATA_SEND_INTERVAL_USECS = (1 / 60.0f) * 1000 * 1000;
const long long DATA_SEND_INTERVAL_USECS = (1 / 60.0f) * 1000 * 1000;
sockaddr_in senderAddress;
unsigned char receivedData[MAX_PACKET_SIZE];
@ -65,6 +64,11 @@ void Agent::run(QUrl scriptURL) {
// update the thisSend timeval to the current time
gettimeofday(&thisSend, NULL);
// if we're not hearing from the domain-server we should stop running
if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
break;
}
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
gettimeofday(&lastDomainServerCheckIn, NULL);

View file

@ -9,9 +9,6 @@
#ifndef __hifi__Agent__
#define __hifi__Agent__
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include "SharedUtil.h"
#include <QtCore/QObject>

View file

@ -12,6 +12,9 @@
#include <sys/time.h>
#include <sys/wait.h>
#include <QtCore/QCoreApplication>
#include "Agent.h"
#include <Assignment.h>
#include <AudioMixer.h>
#include <AvatarMixer.h>
@ -92,8 +95,18 @@ void childClient() {
if (deployedAssignment.getType() == Assignment::AudioMixerType) {
AudioMixer::run();
} else {
} else if (deployedAssignment.getType() == Assignment::AvatarMixerType) {
AvatarMixer::run();
} else {
// figure out the URL for the script for this agent assignment
QString scriptURLString("http://%1:8080/assignment/%2");
scriptURLString = scriptURLString.arg(inet_ntoa(domainSocketAddr),
deployedAssignment.getUUIDStringWithoutCurlyBraces());
qDebug() << "Starting an Agent assignment-client with script at" << scriptURLString << "\n";
Agent scriptAgent;
scriptAgent.run(QUrl(scriptURLString));
}
} else {
qDebug("Received a bad destination socket for assignment.\n");
@ -171,6 +184,8 @@ void parentMonitor() {
int main(int argc, const char* argv[]) {
QCoreApplication app(argc, (char**) argv);
setvbuf(stdout, NULL, _IOLBF, 0);
// use the verbose message handler in Logging

View file

@ -26,6 +26,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <QtCore/QMutex>
#include "Assignment.h"
#include "NodeList.h"
#include "NodeTypes.h"
@ -40,6 +42,9 @@ unsigned char packetData[MAX_PACKET_SIZE];
const int NODE_COUNT_STAT_INTERVAL_MSECS = 5000;
QMutex assignmentQueueMutex;
std::deque<Assignment*> assignmentQueue;
unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) {
*currentPosition++ = nodeToAdd->getType();
@ -70,18 +75,25 @@ static int mongooseRequestHandler(struct mg_connection *conn) {
const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "web/assignment";
static void mongooseUploadHandler(struct mg_connection *conn, const char *path) {
// create an assignment for this saved script
Assignment scriptAssignment(Assignment::CreateCommand, Assignment::AgentType);
// create an assignment for this saved script, for now make it local only
Assignment *scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment::AgentType, Assignment::LocalLocation);
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
newPath += "/";
// append the UUID for this script as the new filename, remove the curly braces
newPath += scriptAssignment.getUUID().toString().mid(1, scriptAssignment.getUUID().toString().length() - 2);
newPath += scriptAssignment->getUUIDStringWithoutCurlyBraces();
// rename the saved script to the GUID of the assignment and move it to the script host locaiton
rename(path, newPath.toStdString().c_str());
qDebug("Saved a script for assignment at %s\n", newPath.toStdString().c_str());
// add the script assigment to the assignment queue
// lock the assignment queue mutex since we're operating on a different thread than DS main
::assignmentQueueMutex.lock();
::assignmentQueue.push_back(scriptAssignment);
::assignmentQueueMutex.unlock();
}
int main(int argc, const char* argv[]) {
@ -121,9 +133,6 @@ int main(int argc, const char* argv[]) {
const long long GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000;
timeval lastGlobalAssignmentRequest = {};
// setup the assignment queue
std::deque<Assignment*> assignmentQueue;
// as a domain-server we will always want an audio mixer and avatar mixer
// setup the create assignments for those
Assignment audioMixerAssignment(Assignment::CreateCommand,
@ -156,19 +165,21 @@ int main(int argc, const char* argv[]) {
while (true) {
::assignmentQueueMutex.lock();
// check if our audio-mixer or avatar-mixer are dead and we don't have existing assignments in the queue
// so we can add those assignments back to the front of the queue since they are high-priority
if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER) &&
std::find(assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == assignmentQueue.end()) {
std::find(::assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == ::assignmentQueue.end()) {
qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n");
assignmentQueue.push_front(&avatarMixerAssignment);
::assignmentQueue.push_front(&avatarMixerAssignment);
}
if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) &&
std::find(assignmentQueue.begin(), assignmentQueue.end(), &audioMixerAssignment) == assignmentQueue.end()) {
std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &audioMixerAssignment) == ::assignmentQueue.end()) {
qDebug("Missing an audio mixer and assignment not in queue. Adding.\n");
assignmentQueue.push_front(&audioMixerAssignment);
::assignmentQueue.push_front(&audioMixerAssignment);
}
::assignmentQueueMutex.unlock();
while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) &&
packetVersionMatch(packetData)) {
@ -269,11 +280,13 @@ int main(int argc, const char* argv[]) {
qDebug("Received a request for assignment.\n");
::assignmentQueueMutex.lock();
// this is an unassigned client talking to us directly for an assignment
// go through our queue and see if there are any assignments to give out
std::deque<Assignment*>::iterator assignment = assignmentQueue.begin();
std::deque<Assignment*>::iterator assignment = ::assignmentQueue.begin();
while (assignment != assignmentQueue.end()) {
while (assignment != ::assignmentQueue.end()) {
// give this assignment out, no conditions stop us from giving it to the local assignment client
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT);
@ -284,11 +297,18 @@ int main(int argc, const char* argv[]) {
numHeaderBytes + numAssignmentBytes);
// remove the assignment from the queue
assignmentQueue.erase(assignment);
::assignmentQueue.erase(assignment);
if ((*assignment)->getType() == Assignment::AgentType) {
// if this is a script assignment we need to delete it to avoid a memory leak
delete *assignment;
}
// stop looping, we've handed out an assignment
break;
}
::assignmentQueueMutex.unlock();
}
}
@ -296,8 +316,10 @@ int main(int argc, const char* argv[]) {
if (usecTimestampNow() - usecTimestamp(&lastGlobalAssignmentRequest) >= GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS) {
gettimeofday(&lastGlobalAssignmentRequest, NULL);
::assignmentQueueMutex.lock();
// go through our queue and see if there are any assignments to send to the global assignment server
std::deque<Assignment*>::iterator assignment = assignmentQueue.begin();
std::deque<Assignment*>::iterator assignment = ::assignmentQueue.begin();
while (assignment != assignmentQueue.end()) {
@ -308,7 +330,12 @@ int main(int argc, const char* argv[]) {
nodeList->sendAssignment(*(*assignment));
// remove the assignment from the queue
assignmentQueue.erase(assignment);
::assignmentQueue.erase(assignment);
if ((*assignment)->getType() == Assignment::AgentType) {
// if this is a script assignment we need to delete it to avoid a memory leak
delete *assignment;
}
// stop looping, we've handed out an assignment
break;
@ -318,6 +345,7 @@ int main(int argc, const char* argv[]) {
}
}
::assignmentQueueMutex.unlock();
}
if (Logging::shouldSendStats()) {

View file

@ -1,3 +1,4 @@
//
// AudioMixer.cpp
// hifi

View file

@ -89,6 +89,10 @@ Assignment::~Assignment() {
delete _attachedLocalSocket;
}
QString Assignment::getUUIDStringWithoutCurlyBraces() const {
return _uuid.toString().mid(1, _uuid.toString().length() - 2);
}
void Assignment::setAttachedPublicSocket(const sockaddr* attachedPublicSocket) {
if (_attachedPublicSocket) {
// delete the old socket if it exists

View file

@ -49,6 +49,7 @@ public:
~Assignment();
const QUuid& getUUID() const { return _uuid; }
QString getUUIDStringWithoutCurlyBraces() const;
Assignment::Command getCommand() const { return _command; }
Assignment::Type getType() const { return _type; }
Assignment::Location getLocation() const { return _location; }