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
 | 
			
		||||
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?
 | 
			
		||||
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.name = it.path().filename().string();
 | 
			
		||||
            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));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -324,6 +335,32 @@ bool Laminar::loadConfiguration() {
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -425,6 +462,29 @@ void Laminar::reapAdvance() {
 | 
			
		||||
    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() {
 | 
			
		||||
    auto it = queuedJobs.begin();
 | 
			
		||||
    while(it != queuedJobs.end()) {
 | 
			
		||||
@ -432,7 +492,7 @@ void Laminar::assignNewJobs() {
 | 
			
		||||
        for(auto& sn : nodes) {
 | 
			
		||||
            Node& node = sn.second;
 | 
			
		||||
            std::shared_ptr<Run> run = *it;
 | 
			
		||||
            if(node.queue(*run)) {
 | 
			
		||||
            if(nodeCanQueue(node, *run)) {
 | 
			
		||||
                node.busyExecutors++;
 | 
			
		||||
                run->node = &node;
 | 
			
		||||
                run->startedAt = time(0);
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,7 @@ private:
 | 
			
		||||
    void assignNewJobs();
 | 
			
		||||
    bool stepRun(std::shared_ptr<Run> run);
 | 
			
		||||
    void runFinished(const Run*);
 | 
			
		||||
    bool nodeCanQueue(const Node&, const Run&) const;
 | 
			
		||||
 | 
			
		||||
    std::list<std::shared_ptr<Run>> queuedJobs;
 | 
			
		||||
 | 
			
		||||
@ -79,6 +80,8 @@ private:
 | 
			
		||||
 | 
			
		||||
    std::unordered_map<std::string, uint> buildNums;
 | 
			
		||||
 | 
			
		||||
    std::unordered_map<std::string, std::set<std::string>> jobTags;
 | 
			
		||||
 | 
			
		||||
    RunSet activeJobs;
 | 
			
		||||
    Database* db;
 | 
			
		||||
    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
 | 
			
		||||
/// along with Laminar.  If not, see <http://www.gnu.org/licenses/>
 | 
			
		||||
///
 | 
			
		||||
#ifndef NODE_H
 | 
			
		||||
#define NODE_H
 | 
			
		||||
#ifndef _LAMINAR_NODE_H_
 | 
			
		||||
#define _LAMINAR_NODE_H_
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
class Run;
 | 
			
		||||
 | 
			
		||||
@ -32,10 +33,11 @@ public:
 | 
			
		||||
    std::string name;
 | 
			
		||||
    int numExecutors;
 | 
			
		||||
    int busyExecutors = 0;
 | 
			
		||||
    std::set<std::string> tags;
 | 
			
		||||
 | 
			
		||||
    // Attempts to queue the given run to this node. Returns true if succeeded.
 | 
			
		||||
    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("lBuildNum", buildNum.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("lLastResult", to_string(lastResult).c_str(), true);
 | 
			
		||||
            setenv("lWorkspace", (fs::path(laminarHome)/"run"/name/"workspace").string().c_str(), true);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user