mirror of
				https://github.com/ohwgiles/laminar.git
				synced 2025-06-13 12:54:29 +00:00 
			
		
		
		
	support for job and node tags
This commit is contained in:
		
							parent
							
								
									79c3ee5fcb
								
							
						
					
					
						commit
						0df97e95fd
					
				@ -82,7 +82,7 @@ generate_compressed_bins(${CMAKE_BINARY_DIR} js/angular.min.js js/angular-route.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Server
 | 
					## Server
 | 
				
			||||||
add_executable(laminard src/database.cpp src/main.cpp src/server.cpp src/laminar.cpp
 | 
					add_executable(laminard src/database.cpp src/main.cpp src/server.cpp src/laminar.cpp
 | 
				
			||||||
    src/conf.cpp src/resources.cpp src/run.cpp src/node.cpp laminar.capnp.c++ ${COMPRESSED_BINS})
 | 
					    src/conf.cpp src/resources.cpp src/run.cpp laminar.capnp.c++ ${COMPRESSED_BINS})
 | 
				
			||||||
# TODO: some alternative to boost::filesystem?
 | 
					# TODO: some alternative to boost::filesystem?
 | 
				
			||||||
target_link_libraries(laminard capnp capnp-rpc kj-async kj boost_filesystem boost_system sqlite3)
 | 
					target_link_libraries(laminard capnp capnp-rpc kj-async kj boost_filesystem boost_system sqlite3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -310,6 +310,17 @@ bool Laminar::loadConfiguration() {
 | 
				
			|||||||
            Node node;
 | 
					            Node node;
 | 
				
			||||||
            node.name = it.path().filename().string();
 | 
					            node.name = it.path().filename().string();
 | 
				
			||||||
            node.numExecutors = conf.get<int>("EXECUTORS", 6);
 | 
					            node.numExecutors = conf.get<int>("EXECUTORS", 6);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::string tags = conf.get<std::string>("TAGS");
 | 
				
			||||||
 | 
					            if(!tags.empty()) {
 | 
				
			||||||
 | 
					                std::istringstream iss(tags);
 | 
				
			||||||
 | 
					                std::set<std::string> tagList;
 | 
				
			||||||
 | 
					                std::copy(std::istream_iterator<std::string>(iss),
 | 
				
			||||||
 | 
					                          std::istream_iterator<std::string>(),
 | 
				
			||||||
 | 
					                          std::inserter(tagList, tagList.begin()));
 | 
				
			||||||
 | 
					                node.tags = tagList;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            nm.emplace(node.name, std::move(node));
 | 
					            nm.emplace(node.name, std::move(node));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -324,6 +335,32 @@ bool Laminar::loadConfiguration() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    nodes = nm;
 | 
					    nodes = nm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fs::path jobsDir = fs::path(homeDir)/"cfg"/"jobs";
 | 
				
			||||||
 | 
					    if(fs::is_directory(jobsDir)) {
 | 
				
			||||||
 | 
					        fs::directory_iterator dit(jobsDir);
 | 
				
			||||||
 | 
					        for(fs::directory_entry& it : dit) {
 | 
				
			||||||
 | 
					            if(!fs::is_directory(it.status()))
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            fs::directory_entry config(it.path()/"config");
 | 
				
			||||||
 | 
					            if(!fs::is_regular_file(config.status()))
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            StringMap conf = parseConfFile(config.path().string().c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::string tags = conf.get<std::string>("TAGS");
 | 
				
			||||||
 | 
					            if(!tags.empty()) {
 | 
				
			||||||
 | 
					                std::istringstream iss(tags);
 | 
				
			||||||
 | 
					                std::set<std::string> tagList;
 | 
				
			||||||
 | 
					                std::copy(std::istream_iterator<std::string>(iss),
 | 
				
			||||||
 | 
					                          std::istream_iterator<std::string>(),
 | 
				
			||||||
 | 
					                          std::inserter(tagList, tagList.begin()));
 | 
				
			||||||
 | 
					                jobTags[it.path().filename().string()] = tagList;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -425,6 +462,29 @@ void Laminar::reapAdvance() {
 | 
				
			|||||||
    assignNewJobs();
 | 
					    assignNewJobs();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Laminar::nodeCanQueue(const Node& node, const Run& run) const {
 | 
				
			||||||
 | 
					    // if a node is too busy, it can't take the job
 | 
				
			||||||
 | 
					    if(node.busyExecutors >= node.numExecutors)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto it = jobTags.find(run.name);
 | 
				
			||||||
 | 
					    // if both nodes have no tags, it's OK
 | 
				
			||||||
 | 
					    if(it == jobTags.end() && node.tags.size() == 0)
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // but if just one of them does, don't allow the build
 | 
				
			||||||
 | 
					    if(it == jobTags.end() || node.tags.size() == 0)
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // in other cases, allow the build if they have a tag in common
 | 
				
			||||||
 | 
					    for(const std::string& tag : it->second) {
 | 
				
			||||||
 | 
					        if(node.tags.find(tag) != node.tags.end())
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Laminar::assignNewJobs() {
 | 
					void Laminar::assignNewJobs() {
 | 
				
			||||||
    auto it = queuedJobs.begin();
 | 
					    auto it = queuedJobs.begin();
 | 
				
			||||||
    while(it != queuedJobs.end()) {
 | 
					    while(it != queuedJobs.end()) {
 | 
				
			||||||
@ -432,7 +492,7 @@ void Laminar::assignNewJobs() {
 | 
				
			|||||||
        for(auto& sn : nodes) {
 | 
					        for(auto& sn : nodes) {
 | 
				
			||||||
            Node& node = sn.second;
 | 
					            Node& node = sn.second;
 | 
				
			||||||
            std::shared_ptr<Run> run = *it;
 | 
					            std::shared_ptr<Run> run = *it;
 | 
				
			||||||
            if(node.queue(*run)) {
 | 
					            if(nodeCanQueue(node, *run)) {
 | 
				
			||||||
                node.busyExecutors++;
 | 
					                node.busyExecutors++;
 | 
				
			||||||
                run->node = &node;
 | 
					                run->node = &node;
 | 
				
			||||||
                run->startedAt = time(0);
 | 
					                run->startedAt = time(0);
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,7 @@ private:
 | 
				
			|||||||
    void assignNewJobs();
 | 
					    void assignNewJobs();
 | 
				
			||||||
    bool stepRun(std::shared_ptr<Run> run);
 | 
					    bool stepRun(std::shared_ptr<Run> run);
 | 
				
			||||||
    void runFinished(const Run*);
 | 
					    void runFinished(const Run*);
 | 
				
			||||||
 | 
					    bool nodeCanQueue(const Node&, const Run&) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::list<std::shared_ptr<Run>> queuedJobs;
 | 
					    std::list<std::shared_ptr<Run>> queuedJobs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -79,6 +80,8 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    std::unordered_map<std::string, uint> buildNums;
 | 
					    std::unordered_map<std::string, uint> buildNums;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::unordered_map<std::string, std::set<std::string>> jobTags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RunSet activeJobs;
 | 
					    RunSet activeJobs;
 | 
				
			||||||
    Database* db;
 | 
					    Database* db;
 | 
				
			||||||
    Server* srv;
 | 
					    Server* srv;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										25
									
								
								src/node.cpp
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/node.cpp
									
									
									
									
									
								
							@ -1,25 +0,0 @@
 | 
				
			|||||||
///
 | 
					 | 
				
			||||||
/// Copyright 2015 Oliver Giles
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// This file is part of Laminar
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// Laminar is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
/// it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
/// the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
/// (at your option) any later version.
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// Laminar 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 General Public License for more details.
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
/// along with Laminar.  If not, see <http://www.gnu.org/licenses/>
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
#include "node.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool Node::queue(const Run& run) {
 | 
					 | 
				
			||||||
    // later this could check if the given run is allowed to run
 | 
					 | 
				
			||||||
    // on this node, for example if the run's tags match the node's tags
 | 
					 | 
				
			||||||
    return busyExecutors < numExecutors;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -16,10 +16,11 @@
 | 
				
			|||||||
/// You should have received a copy of the GNU General Public License
 | 
					/// You should have received a copy of the GNU General Public License
 | 
				
			||||||
/// along with Laminar.  If not, see <http://www.gnu.org/licenses/>
 | 
					/// along with Laminar.  If not, see <http://www.gnu.org/licenses/>
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
#ifndef NODE_H
 | 
					#ifndef _LAMINAR_NODE_H_
 | 
				
			||||||
#define NODE_H
 | 
					#define _LAMINAR_NODE_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <set>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Run;
 | 
					class Run;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,10 +33,11 @@ public:
 | 
				
			|||||||
    std::string name;
 | 
					    std::string name;
 | 
				
			||||||
    int numExecutors;
 | 
					    int numExecutors;
 | 
				
			||||||
    int busyExecutors = 0;
 | 
					    int busyExecutors = 0;
 | 
				
			||||||
 | 
					    std::set<std::string> tags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Attempts to queue the given run to this node. Returns true if succeeded.
 | 
					    // Attempts to queue the given run to this node. Returns true if succeeded.
 | 
				
			||||||
    bool queue(const Run& run);
 | 
					    bool queue(const Run& run);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // NODE_H
 | 
					#endif // _LAMINAR_NODE_H_
 | 
				
			||||||
 | 
				
			|||||||
@ -91,7 +91,8 @@ bool Run::step() {
 | 
				
			|||||||
            setenv("PATH", PATH.c_str(), true);
 | 
					            setenv("PATH", PATH.c_str(), true);
 | 
				
			||||||
            setenv("lBuildNum", buildNum.c_str(), true);
 | 
					            setenv("lBuildNum", buildNum.c_str(), true);
 | 
				
			||||||
            setenv("lJobName", name.c_str(), true);
 | 
					            setenv("lJobName", name.c_str(), true);
 | 
				
			||||||
            setenv("lNode", node->name.c_str(), true);
 | 
					            if(!node->name.empty())
 | 
				
			||||||
 | 
					                setenv("lNode", node->name.c_str(), true);
 | 
				
			||||||
            setenv("lResult", to_string(result).c_str(), true);
 | 
					            setenv("lResult", to_string(result).c_str(), true);
 | 
				
			||||||
            setenv("lLastResult", to_string(lastResult).c_str(), true);
 | 
					            setenv("lLastResult", to_string(lastResult).c_str(), true);
 | 
				
			||||||
            setenv("lWorkspace", (fs::path(laminarHome)/"run"/name/"workspace").string().c_str(), true);
 | 
					            setenv("lWorkspace", (fs::path(laminarHome)/"run"/name/"workspace").string().c_str(), true);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user