From df862c152b078abbd380a8c1e3984d7a853dd0f7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 10:24:15 -0700 Subject: [PATCH 1/7] add a VoxelScriptingInterface to accept voxel addition in JS --- VoxelScriptingInterface.cpp | 9 +++++++ assignment-client/CMakeLists.txt | 3 ++- assignment-client/src/Agent.cpp | 18 ++++++------- .../src/VoxelScriptingInterface.cpp | 15 +++++++++++ .../src/VoxelScriptingInterface.h | 26 +++++++++++++++++++ 5 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 VoxelScriptingInterface.cpp create mode 100644 assignment-client/src/VoxelScriptingInterface.cpp create mode 100644 assignment-client/src/VoxelScriptingInterface.h diff --git a/VoxelScriptingInterface.cpp b/VoxelScriptingInterface.cpp new file mode 100644 index 0000000000..901bb06750 --- /dev/null +++ b/VoxelScriptingInterface.cpp @@ -0,0 +1,9 @@ +// +// VoxelScriptingInterface.cpp +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include "VoxelScriptingInterface.h" diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 1315b0ce84..f1a8566af3 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -23,4 +23,5 @@ include_glm(${TARGET_NAME} ${ROOT_DIR}) include(${MACRO_DIR}/LinkHifiLibrary.cmake) link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file +link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 3b56a6b0b7..147314ab9d 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -9,11 +9,11 @@ #include #include +#include #include -#include "AvatarData.h" - #include "Agent.h" +#include "VoxelScriptingInterface.h" Agent::Agent() : _shouldStop(false) @@ -39,14 +39,13 @@ void Agent::run(QUrl scriptURL) { QScriptEngine engine; - AvatarData *testAvatarData = new AvatarData; - - QScriptValue avatarDataValue = engine.newQObject(testAvatarData); - engine.globalObject().setProperty("Avatar", avatarDataValue); - QScriptValue agentValue = engine.newQObject(this); engine.globalObject().setProperty("Agent", agentValue); + VoxelScriptingInterface voxelScripter; + QScriptValue voxelScripterValue = engine.newQObject(&voxelScripter); + engine.globalObject().setProperty("Voxels", voxelScripterValue); + qDebug() << "Downloaded script:" << scriptString << "\n"; qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString() << "\n"; @@ -75,9 +74,10 @@ void Agent::run(QUrl scriptURL) { NodeList::getInstance()->sendDomainServerCheckIn(); } + // allow the scripter's call back to setup visual data emit preSendCallback(); - - testAvatarData->sendData(); + // flush the voxel packet queue + voxelScripter.getVoxelPacketSender()->flushQueue(); if (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)) { NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes); diff --git a/assignment-client/src/VoxelScriptingInterface.cpp b/assignment-client/src/VoxelScriptingInterface.cpp new file mode 100644 index 0000000000..9dce6a7c11 --- /dev/null +++ b/assignment-client/src/VoxelScriptingInterface.cpp @@ -0,0 +1,15 @@ +// +// VoxelScriptingInterface.cpp +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#include "VoxelScriptingInterface.h" + +void VoxelScriptingInterface::queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { + // setup a VoxelDetail struct with the data + VoxelDetail addVoxelDetail = {x, y, z, scale, red, green, blue}; + _voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_SET_VOXEL, 1, &addVoxelDetail); +} diff --git a/assignment-client/src/VoxelScriptingInterface.h b/assignment-client/src/VoxelScriptingInterface.h new file mode 100644 index 0000000000..e78dce5ff1 --- /dev/null +++ b/assignment-client/src/VoxelScriptingInterface.h @@ -0,0 +1,26 @@ +// +// VoxelScriptingInterface.h +// hifi +// +// Created by Stephen Birarda on 9/17/13. +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__VoxelScriptingInterface__ +#define __hifi__VoxelScriptingInterface__ + +#include + +#include + +class VoxelScriptingInterface : public QObject { + Q_OBJECT +public: + VoxelEditPacketSender* getVoxelPacketSender() { return &_voxelPacketSender; } +public slots: + void queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); +private: + VoxelEditPacketSender _voxelPacketSender; +}; + +#endif /* defined(__hifi__VoxelScriptingInterface__) */ From a45d64a214a8021e4ac5c24e73139769b4b56abe Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 10:49:51 -0700 Subject: [PATCH 2/7] add ability to send a voxel in JS via VoxelScriptingInterface --- assignment-client/src/Agent.cpp | 4 +-- .../src/VoxelScriptingInterface.cpp | 2 +- domain-server/src/main.cpp | 30 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 147314ab9d..98f0a0e525 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -23,7 +23,7 @@ Agent::Agent() : void Agent::run(QUrl scriptURL) { NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT); - NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AVATAR_MIXER, 1); + NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_VOXEL_SERVER, 1); QNetworkAccessManager manager; @@ -77,7 +77,7 @@ void Agent::run(QUrl scriptURL) { // allow the scripter's call back to setup visual data emit preSendCallback(); // flush the voxel packet queue - voxelScripter.getVoxelPacketSender()->flushQueue(); + voxelScripter.getVoxelPacketSender()->process(); if (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)) { NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes); diff --git a/assignment-client/src/VoxelScriptingInterface.cpp b/assignment-client/src/VoxelScriptingInterface.cpp index 9dce6a7c11..343cb01a44 100644 --- a/assignment-client/src/VoxelScriptingInterface.cpp +++ b/assignment-client/src/VoxelScriptingInterface.cpp @@ -11,5 +11,5 @@ void VoxelScriptingInterface::queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { // setup a VoxelDetail struct with the data VoxelDetail addVoxelDetail = {x, y, z, scale, red, green, blue}; - _voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_SET_VOXEL, 1, &addVoxelDetail); + _voxelPacketSender.sendVoxelEditMessage(PACKET_TYPE_SET_VOXEL, addVoxelDetail); } diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 8912c24483..0a935761a3 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -172,21 +172,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()) { - qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); - ::assignmentQueue.push_front(&avatarMixerAssignment); - } - - if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && - 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); - } - ::assignmentQueueMutex.unlock(); +// ::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()) { +// qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); +// ::assignmentQueue.push_front(&avatarMixerAssignment); +// } +// +// if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && +// 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); +// } +// ::assignmentQueueMutex.unlock(); while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { From 75c59c486393901c10cd199a5862e7c5c2a58122 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 10:54:44 -0700 Subject: [PATCH 3/7] add doxygen comments to VoxelScriptingInterface --- assignment-client/src/VoxelScriptingInterface.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/assignment-client/src/VoxelScriptingInterface.h b/assignment-client/src/VoxelScriptingInterface.h index e78dce5ff1..00be3d536f 100644 --- a/assignment-client/src/VoxelScriptingInterface.h +++ b/assignment-client/src/VoxelScriptingInterface.h @@ -13,13 +13,23 @@ #include +/// handles scripting of voxel commands from JS passed to assigned clients class VoxelScriptingInterface : public QObject { Q_OBJECT public: VoxelEditPacketSender* getVoxelPacketSender() { return &_voxelPacketSender; } public slots: + /// queues the creation of a voxel which will be sent by calling process on the PacketSender + /// \param x the x-coordinate of the voxel (in VS space) + /// \param y the y-coordinate of the voxel (in VS space) + /// \param z the z-coordinate of the voxel (in VS space) + /// \param scale the scale of the voxel (in VS space) + /// \param red the R value for RGB color of voxel + /// \param green the G value for RGB color of voxel + /// \param blue the B value for RGB color of voxel void queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue); private: + /// attached VoxelEditPacketSender that handles queuing and sending of packets to VS VoxelEditPacketSender _voxelPacketSender; }; From 17fda717fe85fc7e8fea952a12cc5d2b7fcd1297 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 11:04:46 -0700 Subject: [PATCH 4/7] move audio and avatar classes into assignment-client target --- assignment-client/CMakeLists.txt | 8 +++++++- assignment-client/src/Agent.cpp | 2 +- .../src => assignment-client/src/audio}/AudioMixer.cpp | 0 .../src => assignment-client/src/audio}/AudioMixer.h | 0 .../src/audio}/AvatarAudioRingBuffer.cpp | 0 .../src/audio}/AvatarAudioRingBuffer.h | 0 .../src/avatars}/AvatarMixer.cpp | 0 .../src/avatars}/AvatarMixer.h | 0 assignment-client/src/main.cpp | 4 ++-- .../src/{ => voxels}/VoxelScriptingInterface.cpp | 0 .../src/{ => voxels}/VoxelScriptingInterface.h | 0 cmake/macros/SetupHifiProject.cmake | 10 +++++++++- libraries/audio/CMakeLists.txt | 8 +------- 13 files changed, 20 insertions(+), 12 deletions(-) rename {libraries/audio/src => assignment-client/src/audio}/AudioMixer.cpp (100%) rename {libraries/audio/src => assignment-client/src/audio}/AudioMixer.h (100%) rename {libraries/audio/src => assignment-client/src/audio}/AvatarAudioRingBuffer.cpp (100%) rename {libraries/audio/src => assignment-client/src/audio}/AvatarAudioRingBuffer.h (100%) rename {libraries/avatars/src => assignment-client/src/avatars}/AvatarMixer.cpp (100%) rename {libraries/avatars/src => assignment-client/src/avatars}/AvatarMixer.h (100%) rename assignment-client/src/{ => voxels}/VoxelScriptingInterface.cpp (100%) rename assignment-client/src/{ => voxels}/VoxelScriptingInterface.h (100%) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index f1a8566af3..5d61190286 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -24,4 +24,10 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake) link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR}) link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR}) -link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file +link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR}) + +# link the stk library +set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk) +find_package(STK REQUIRED) +target_link_libraries(${TARGET_NAME} ${STK_LIBRARIES}) +include_directories(${STK_INCLUDE_DIRS}) \ No newline at end of file diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 98f0a0e525..ac6f1eca4f 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -13,7 +13,7 @@ #include #include "Agent.h" -#include "VoxelScriptingInterface.h" +#include "voxels/VoxelScriptingInterface.h" Agent::Agent() : _shouldStop(false) diff --git a/libraries/audio/src/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp similarity index 100% rename from libraries/audio/src/AudioMixer.cpp rename to assignment-client/src/audio/AudioMixer.cpp diff --git a/libraries/audio/src/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h similarity index 100% rename from libraries/audio/src/AudioMixer.h rename to assignment-client/src/audio/AudioMixer.h diff --git a/libraries/audio/src/AvatarAudioRingBuffer.cpp b/assignment-client/src/audio/AvatarAudioRingBuffer.cpp similarity index 100% rename from libraries/audio/src/AvatarAudioRingBuffer.cpp rename to assignment-client/src/audio/AvatarAudioRingBuffer.cpp diff --git a/libraries/audio/src/AvatarAudioRingBuffer.h b/assignment-client/src/audio/AvatarAudioRingBuffer.h similarity index 100% rename from libraries/audio/src/AvatarAudioRingBuffer.h rename to assignment-client/src/audio/AvatarAudioRingBuffer.h diff --git a/libraries/avatars/src/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp similarity index 100% rename from libraries/avatars/src/AvatarMixer.cpp rename to assignment-client/src/avatars/AvatarMixer.cpp diff --git a/libraries/avatars/src/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h similarity index 100% rename from libraries/avatars/src/AvatarMixer.h rename to assignment-client/src/avatars/AvatarMixer.h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 16522a2d87..2ad8345e53 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -16,8 +16,8 @@ #include "Agent.h" #include -#include -#include +#include "audio/AudioMixer.h" +#include "avatars/AvatarMixer.h" #include #include #include diff --git a/assignment-client/src/VoxelScriptingInterface.cpp b/assignment-client/src/voxels/VoxelScriptingInterface.cpp similarity index 100% rename from assignment-client/src/VoxelScriptingInterface.cpp rename to assignment-client/src/voxels/VoxelScriptingInterface.cpp diff --git a/assignment-client/src/VoxelScriptingInterface.h b/assignment-client/src/voxels/VoxelScriptingInterface.h similarity index 100% rename from assignment-client/src/VoxelScriptingInterface.h rename to assignment-client/src/voxels/VoxelScriptingInterface.h diff --git a/cmake/macros/SetupHifiProject.cmake b/cmake/macros/SetupHifiProject.cmake index 8b2bcb542c..e828e68be2 100644 --- a/cmake/macros/SetupHifiProject.cmake +++ b/cmake/macros/SetupHifiProject.cmake @@ -2,7 +2,15 @@ MACRO(SETUP_HIFI_PROJECT TARGET INCLUDE_QT) project(${TARGET}) # grab the implemenation and header files - file(GLOB TARGET_SRCS src/*.cpp src/*.h src/*.c) + file(GLOB TARGET_SRCS src/*) + + file(GLOB SRC_SUBDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src/*) + foreach(DIR ${SRC_SUBDIRS}) + if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/${DIR}) + FILE(GLOB DIR_CONTENTS src/${DIR}/*) + SET(TARGET_SRCS ${TARGET_SRCS} ${DIR_CONTENTS}) + endif() + endforeach() # add the executable add_executable(${TARGET} ${TARGET_SRCS}) diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt index 6c458149bc..2d82fff1e1 100644 --- a/libraries/audio/CMakeLists.txt +++ b/libraries/audio/CMakeLists.txt @@ -16,10 +16,4 @@ include(${MACRO_DIR}/IncludeGLM.cmake) include_glm(${TARGET_NAME} ${ROOT_DIR}) include(${MACRO_DIR}/LinkHifiLibrary.cmake) -link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) - -# link the stk library -set(STK_ROOT_DIR ${ROOT_DIR}/externals/stk) -find_package(STK REQUIRED) -target_link_libraries(${TARGET_NAME} ${STK_LIBRARIES}) -include_directories(${STK_INCLUDE_DIRS}) \ No newline at end of file +link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR}) \ No newline at end of file From 0e19d9a53ad0e0303750ffc5d49f63cc5175418a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 11:19:13 -0700 Subject: [PATCH 5/7] add handling for number of instances to domain-server --- domain-server/src/main.cpp | 49 ++++++++++++++++++++----------- libraries/shared/src/Assignment.h | 5 ++++ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 0a935761a3..0d76482808 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -76,9 +76,20 @@ static int mongooseRequestHandler(struct mg_connection *conn) { const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "resources/web/assignment"; static void mongooseUploadHandler(struct mg_connection *conn, const char *path) { + // create an assignment for this saved script, for now make it local only Assignment *scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment::AgentType, Assignment::LocalLocation); + // check how many instances of this assignment the user wants by checking the ASSIGNMENT-INSTANCES header + const char ASSIGNMENT_INSTANCES_HTTP_HEADER[] = "ASSIGNMENT-INSTANCES"; + const char *requestInstancesHeader = mg_get_header(conn, ASSIGNMENT_INSTANCES_HTTP_HEADER); + + if (requestInstancesHeader) { + // the user has requested a number of instances greater than 1 + // so set that on the created assignment + scriptAssignment->setNumberOfInstances(atoi(requestInstancesHeader)); + } + QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION); newPath += "/"; // append the UUID for this script as the new filename, remove the curly braces @@ -94,7 +105,6 @@ static void mongooseUploadHandler(struct mg_connection *conn, const char *path) ::assignmentQueueMutex.lock(); ::assignmentQueue.push_back(scriptAssignment); ::assignmentQueueMutex.unlock(); - } int main(int argc, const char* argv[]) { @@ -172,21 +182,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()) { -// qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); -// ::assignmentQueue.push_front(&avatarMixerAssignment); -// } -// -// if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && -// 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); -// } -// ::assignmentQueueMutex.unlock(); + ::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()) { + qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n"); + ::assignmentQueue.push_front(&avatarMixerAssignment); + } + + if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) && + 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); + } + ::assignmentQueueMutex.unlock(); while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) && packetVersionMatch(packetData)) { @@ -308,7 +318,12 @@ int main(int argc, const char* argv[]) { if ((*assignment)->getType() == Assignment::AgentType) { // if this is a script assignment we need to delete it to avoid a memory leak - delete *assignment; + // or if there is more than one instance to send out, simpy decrease the number of instances + if ((*assignment)->getNumberOfInstances() > 1) { + (*assignment)->decrementNumberOfInstances(); + } else { + delete *assignment; + } } // stop looping, we've handed out an assignment diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 6985f21535..dc246a9ad6 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -55,6 +55,10 @@ public: Assignment::Location getLocation() const { return _location; } const timeval& getTime() const { return _time; } + int getNumberOfInstances() const { return _numberOfInstances; } + void setNumberOfInstances(int numberOfInstances) { _numberOfInstances = numberOfInstances; } + void decrementNumberOfInstances() { --_numberOfInstances; } + const sockaddr* getAttachedPublicSocket() { return _attachedPublicSocket; } void setAttachedPublicSocket(const sockaddr* attachedPublicSocket); @@ -77,6 +81,7 @@ private: sockaddr* _attachedPublicSocket; /// pointer to a public socket that relates to assignment, depends on direction sockaddr* _attachedLocalSocket; /// pointer to a local socket that relates to assignment, depends on direction timeval _time; /// time the assignment was created (set in constructor) + int _numberOfInstances; /// the number of instances of this assignment }; QDebug operator<<(QDebug debug, const Assignment &assignment); From 76df707e3192ed870ca0ba03ff130cbbebf13b46 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 11:48:08 -0700 Subject: [PATCH 6/7] add the ability to ask for multiple instances from JS page --- .../resources/web/assignment/css/style.css | 13 +++++++++++- .../resources/web/assignment/index.shtml | 3 +++ .../resources/web/assignment/js/assignment.js | 6 ++++++ domain-server/src/main.cpp | 21 ++++++++++++------- libraries/shared/src/Assignment.cpp | 6 ++++-- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/domain-server/resources/web/assignment/css/style.css b/domain-server/resources/web/assignment/css/style.css index 000f2eff67..b6c26ca9fd 100644 --- a/domain-server/resources/web/assignment/css/style.css +++ b/domain-server/resources/web/assignment/css/style.css @@ -36,11 +36,22 @@ body { } #deploy-button { background-color: #0DFFBB; - right: 0px; + right: 85px; } #deploy-button:hover { background-color: #28FF57; } + +#instance-field { + position: absolute; + right: 20px; + top: 40px; +} + +#instance-field input { + width: 80px; +} + #stop-button { background-color: #CC1F00; right: 0px; diff --git a/domain-server/resources/web/assignment/index.shtml b/domain-server/resources/web/assignment/index.shtml index fe47b818ed..0bc0e67eef 100644 --- a/domain-server/resources/web/assignment/index.shtml +++ b/domain-server/resources/web/assignment/index.shtml @@ -14,6 +14,9 @@ Run +
+ +
diff --git a/domain-server/resources/web/assignment/js/assignment.js b/domain-server/resources/web/assignment/js/assignment.js index 630acd4847..a34f539961 100644 --- a/domain-server/resources/web/assignment/js/assignment.js +++ b/domain-server/resources/web/assignment/js/assignment.js @@ -20,6 +20,11 @@ $(document).ready(function(){ // add the script + script + '\r\n' + '--' + boundary + '--'; + + var headers = {}; + if ($('#instance-field input').val()) { + headers['ASSIGNMENT-INSTANCES'] = $('#instance-field input').val(); + } // post form to assignment in order to create an assignment $.ajax({ @@ -27,6 +32,7 @@ $(document).ready(function(){ data: body, type: "POST", url: "/assignment", + headers: headers, success: function (data, status) { console.log(data); console.log(status); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 0d76482808..b4b5c0ec36 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -313,17 +313,18 @@ int main(int argc, const char* argv[]) { broadcastPacket, numHeaderBytes + numAssignmentBytes); - // remove the assignment from the queue - ::assignmentQueue.erase(assignment); - if ((*assignment)->getType() == Assignment::AgentType) { // if this is a script assignment we need to delete it to avoid a memory leak // or if there is more than one instance to send out, simpy decrease the number of instances if ((*assignment)->getNumberOfInstances() > 1) { (*assignment)->decrementNumberOfInstances(); } else { + ::assignmentQueue.erase(assignment); delete *assignment; } + } else { + // remove the assignment from the queue + ::assignmentQueue.erase(assignment); } // stop looping, we've handed out an assignment @@ -351,12 +352,18 @@ int main(int argc, const char* argv[]) { nodeList->sendAssignment(*(*assignment)); - // remove the assignment from the queue - ::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; + // or if there is more than one instance to send out, simpy decrease the number of instances + if ((*assignment)->getNumberOfInstances() > 1) { + (*assignment)->decrementNumberOfInstances(); + } else { + ::assignmentQueue.erase(assignment); + delete *assignment; + } + } else { + // remove the assignment from the queue + ::assignmentQueue.erase(assignment); } // stop looping, we've handed out an assignment diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 8f6d20db9e..d794495c29 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -21,7 +21,8 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assig _type(type), _location(location), _attachedPublicSocket(NULL), - _attachedLocalSocket(NULL) + _attachedLocalSocket(NULL), + _numberOfInstances(1) { // set the create time on this assignment gettimeofday(&_time, NULL); @@ -35,7 +36,8 @@ Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assig Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : _location(GlobalLocation), _attachedPublicSocket(NULL), - _attachedLocalSocket(NULL) + _attachedLocalSocket(NULL), + _numberOfInstances(1) { // set the create time on this assignment gettimeofday(&_time, NULL); From 2cfa45e4f86fe293406a8c8b0fadf9312b4291ab Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 17 Sep 2013 12:09:10 -0700 Subject: [PATCH 7/7] allow the assignment-client to specify the type of assignment it desires --- assignment-client/src/main.cpp | 14 +++++++-- assignment-server/src/main.cpp | 55 ++++++++++++++++++++-------------- domain-server/src/main.cpp | 46 ++++++++++++++++------------ 3 files changed, 71 insertions(+), 44 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index f58828e65f..76fb99839a 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -31,6 +31,7 @@ const char CHILD_TARGET_NAME[] = "assignment-client"; pid_t* childForks = NULL; sockaddr_in customAssignmentSocket = {}; int numForks = 0; +Assignment::Type overiddenAssignmentType = Assignment::AllTypes; void childClient() { // this is one of the child forks or there is a single assignment client, continue assignment-client execution @@ -56,8 +57,8 @@ void childClient() { sockaddr_in senderSocket = {}; - // create a request assignment, accept all assignments, pass the desired pool (if it exists) - Assignment requestAssignment(Assignment::RequestCommand, Assignment::AllTypes); + // create a request assignment, accept assignments defined by the overidden type + Assignment requestAssignment(Assignment::RequestCommand, ::overiddenAssignmentType); while (true) { if (usecTimestampNow() - usecTimestamp(&lastRequest) >= ASSIGNMENT_REQUEST_INTERVAL_USECS) { @@ -211,6 +212,15 @@ int main(int argc, const char* argv[]) { ::customAssignmentSocket = socketForHostnameAndHostOrderPort(customAssignmentServerHostname, assignmentServerPort); } + const char ASSIGNMENT_TYPE_OVVERIDE_OPTION[] = "-t"; + const char* assignmentTypeString = getCmdOption(argc, argv, ASSIGNMENT_TYPE_OVVERIDE_OPTION); + + if (assignmentTypeString) { + // the user is asking to only be assigned to a particular type of assignment + // so set that as the ::overridenAssignmentType to be used in requests + ::overiddenAssignmentType = (Assignment::Type) atoi(assignmentTypeString); + } + const char* NUM_FORKS_PARAMETER = "-n"; const char* numForksString = getCmdOption(argc, argv, NUM_FORKS_PARAMETER); diff --git a/assignment-server/src/main.cpp b/assignment-server/src/main.cpp index caec59cd77..db335008a5 100644 --- a/assignment-server/src/main.cpp +++ b/assignment-server/src/main.cpp @@ -62,30 +62,39 @@ int main(int argc, const char* argv[]) { continue; } - // check if the requestor is on the same network as the destination for the assignment - if (senderSocket.sin_addr.s_addr == - ((sockaddr_in*) (*assignment)->getAttachedPublicSocket())->sin_addr.s_addr) { - // if this is the case we remove the public socket on the assignment by setting it to NULL - // this ensures the local IP and port sent to the requestor is the local address of destination - (*assignment)->setAttachedPublicSocket(NULL); + if (requestAssignment.getType() == Assignment::AllTypes || + (*assignment)->getType() == requestAssignment.getType()) { + // give this assignment out, either we have a type match or the requestor has said they will + // take all types + + // check if the requestor is on the same network as the destination for the assignment + if (senderSocket.sin_addr.s_addr == + ((sockaddr_in*) (*assignment)->getAttachedPublicSocket())->sin_addr.s_addr) { + // if this is the case we remove the public socket on the assignment by setting it to NULL + // this ensures the local IP and port sent to the requestor is the local address of destination + (*assignment)->setAttachedPublicSocket(NULL); + } + + + int numAssignmentBytes = (*assignment)->packToBuffer(assignmentPacket + numSendHeaderBytes); + + // send the assignment + serverSocket.send((sockaddr*) &senderSocket, + assignmentPacket, + numSendHeaderBytes + numAssignmentBytes); + + + // delete this assignment now that it has been sent out + delete *assignment; + // remove it from the deque and make the iterator the next assignment + assignmentQueue.erase(assignment); + + // stop looping - we've handed out an assignment + break; + } else { + // push forward the iterator to check the next assignment + assignment++; } - - - int numAssignmentBytes = (*assignment)->packToBuffer(assignmentPacket + numSendHeaderBytes); - - // send the assignment - serverSocket.send((sockaddr*) &senderSocket, - assignmentPacket, - numSendHeaderBytes + numAssignmentBytes); - - - // delete this assignment now that it has been sent out - delete *assignment; - // remove it from the deque and make the iterator the next assignment - assignmentQueue.erase(assignment); - - // stop looping - we've handed out an assignment - break; } } } else if (senderData[0] == PACKET_TYPE_CREATE_ASSIGNMENT && packetVersionMatch(senderData)) { diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 3cb433b933..62d8be42b7 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -330,31 +330,39 @@ int main(int argc, const char* argv[]) { std::deque::iterator assignment = ::assignmentQueue.begin(); while (assignment != ::assignmentQueue.end()) { + // construct the requested assignment from the packet data + Assignment requestAssignment(packetData, receivedBytes); - // give this assignment out, no conditions stop us from giving it to the local assignment client - int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); - int numAssignmentBytes = (*assignment)->packToBuffer(broadcastPacket + numHeaderBytes); - - nodeList->getNodeSocket()->send((sockaddr*) &nodePublicAddress, - broadcastPacket, - numHeaderBytes + numAssignmentBytes); - - if ((*assignment)->getType() == Assignment::AgentType) { - // if this is a script assignment we need to delete it to avoid a memory leak - // or if there is more than one instance to send out, simpy decrease the number of instances - if ((*assignment)->getNumberOfInstances() > 1) { - (*assignment)->decrementNumberOfInstances(); + if (requestAssignment.getType() == Assignment::AllTypes || + (*assignment)->getType() == requestAssignment.getType()) { + // give this assignment out, either the type matches or the requestor said they will take any + int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); + int numAssignmentBytes = (*assignment)->packToBuffer(broadcastPacket + numHeaderBytes); + + nodeList->getNodeSocket()->send((sockaddr*) &nodePublicAddress, + broadcastPacket, + numHeaderBytes + numAssignmentBytes); + + if ((*assignment)->getType() == Assignment::AgentType) { + // if this is a script assignment we need to delete it to avoid a memory leak + // or if there is more than one instance to send out, simpy decrease the number of instances + if ((*assignment)->getNumberOfInstances() > 1) { + (*assignment)->decrementNumberOfInstances(); + } else { + ::assignmentQueue.erase(assignment); + delete *assignment; + } } else { + // remove the assignment from the queue ::assignmentQueue.erase(assignment); - delete *assignment; } + + // stop looping, we've handed out an assignment + break; } else { - // remove the assignment from the queue - ::assignmentQueue.erase(assignment); + // push forward the iterator to check the next assignment + assignment++; } - - // stop looping, we've handed out an assignment - break; } ::assignmentQueueMutex.unlock();