├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── examples ├── MiniSAT │ ├── MiniSATWrapper.py │ ├── README.md │ ├── gzip_vc1071.cnf │ └── minisat ├── SGD │ ├── README.md │ ├── SGDWrapper.py │ └── sgd_ta.py ├── artificial_example │ ├── README.md │ ├── target_algorithm.py │ └── wrapper.py └── dummy_wrapper │ ├── README.md │ └── dummy_wrapper.py ├── genericWrapper4AC ├── __init__.py ├── argparser │ ├── __init__.py │ └── parse.py ├── data │ ├── __init__.py │ └── data.py ├── domain_specific │ ├── __init__.py │ └── satwrapper.py └── generic_wrapper.py ├── runsolver ├── runsolver-3.3.4-patched │ └── src │ │ ├── Changelog │ │ ├── CircularBufferFilter.hh │ │ ├── Cores.hh │ │ ├── CreateSyscallsNames.cc │ │ ├── LICENSE-GPL-3.0.txt │ │ ├── Makefile │ │ ├── Makefile.back │ │ ├── Observer.hh │ │ ├── ProcessData.hh │ │ ├── ProcessHistory.hh │ │ ├── ProcessList.hh │ │ ├── ProcessTree.hh │ │ ├── README │ │ ├── SignalNames.cc │ │ ├── SignalNames.d │ │ ├── SignalNames.hh │ │ ├── SyscallNames.cc │ │ ├── SyscallNames.d │ │ ├── SyscallNames.hh │ │ ├── SyscallsTracer.hh │ │ ├── TimeStamper.hh │ │ ├── aeatk.c │ │ ├── runsolver │ │ ├── runsolver.cc │ │ ├── runsolver.d │ │ └── vlineSplitter.cc └── runsolver-3.4.0 │ └── src │ ├── Changelog │ ├── CircularBufferFilter.hh │ ├── Cores.hh │ ├── ExecutionSummary.hh │ ├── LICENSE-GPL-3.0.txt │ ├── Makefile │ ├── Observer.hh │ ├── ProcessData.hh │ ├── ProcessHistory.hh │ ├── ProcessList.hh │ ├── ProcessTree.hh │ ├── README │ ├── SignalNames.cc │ ├── SignalNames.d │ ├── SignalNames.hh │ ├── SignalNames.o │ ├── TimeStamper.hh │ ├── Watcher.hh │ ├── runsolver │ ├── runsolver.cc │ ├── runsolver.d │ ├── runsolver.o │ ├── server │ ├── Makefile │ ├── Makefile~ │ ├── server │ ├── server.cc │ └── server.cc~ │ └── vlineSplitter.cc ├── setup.py └── test ├── __init__.py ├── test_calls ├── __init__.py ├── test_calls.py └── test_checker.py └── test_resources ├── __init__.py ├── mem_str.py ├── pi.py └── test_limits.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.c text 7 | *.h text 8 | *.py text 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | test/test_binaries/ 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | 57 | # Sphinx documentation 58 | docs/_build/ 59 | 60 | # PyBuilder 61 | target/ 62 | 63 | #Ipython Notebook 64 | .ipynb_checkpoints 65 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | matrix: 4 | 5 | include: 6 | - os: linux 7 | env: PYTHON_VERSION="3.7" COVERAGE="true" MINICONDA_URL="https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh" 8 | 9 | cache: 10 | directories: 11 | - $HOME/.cache/pip 12 | pip: true 13 | 14 | sudo: false 15 | 16 | before_cache: 17 | - rm -f $HOME/.cache/pip/log/debug.log 18 | 19 | before_install: 20 | - sudo apt-get install -y libnuma-dev 21 | - wget $MINICONDA_URL -O miniconda.sh 22 | - bash miniconda.sh -b -p $HOME/miniconda 23 | - export PATH="$HOME/miniconda/bin:$PATH" 24 | - if [[ `which conda` ]]; then echo 'Conda installation successful'; else exit 1; fi 25 | - conda create -n testenv --yes python=$PYTHON_VERSION pip wheel nose #gxx_linux-64 gcc_linux-64 26 | - source activate testenv 27 | 28 | install: 29 | - pip install pep8 codecov 30 | - pip install nose numpy scipy scikit-learn 31 | - python setup.py install 32 | 33 | # command to run tests, e.g. python setup.py test 34 | script: 35 | - nosetests 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, the Contributors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Generic Wrapper for Algorithm Configuration 2 | 3 | The generic wrapper is a base class to easily implement your own interface between your algorithm and an algorithm configurator (such as ParamILS or SMAC). 4 | 5 | The generic wrapper is developed and maintained by members of the [AutoML](http://www.automl.org) Group at the University of Freiburg and the [Beta Lab](http://www.cs.ubc.ca/labs/beta/) of the university of British Columbia. 6 | 7 | Status for master branch: [![Build Status](https://travis-ci.org/automl/GenericWrapper4AC.svg?branch=master)](https://travis-ci.org/automl/GenericWrapper4AC) 8 | 9 | Status for dev branch: [![Build Status](https://travis-ci.org/automl/GenericWrapper4AC.svg?branch=dev)](https://travis-ci.org/automl/GenericWrapper4AC) 10 | 11 | ## INSTALLATION 12 | 13 | We provide a `setup.py` script which can be used to install generic wrapper as a package 14 | and which also installs all dependencies (including `runsolver`). 15 | 16 | ``` 17 | python setup.py install 18 | 19 | # To test installation run afterwards 20 | python setup.py test 21 | ``` 22 | 23 | NOTE: GenericWrapper4AC is also available on pypi but the installation of the runsolver fails using pip. We are still looking into this issue. 24 | 25 | ## USAGE 26 | 27 | The generic wrapper provides the interfaces to ParamILS and SMAC. Please see the [documentation of SMAC](http://www.cs.ubc.ca/labs/beta/Projects/SMAC/v2.10.03/manual.pdf) for an extensive description of the required interfaces. 28 | 29 | The script `generic_wrapper.py` provides the class `AbstractWrapper`. It provides all necessary functions to run your algorithms, including: 30 | 31 | * reading the input format of ParamILS and SMAC 32 | * limiting the resources (CPU and memory) by using the [runsolver](http://www.cril.univ-artois.fr/~roussel/runsolver/) 33 | * returning the output in ParamILS and SMAC format 34 | 35 | You have to implement only two functions 36 | 37 | * `get_command_line_args()` : given the parameter configuration, the instance at hand and the random seed, the function has to return the command line call of your algorithm (string) 38 | * `process_results()`: given the output of your algorithm, this function has to return a dictionary including the return status of your algorithm ("SUCCESS"|"TIMEOUT"|"CRASHED"|"ABORT") and the runtime/quality/cost of your algorithm run. 39 | 40 | See the docstrings and the examples for more details. 41 | 42 | ### NOTE 43 | 44 | For debugging reasons, the generic wrapper will not delete the output files of your algorithm if your algorithm crashed (or failed in any way). If your algorithm crashes very often, this can fill up your file system quickly. 45 | 46 | If your command line call includes "--config", the generic wrapper assumes that the new aclib call format will be used. 47 | 48 | ``` 49 | [] [] ... [--cutoff ] [--instance ] 50 | [--seed ] --config [-param_name_1 value_1] [-param_name_2 value_2] ... 51 | ``` 52 | 53 | ## Requirements 54 | 55 | Since we use the `runsolver` to limit resources, the generic wrapper can only be used on Linux systems. 56 | 57 | ## Examples 58 | 59 | Please see `./examples/` for some examples with black box functions (no problem instances included) and examples of algorithms with problem instances (i.e., SAT solving). 60 | Each example comes with its own README with further details. 61 | 62 | ## Troubleshooting 63 | 64 | ### Runsolver 65 | The current version of the GenericWrapper4AC uses the runsolver version 3.4.0. 66 | We provide a statically compiled binary. However, under certain circumstances (special kernels and so on), this static binary of the runsolver can fail. 67 | The setup script should check whether the runsolver can be at least called successfully. 68 | We recommend to also run the unit tests to verify that the runsolver is working properly. 69 | If there are any issues with the runsolver, we recommend to first recompile the runsolver (see `runsolver/runsolver-3.4.0/src`). 70 | If there are even further issues, please check whether a new version of the runsolver is available: `http://www.cril.univ-artois.fr/~roussel/runsolver/`. 71 | 72 | ## License 73 | 74 | The generic wrapper base class is published under a BSD license -- please see LICENSE for more details. 75 | The used runsolver was written by Olivier Roussel and is published under GPLv3.0 -- see `runsolver/` 76 | Please note that not all code provided in the examples are under a BSD license -- please check the license for these examples separately. 77 | 78 | ## Contributors 79 | 80 | * Marius Lindauer 81 | * Katharina Eggensperger 82 | * Chris Fawcett 83 | * Frank Hutter 84 | 85 | ## Reference 86 | 87 | If you use our generic wrapper in an academic context, please consider to cite our paper: 88 | 89 | ``` 90 | @article{eggensperger-jair19a, 91 | author = {K. Eggensperger and M. Lindauer and F. Hutter}, 92 | title = {Pitfalls and Best Practices in Algorithm Configuration}, 93 | journal = {Journal of Artificial Intelligence Research (JAIR)}, 94 | year = {2019}, 95 | volume = {64}, 96 | pages = {861-894} 97 | } 98 | ``` 99 | -------------------------------------------------------------------------------- /examples/MiniSAT/MiniSATWrapper.py: -------------------------------------------------------------------------------- 1 | import os 2 | from genericWrapper4AC.domain_specific.satwrapper import SatWrapper 3 | 4 | 5 | class MiniSATWrapper(SatWrapper): 6 | 7 | 8 | def get_command_line_args(self, runargs, config): 9 | ''' 10 | @contact: lindauer@informatik.uni-freiburg.de, fh@informatik.uni-freiburg.de 11 | Returns the command line call string to execute the target algorithm (here: Spear). 12 | Args: 13 | runargs: a map of several optional arguments for the execution of the target algorithm. 14 | { 15 | "instance": , 16 | "specifics" : , 17 | "cutoff" : , 18 | "runlength" : , 19 | "seed" : 20 | } 21 | config: a mapping from parameter name to parameter value 22 | Returns: 23 | A command call list to execute the target algorithm. 24 | ''' 25 | solver_binary = os.path.join(os.path.dirname(__file__), "minisat") 26 | cmd = "%s -rnd-seed=%d" %(solver_binary, runargs["seed"]) 27 | for name, value in config.items(): 28 | cmd += " %s=%s" %(name, value) 29 | cmd += " %s" %(runargs["instance"]) 30 | 31 | return cmd 32 | 33 | if __name__ == "__main__": 34 | wrapper = MiniSATWrapper() 35 | wrapper.main() 36 | -------------------------------------------------------------------------------- /examples/MiniSAT/README.md: -------------------------------------------------------------------------------- 1 | #Example for using the Generic Wrapper for MiniSAT 2 | 3 | This example shows how we used the generic wrapper in the Configurable SAT Solver Challenge (CSSC). 4 | As a SAT solver, we use here the well-known solver [MiniSAT](http://minisat.se/). 5 | 6 | As a general interface to SAT solvers, we provide the class `genericWrapper4AC.domain_specific.satwrapper`. 7 | 8 | For a new SAT solver, only a single function needs to be implemented: `get_command_line_args()` 9 | that generates the call string given an instance, a configuration and a cutoff time. 10 | 11 | The following, SAT-specific function is already implemented, `process_results()`: 12 | 13 | 1. Reading the output file of the solver 14 | 1. Searches for `SATISFIABLE` or `UNSATISFIABLE` and checks the result if possible. 15 | 1. `SATISFIABLE` can be checked with one of the following ways: 16 | * With the option `--sat-checker`, you can provide the binary of the SAT checker tool from the SAT competition; this will explicitly check the returned variable assignment. 17 | * With the option `--sol-file`, you provide a CSV file (whitespace separated) that includes an entry for each instance in the format ` ` 18 | * The instance specific is set to either `SAT` or `UNSAT` 19 | 1. `UNSATISFIABLE` can be checked with the two latter ways of checking `SATISFIABLE` 20 | 21 | An example call for minisat could the be following: 22 | 23 | `python examples/MiniSAT/MiniSATWrapper.py examples/MiniSAT/gzip_vc1071.cnf SAT 10 0 42 -rnd-freq 0 -var-decay 0.001 -cla-decay 0.001 -gc-frac 0.000001 -rfirst 1000` 24 | 25 | This will run `MiniSat` on the instance `gzip_vc1071.cnf`, assuming that it is a `SATISFIABLE` instance, using at most 10 CPU seconds and a random seed of 42. This will be translated in the following call: 26 | 27 | `examples/MiniSAT/minisat -rnd-seed=42 -cla-decay=0.001 -var-decay=0.001 -gc-frac=0.000001 -rfirst=1000 -rnd-freq=0 examples/MiniSAT/gzip_vc1071.cnf` 28 | 29 | The output of the wrapper call will include: 30 | 31 | `Result for ParamILS: SUCCESS, 0.004, -1, -1, 42, SAT checker was not given; could not verify SAT` 32 | 33 | With this line, ParamILS/SMAC will know that `MiniSat` returned successfully and needed 0.004 CPU seconds. 34 | 35 | The alternative call in the new format would be 36 | 37 | `python examples/MiniSAT/MiniSATWrapper.py --instance examples/MiniSAT/gzip_vc1071.cnf --cutoff 10 --seed 42 --config -rnd-freq 0 -var-decay 0.001 -cla-decay 0.001 -gc-frac 0.000001 -rfirst 1000` 38 | -------------------------------------------------------------------------------- /examples/MiniSAT/minisat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/examples/MiniSAT/minisat -------------------------------------------------------------------------------- /examples/SGD/README.md: -------------------------------------------------------------------------------- 1 | #Wrapper for SGD 2 | 3 | This is a more advanced example for optimizing a black box function (here SGD on a fixed data set) which has an additional requirement: scikit-learn. 4 | 5 | The target algorithm is a simple python script `sgd_ta.py` which loads the iris data set from scikit-learn, reads the parameter configuration, fits a SGD classifier and prints the accuracy on a holdout set. 6 | 7 | The script supports three kind of "instances": 8 | 9 | 1. if the instance is "train", we split the data into train, validation and test set, and train SGD on train and evaluate it on valid 10 | 2. if the instance is "test", we split the data into train (train+validation) and test set, and train SGD on train and evaluate it on test 11 | 3. if the instance is "cvX", we split the data into train and test, and further use a k-fold CV on train; the X-th split is used for training and evaluation 12 | 13 | The `SGDWrapper.py` implements the required two functions: 14 | 15 | 1. `get_command_line_args()` that generates the command line call by starting with the call of the sgd script, adds the random seed as a parameter called `random_state` (as done in sklearn) and adds all parameters to the command line call 16 | 1. `process_results()` reads only the printed accuracy from the `sgd_ta.py` script and returns it as the quality of the function. 17 | 18 | An example call of the wrapper would be: 19 | 20 | `python examples/SGD/SGDWrapper.py train 0 5 0 9 -learning_rate constant -eta0 1 -loss hinge -penalty l2 -alpha 0.0001 -learning_rate optimal -eta0 0.0 -n_iter 2` 21 | 22 | which is translated to 23 | 24 | `python examples/SGD/sgd_ta.py train random_state 9 learning_rate optimal eta0 0.0 loss hinge penalty l2 alpha 0.0001 n_iter 2` 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/SGD/SGDWrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # encoding: utf-8 3 | 4 | ''' 5 | SGDWrapper -- Simple wrapper around an external script for SGD 6 | 7 | @author: Marius Lindauer 8 | @copyright: 2016 ML4AAD. All rights reserved. 9 | @license: BSD 10 | @contact: lindauer@informatik.uni-freiburg.de 11 | ''' 12 | 13 | import sys 14 | import re 15 | import math 16 | import logging 17 | 18 | from genericWrapper4AC.generic_wrapper import AbstractWrapper 19 | 20 | class SGDWrapper(AbstractWrapper): 21 | ''' 22 | Simple wrapper for an external SDG script 23 | ''' 24 | 25 | def __init__(self): 26 | logging.basicConfig() 27 | AbstractWrapper.__init__(self) 28 | 29 | self._return_value = None 30 | 31 | def get_command_line_args(self, runargs, config): 32 | ''' 33 | Returns the command line call string to execute the target algorithm (here: Spear). 34 | Args: 35 | runargs: a map of several optional arguments for the execution of the target algorithm. 36 | { 37 | "instance": , 38 | "specifics" : , 39 | "cutoff" : , 40 | "runlength" : , 41 | "seed" : 42 | } 43 | config: a mapping from parameter name to parameter value 44 | Returns: 45 | A command call list to execute the target algorithm. 46 | ''' 47 | cmd = "python examples/SGD/sgd_ta.py %s random_state %d " %(runargs["instance"], runargs["seed"]) 48 | cmd += " ".join(["%s %s" %(name[1:], value) for name, value in config.items()]) 49 | 50 | return cmd 51 | 52 | def process_results(self, filepointer, exit_code): 53 | ''' 54 | Parse a results file to extract the run's status (SUCCESS/CRASHED/etc) and other optional results. 55 | 56 | Args: 57 | filepointer: a pointer to the file containing the solver execution standard out. 58 | exit_code : exit code of target algorithm 59 | Returns: 60 | A map containing the standard AClib run results. The current standard result map as of AClib 2.06 is: 61 | { 62 | "status" : <"SAT"/"UNSAT"/"TIMEOUT"/"CRASHED"/"ABORT">, 63 | "runtime" : , 64 | "quality" : , 65 | "misc" : 66 | } 67 | ATTENTION: The return values will overwrite the measured results of the runsolver (if runsolver was used). 68 | ''' 69 | 70 | self.logger.debug("reading solver results from %s" % (filepointer.name)) 71 | 72 | # If solver result file is empty, we also assume a crash 73 | resultMap = {'status': 'CRASHED', 74 | 'quality': 1 # assumption minimization 75 | } 76 | for line in filepointer: 77 | try: 78 | out_ = str(line.decode('UTF-8')).replace("\n","") 79 | return_value = float(out_) 80 | resultMap = {'status' : 'SUCCESS', 81 | 'quality' : return_value 82 | } 83 | return resultMap 84 | except ValueError: 85 | pass 86 | 87 | return resultMap 88 | 89 | 90 | if __name__ == "__main__": 91 | wrapper = SGDWrapper() 92 | wrapper.main() 93 | -------------------------------------------------------------------------------- /examples/SGD/sgd_ta.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # encoding: utf-8 3 | 4 | ''' 5 | sgd_ta -- script to fit and evaluate SGD wrt a given configuration 6 | 7 | @author: Marius Lindauer 8 | @copyright: 2016 ML4AAD. All rights reserved. 9 | @license: BSD 10 | @contact: lindauer@informatik.uni-freiburg.de 11 | ''' 12 | 13 | import sys 14 | 15 | from sklearn.linear_model import SGDClassifier 16 | from sklearn.datasets import load_iris, load_digits 17 | from sklearn.model_selection import train_test_split, KFold 18 | 19 | data = load_iris() 20 | #data = load_digits() 21 | 22 | if sys.argv[1] == "train": 23 | X_train_f, X_test, y_train_f, y_test = train_test_split(data.data, data.target, test_size=0.25, random_state=0) 24 | X_train, X_valid, y_train, y_valid = train_test_split(X_train_f, y_train_f, test_size=0.25, random_state=0) 25 | elif sys.argv[1] == "test": 26 | X_train_f, X_test, y_train_f, y_test = train_test_split(data.data, data.target, test_size=0.25, random_state=0) 27 | elif sys.argv[1][:2] == "cv": 28 | X_train_f, X_test, y_train_f, y_test = train_test_split(data.data, data.target, test_size=0.25, random_state=0) 29 | kf = KFold(n_splits=10, shuffle=True, random_state=1) 30 | kfs = [kf for kf in kf.split(X_train_f)] 31 | cv = int(sys.argv[1][2:]) - 1 32 | X_train = X_train_f[kfs[cv][0]] 33 | y_train = y_train_f[kfs[cv][0]] 34 | X_valid = X_train_f[kfs[cv][1]] 35 | y_valid = y_train_f[kfs[cv][1]] 36 | 37 | params = iter(sys.argv[2:]) 38 | 39 | while True: 40 | try: 41 | name = next(params) 42 | except StopIteration: 43 | break 44 | value = next(params) 45 | 46 | if name == "random_state": 47 | random_state = int(value)+1 48 | 49 | elif name == "loss": 50 | loss = str(value) 51 | 52 | elif name == "penalty": 53 | penalty = str(value) 54 | 55 | elif name == "alpha": 56 | alpha = float(value) 57 | 58 | elif name == "learning_rate": 59 | learning_rate = str(value) 60 | 61 | elif name == "eta0": 62 | eta0 = float(value) 63 | 64 | elif name == "n_iter": 65 | n_iter = int(value) 66 | 67 | sgd = SGDClassifier(random_state=random_state, 68 | loss=loss, 69 | penalty=penalty, 70 | alpha=alpha, 71 | learning_rate=learning_rate, 72 | eta0=eta0, 73 | max_iter=n_iter) 74 | 75 | #print(sgd.loss, sgd.penalty, sgd.alpha, sgd.learning_rate, sgd.eta0) 76 | 77 | if sys.argv[1] == "train" or sys.argv[1][:2] == "cv": 78 | sgd.fit(X_train,y_train) 79 | print(-1 * sgd.score(X_valid, y_valid)) 80 | else: 81 | sgd.fit(X_train_f,y_train_f) 82 | print(-1 * sgd.score(X_test, y_test)) 83 | 84 | 85 | -------------------------------------------------------------------------------- /examples/artificial_example/README.md: -------------------------------------------------------------------------------- 1 | # Test Wrapper 2 | 3 | This is a basic example for a simple artificial function to show the features of the generic wrapper. 4 | Furthermore, this example should be useful for testing the generic wrapper and compatible algorithm configurators. 5 | 6 | The target algorithm is a simple python script `target_algorithm.py` 7 | which parses three parameters. In the pcs format, this would correspond to: 8 | 9 | ``` 10 | str_param categorical {str1,str2}[str2] 11 | int_param integer [1,100][1] 12 | float_param float [0,1][0.1] 13 | ``` 14 | 15 | The script supports pseudo instances in the format `inst:`, where `hardness` is parsed as an integer and multiplied to the final result. 16 | 17 | The random seed is used for letting the target algorithm sleep for `int(seed)/100` seconds. 18 | Since it is only a sleep and the generic wrapper measures CPU time by default, 19 | the random see will change the wallclock time, but not the returned CPU time. 20 | 21 | The `wrapper.py` implements the required two functions: 22 | 23 | 1. `get_command_line_args()` that generates the command line call by starting with the call of the target algorithm script, adds the random seed as the second parameter and adds all parameters to the command line call 24 | 1. `process_results()` reads only the printed value from the `target_algorithm.py` script and returns it as the quality of the function. 25 | 26 | An example call of the wrapper would be: 27 | 28 | `python examples/artificial_example/wrapper.py --seed 10 --instance inst:10 --config -float_param 0.1 -int_param 2 -str_param str2` 29 | 30 | which is translated to 31 | 32 | `python examples/artificial_example/target_algorithm.py inst:10 10 float_param 0.1 int_param 2 str_param str2` 33 | 34 | The expected output should include a line such as: 35 | 36 | `Result of this algorithm run: {"status": "SUCCESS", "cost": 41.0, "runtime": 0.038031, "misc": ""}` 37 | 38 | where the measured CPU time can vary slightly. -------------------------------------------------------------------------------- /examples/artificial_example/target_algorithm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # encoding: utf-8 3 | 4 | ''' 5 | target_algorithm -- script to emulate a target algorithm (only for testing purpose) 6 | 7 | @author: Marius Lindauer 8 | @copyright: 2018 ML4AAD. All rights reserved. 9 | @license: BSD 10 | @contact: lindauer@informatik.uni-freiburg.de 11 | ''' 12 | 13 | import sys, time 14 | 15 | # instance format: inst: 16 | inst_ = sys.argv[1] 17 | hardness = int(inst_.split(":")[1]) 18 | 19 | # seed 20 | seed = int(sys.argv[2]) 21 | 22 | params = iter(sys.argv[3:]) 23 | 24 | str_dict = {"str1": 1, 25 | "str2": 2} 26 | x1, x2, x3 = 0, 0, 0 27 | 28 | while True: 29 | try: 30 | name = next(params) 31 | except StopIteration: 32 | break 33 | value = next(params) 34 | 35 | if name == "int_param": 36 | x1 = int(value) 37 | 38 | elif name == "float_param": 39 | x2 = float(value) 40 | 41 | elif name == "str_param": 42 | x3 = str_dict.get(value, 0) 43 | 44 | time.sleep(seed/100) 45 | 46 | print("%f" %((x1+x2+x3)*hardness)) 47 | 48 | -------------------------------------------------------------------------------- /examples/artificial_example/wrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # encoding: utf-8 3 | 4 | ''' 5 | SGDWrapper -- Simple wrapper around an external script for SGD 6 | 7 | @author: Marius Lindauer 8 | @copyright: 2018 ML4AAD. All rights reserved. 9 | @license: BSD 10 | @contact: lindauer@informatik.uni-freiburg.de 11 | ''' 12 | 13 | import sys 14 | import re 15 | import math 16 | import logging 17 | 18 | from genericWrapper4AC.generic_wrapper import AbstractWrapper 19 | 20 | class ArtWrapper(AbstractWrapper): 21 | ''' 22 | Simple wrapper for an external artificial script 23 | ''' 24 | 25 | def __init__(self): 26 | logging.basicConfig() 27 | AbstractWrapper.__init__(self) 28 | 29 | self._return_value = None 30 | 31 | def get_command_line_args(self, runargs, config): 32 | ''' 33 | Returns the command line call string to execute the target algorithm (here: Spear). 34 | Args: 35 | runargs: a map of several optional arguments for the execution of the target algorithm. 36 | { 37 | "instance": , 38 | "specifics" : , 39 | "cutoff" : , 40 | "runlength" : , 41 | "seed" : 42 | } 43 | config: a mapping from parameter name to parameter value 44 | Returns: 45 | A command call list to execute the target algorithm. 46 | ''' 47 | cmd = "python examples/artificial_example/target_algorithm.py %s %d " %(runargs["instance"], runargs["seed"]) 48 | cmd += " ".join(["%s %s" %(name[1:], value) for name, value in config.items()]) 49 | 50 | return cmd 51 | 52 | def process_results(self, filepointer, exit_code): 53 | ''' 54 | Parse a results file to extract the run's status (SUCCESS/CRASHED/etc) and other optional results. 55 | 56 | Args: 57 | filepointer: a pointer to the file containing the solver execution standard out. 58 | exit_code : exit code of target algorithm 59 | Returns: 60 | A map containing the standard AClib run results. The current standard result map as of AClib 2.06 is: 61 | { 62 | "status" : <"SAT"/"UNSAT"/"TIMEOUT"/"CRASHED"/"ABORT">, 63 | "runtime" : , 64 | "quality" : , 65 | "misc" : 66 | } 67 | ATTENTION: The return values will overwrite the measured results of the runsolver (if runsolver was used). 68 | ''' 69 | 70 | self.logger.debug("reading solver results from %s" % (filepointer.name)) 71 | 72 | # If solver result file is empty, we also assume a crash 73 | resultMap = {'status': 'CRASHED', 74 | 'quality': 1 # assumption minimization 75 | } 76 | for line in filepointer: 77 | try: 78 | out_ = str(line.decode('UTF-8')).replace("\n","") 79 | return_value = float(out_) 80 | resultMap = {'status' : 'SUCCESS', 81 | 'quality' : return_value 82 | } 83 | return resultMap 84 | except ValueError: 85 | pass 86 | 87 | return resultMap 88 | 89 | 90 | if __name__ == "__main__": 91 | wrapper = ArtWrapper() 92 | wrapper.main() 93 | -------------------------------------------------------------------------------- /examples/dummy_wrapper/README.md: -------------------------------------------------------------------------------- 1 | # Example call I) 2 | 3 | `python examples/dummy_wrapper/dummy_wrapper.py --cutoff 12 --instance cost+time --seed 44 --config -cost 2 -runtime 5` 4 | 5 | Expected output: 6 | 7 | `Result of this algorithm run: {"status": "SUCCESS", "cost": 2.0, "runtime": 5.0, "misc": ""}` 8 | 9 | # Example call II) 10 | 11 | `python examples/dummy_wrapper/dummy_wrapper.py --cutoff 12 --instance time --seed 45 --config -cost 2 -runtime 50` 12 | 13 | Expected output: 14 | 15 | `Result of this algorithm run: {"status": "TIMEOUT", "cost": 12.0, "runtime": 12.0, "misc": ""}` 16 | 17 | # Example call III) 18 | 19 | `python examples/dummy_wrapper/dummy_wrapper.py --cutoff 12 --instance time --seed 44 --config -cost 20 -runtime 50` 20 | 21 | Expected output: 22 | 23 | `Result of this algorithm run: {"status": "SUCCESS", "cost": 12.0, "runtime": 12.0, "misc": ""}` 24 | 25 | # Example call IV) 26 | 27 | `python examples/dummy_wrapper/dummy_wrapper.py --cutoff 12 --instance time --seed 46 --config -cost 20 -runtime 50` 28 | 29 | Expected output: 30 | 31 | `Result of this algorithm run: {"status": "CRASHED", "cost": 12.0, "runtime": 12.0, "misc": "; Problem with run. Exit code was N/A.; Preserving runsolver output at XXX - preserving target algorithm output at XXX"}` 32 | 33 | # Example call V) 34 | 35 | `python examples/dummy_wrapper/dummy_wrapper.py --cutoff 12 --instance time --seed 47 --config -cost 20 -runtime 50` 36 | 37 | Expected output: 38 | 39 | `Result of this algorithm run: {"status": "ABORT", "cost": 12.0, "runtime": 12.0, "misc": "; Problem with run. Exit code was N/A.; Preserving runsolver output at XXX - preserving target algorithm output at XXX"}` 40 | 41 | # Example call VI) 42 | 43 | `python examples/dummy_wrapper/dummy_wrapper.py --cutoff 12 --instance cost --seed 48 --config -cost 20 -runtime 50` 44 | 45 | Expected output: 46 | 47 | `Result of this algorithm run: {"status": "SUCCESS", "cost": 20.0, "runtime": 0.000515, "misc": ""}` 48 | -------------------------------------------------------------------------------- /examples/dummy_wrapper/dummy_wrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # encoding: utf-8 3 | 4 | ''' 5 | DummyWrapper -- Dummy wrapper for unit testing 6 | 7 | This requires the installation of https://github.com/automl/GenericWrapper4AC 8 | 9 | @author: Manuel López-Ibáñez 10 | @copyright: 2018 11 | @license: BSD 12 | @contact: manuel.lopez-ibanez@manchester.ac.uk 13 | ''' 14 | 15 | import json 16 | import traceback 17 | 18 | from genericWrapper4AC.generic_wrapper import AbstractWrapper 19 | 20 | class DummyWrapper(AbstractWrapper): 21 | ''' 22 | Dummy wrapper for unit testing 23 | ''' 24 | 25 | def __init__(self): 26 | AbstractWrapper.__init__(self) 27 | self._return_value = None 28 | 29 | def get_command_line_args(self, runargs, config): 30 | ''' 31 | ''' 32 | runargs.update(config) 33 | return "echo '" + json.dumps(runargs) + "'" 34 | 35 | def process_results(self, filepointer, exit_code): 36 | ''' 37 | Parse a results file to extract the run's status (SUCCESS/CRASHED/etc) and other optional results. 38 | 39 | Args: 40 | filepointer: a pointer to the file containing the solver execution standard out. 41 | exit_code : exit code of target algorithm 42 | ''' 43 | 44 | statuses = ['SUCCESS', 'TIMEOUT', 'CRASHED', 'ABORT'] 45 | 46 | # If something fails, we a serious problem 47 | output = dict(status='ABORT') 48 | for line in filepointer: 49 | try: 50 | argmap = json.loads(str(line.decode('UTF-8')).replace("\n","")) 51 | ins = argmap["instance"] 52 | seed = argmap["seed"] 53 | cost = float(argmap["-cost"]) 54 | runtime = float(argmap["-runtime"]) 55 | status = statuses[seed % len(statuses)] 56 | if ins == "cost": 57 | output = dict(status = status, cost = cost) 58 | elif ins == "time": 59 | cutoff = float(argmap["cutoff"]) 60 | output = dict(status=status, runtime=min(cutoff,runtime)) 61 | elif ins == "cost+time": 62 | cutoff = float(argmap["cutoff"]) 63 | output = dict(status=status, cost=cost, runtime=min(cutoff,runtime)) 64 | except ValueError: 65 | traceback.print_exc() 66 | pass 67 | 68 | return output 69 | 70 | 71 | if __name__ == "__main__": 72 | wrapper = DummyWrapper() 73 | wrapper.main() 74 | -------------------------------------------------------------------------------- /genericWrapper4AC/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/genericWrapper4AC/__init__.py -------------------------------------------------------------------------------- /genericWrapper4AC/argparser/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/genericWrapper4AC/argparser/__init__.py -------------------------------------------------------------------------------- /genericWrapper4AC/argparser/parse.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @author: Marius Lindauer 3 | @copyright: 2018 ML4AAD. All rights reserved. 4 | @license: BSD 5 | ''' 6 | 7 | 8 | import os 9 | import typing 10 | import genericWrapper4AC 11 | 12 | from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, SUPPRESS 13 | 14 | from genericWrapper4AC.data.data import Data 15 | 16 | 17 | def get_parser(): 18 | ''' 19 | Creates an ArgumentParser object 20 | and adds the general arguments, such as runsolver-path, temp-file-dir, mem-limit, max_quality 21 | ''' 22 | 23 | parser = ArgumentParser( 24 | formatter_class=ArgumentDefaultsHelpFormatter, allow_abbrev=False, 25 | add_help=False) 26 | 27 | parser.add_argument("--runsolver-path", dest="runsolver", default=os.path.join(genericWrapper4AC.__path__[ 28 | 0], "binaries", "runsolver"), help="path to runsolver binary (if None, the runsolver is deactivated)") 29 | parser.add_argument("--temp-file-dir", dest="tmp_dir", default=None, 30 | help="directory for temporary files of runsolver (relative to -exec-dir in SMAC scenario)") 31 | parser.add_argument("--mem-limit", dest="mem_limit", 32 | default=3072, type=int, help="memory limit in MB") 33 | parser.add_argument("--max_quality", dest="max_quality", default=None, 34 | help="maximal quality of unsuccessful runs with timeouts or crashes") 35 | parser.add_argument("--overwrite_cost_runtime", dest="overwrite_cost_runtime", default=False, 36 | action="store_true", 37 | help="overwrite cost field with runtime field") 38 | # deactivate -h such that 'h' can be a parameter of the target algorithm 39 | parser.add_argument('--help', action='help', default=SUPPRESS, 40 | help='Show this help message and exit.') 41 | 42 | return parser 43 | 44 | 45 | def get_extended_parser(parser:ArgumentParser): 46 | ''' 47 | Extends the parser created in get_parser by optional arguments supported 48 | in the new aclib format 49 | 50 | Arguments 51 | parser: Argumentparser 52 | ''' 53 | 54 | parser.add_argument("--instance", dest="instance", 55 | default=None, help="path to instance") 56 | parser.add_argument("--cutoff", dest="cutoff", default=None, 57 | type=float, help="running time cutoff") 58 | parser.add_argument("--seed", dest="seed", default=None, 59 | type=int, help="random seed") 60 | 61 | return parser 62 | 63 | def parse(cmd_arguments: typing.List[str], parser:ArgumentParser): 64 | ''' 65 | use parser from get_*parser() to parse 66 | 67 | Arguments 68 | --------- 69 | cmd_arguments: typing.List[str] 70 | command line arguments 71 | parser: ArgumentParser 72 | parser 73 | 74 | Returns 75 | ------- 76 | d: ~genericWrapper4AC.data.data.Data 77 | main_args: Namespace 78 | required for backward compatibility 79 | ''' 80 | 81 | new_format = False 82 | if "--config" in cmd_arguments: 83 | new_format = True 84 | parser = get_extended_parser(parser=parser) 85 | 86 | main_args, target_args = parser.parse_known_args(cmd_arguments[1:]) 87 | 88 | if new_format: 89 | d = parse_config_new(main_args=main_args, target_args=target_args) 90 | else: 91 | d = parse_config_old(main_args=main_args, target_args=target_args) 92 | 93 | d.runsolver = main_args.runsolver 94 | d.tmp_dir = main_args.tmp_dir 95 | d.mem_limit = main_args.mem_limit 96 | if main_args.max_quality is not None: 97 | d.max_quality = main_args.max_quality 98 | 99 | d.new_format = new_format 100 | 101 | return d, main_args 102 | 103 | 104 | def parse_config_old(main_args, target_args: typing.List[str]): 105 | ''' 106 | creates Data() object and fills it with parsed command line arguments 107 | using the old call format 108 | 109 | Arguments 110 | -------- 111 | main_args: Namespace 112 | arguments parsed by argparse 113 | target_args: typing.List[str] 114 | arguments not parsed so far 115 | 116 | Returns 117 | ------- 118 | d: ~genericWrapper4AC.data.data.Data 119 | ''' 120 | 121 | d = Data() 122 | 123 | d.instance = target_args[0] 124 | d.specifics = target_args[1] 125 | # runsolver only rounds down to integer 126 | d.cutoff = int(float(target_args[2]) + 1 - 1e-10) 127 | d.cutoff = min(d.cutoff, 2**31 - 1) # at most 32bit integer supported 128 | d.time = d.cutoff 129 | d.runlength = int(target_args[3]) 130 | d.seed = int(target_args[4]) 131 | d.config = target_args[5:] 132 | d.config = dict((name, value.strip("'")) 133 | for name, value in zip(d.config[::2], d.config[1::2])) 134 | 135 | return d 136 | 137 | 138 | def parse_config_new(main_args, target_args: typing.List[str]): 139 | ''' 140 | creates Data() object and fills it with parsed command line arguments 141 | using the new ACLib2 call format 142 | 143 | Arguments 144 | -------- 145 | main_args: Namespace 146 | arguments parsed by argparse 147 | target_args: typing.List[str] 148 | arguments not parsed so far 149 | 150 | Returns 151 | ------- 152 | d: ~genericWrapper4AC.data.data.Data 153 | ''' 154 | 155 | d = Data() 156 | 157 | d.instance = main_args.instance 158 | # runsolver only rounds down to integer 159 | if main_args.cutoff is not None: 160 | d.cutoff = int(main_args.cutoff + 1 - 1e-10) 161 | d.cutoff = min(d.cutoff, 2**31 - 1) # at most 32bit integer supported 162 | d.time = d.cutoff 163 | d.seed = main_args.seed 164 | 165 | d.config = target_args[target_args.index("--config") + 1:] 166 | d.config = dict((name, value.strip("'")) 167 | for name, value in zip(d.config[::2], d.config[1::2])) 168 | 169 | return d 170 | -------------------------------------------------------------------------------- /genericWrapper4AC/data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/genericWrapper4AC/data/__init__.py -------------------------------------------------------------------------------- /genericWrapper4AC/data/data.py: -------------------------------------------------------------------------------- 1 | ''' 2 | @author: Marius Lindauer 3 | @copyright: 2018 ML4AAD. All rights reserved. 4 | @license: BSD 5 | ''' 6 | 7 | class Data(object): 8 | 9 | def __init__(self): 10 | 11 | self.instance = None 12 | self.specifics = None 13 | self.cutoff = None 14 | self.runlength = None 15 | self.seed = None 16 | self.config = [] 17 | 18 | # return values 19 | self.status = "CRASHED" 20 | self.cost = 2**32 - 1 21 | self.time = 0 22 | self.additional = "" 23 | self.exit_code = 0 24 | 25 | # call arguments 26 | self.runsolver = None 27 | self.tmp_dir = None 28 | self.mem_limit = None 29 | self.max_quality = 2**32 - 1 30 | 31 | self.new_format = False 32 | -------------------------------------------------------------------------------- /genericWrapper4AC/domain_specific/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/genericWrapper4AC/domain_specific/__init__.py -------------------------------------------------------------------------------- /genericWrapper4AC/domain_specific/satwrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | # encoding: utf-8 3 | 4 | ''' 5 | SATCSSCWrapper -- target algorithm wrapper for SAT solvers 6 | 7 | @author: Marius Lindauer 8 | @copyright: 2016 Ml4AAD. All rights reserved. 9 | @license: BSD 10 | @contact: lindauer@informatik.uni-freiburg.de 11 | ''' 12 | 13 | import sys 14 | import re 15 | import os 16 | import imp 17 | import logging 18 | from subprocess import Popen, PIPE 19 | 20 | from genericWrapper4AC.generic_wrapper import AbstractWrapper 21 | 22 | class SatWrapper(AbstractWrapper): 23 | ''' 24 | General wrapper for a SAT solver 25 | ''' 26 | 27 | def __init__(self): 28 | ''' 29 | Constructor 30 | ''' 31 | logging.basicConfig() 32 | AbstractWrapper.__init__(self) 33 | 34 | self.parser.add_argument("--sol-file", dest="solubility_file", default=None, help="File with \" {SATISFIABLE|UNSATISFIABLE|UNKNOWN}\" ") 35 | self.parser.add_argument("--sat-checker", dest="sat_checker", default=None, help="binary of SAT checker") 36 | 37 | self._instance = "" 38 | self._instance = "" 39 | 40 | self.inst_specific = None 41 | 42 | def process_results(self, filepointer, exit_code): 43 | ''' 44 | Parse a results file to extract the run's status (SUCCESS/CRASHED/etc) and other optional results. 45 | 46 | Args: 47 | filepointer: a pointer to the file containing the solver execution standard out. 48 | exit_code : exit code of target algorithm 49 | Returns: 50 | A map containing the standard AClib run results. The current standard result map as of AClib 2.06 is: 51 | { 52 | "status" : <"SAT"/"UNSAT"/"TIMEOUT"/"CRASHED"/"ABORT">, 53 | "runtime" : , 54 | "quality" : , 55 | "misc" : 56 | } 57 | ATTENTION: The return values will overwrite the measured results of the runsolver (if runsolver was used). 58 | ''' 59 | self.logger.debug("reading solver results from %s" % (filepointer.name)) 60 | data = filepointer.read() 61 | try: 62 | data = str(data.decode("utf8")) 63 | except AttributeError: 64 | pass 65 | 66 | resultMap = {} 67 | 68 | resultMap['misc'] = "" 69 | 70 | if re.search('UNSATISFIABLE', data): 71 | resultMap['status'] = 'UNSAT' 72 | 73 | # verify UNSAT via external knowledge 74 | if self.data.specifics in ["SAT", "10", "SATISFIABLE"]: 75 | resultMap['status'] = 'CRASHED' 76 | resultMap['misc'] = "according to instance specific, instance is SAT but UNSAT was reported" 77 | elif not self.args.solubility_file: 78 | resultMap['misc'] += "; solubility file was not given; could not verify UNSAT" 79 | elif not os.path.isfile(self.args.solubility_file): 80 | resultMap['misc'] += "; have not found %s; could not verify UNSAT" % (self.args.solubility_file) 81 | elif not self._verify_via_solubility_file(sol="UNSAT"): # use solubility file 82 | resultMap['status'] = 'CRASHED' 83 | resultMap['misc'] += "; according to solubility file, instance is SAT but UNSAT was reported" 84 | 85 | elif re.search('SATISFIABLE', data): 86 | resultMap['status'] = 'SAT' 87 | 88 | # look for model 89 | model = None 90 | for line in data.split("\n"): 91 | if line.startswith("v "): 92 | model = map(int, line.split(" ")[1:-1]) 93 | break 94 | 95 | # verify SAT 96 | if self.data.specifics in ["UNSAT", "20", "UNSATISFIABLE"] : 97 | resultMap['status'] = 'CRASHED' 98 | resultMap['misc'] = "; according to instance specific, instance is UNSAT but SAT was reported" 99 | elif not self.args.solubility_file: 100 | resultMap['misc'] += "; solubility file was not given; could not verify SAT" 101 | elif not os.path.isfile(self.args.solubility_file): 102 | resultMap['misc'] += "; have not found %s; could not verify SAT" % (self.args.solubility_file) 103 | elif not self._verify_via_solubility_file(sol="SAT"): # use solubility file 104 | resultMap['status'] = 'CRASHED' 105 | resultMap['misc'] += "; according to solubility file, instance is UNSAT but SAT was reported" 106 | 107 | 108 | if not self.args.sat_checker: 109 | resultMap['misc'] += "; SAT checker was not given; could not verify SAT" 110 | elif not os.path.isfile(self.args.sat_checker): 111 | resultMap['misc'] += "; have not found %s; could not verify SAT" % (self.args.sat_checker) 112 | elif model is None: 113 | resultMap['misc'] += "; print of solution was probably incomplete because of runsolver SIGTERM/SIGKILL" 114 | resultMap['status'] = 'TIMEOUT' 115 | elif not self._verify_SAT(model, filepointer): 116 | # fix: race condition between SIGTERM of runsolver and print of solution 117 | if self.data.status == "TIMEOUT": 118 | resultMap['status'] = 'TIMEOUT' 119 | resultMap['misc'] = 'print of solution was probably incomplete because of runsolver SIGTERM/SIGKILL' 120 | else: 121 | resultMap['status'] = 'CRASHED' 122 | resultMap['misc'] = "SOLVER BUG: solver returned a wrong model" 123 | # save command line call 124 | 125 | elif re.search('s UNKNOWN', data): 126 | resultMap['status'] = 'TIMEOUT' 127 | resultMap['misc'] = "Found s UNKNOWN line - interpreting as TIMEOUT" 128 | elif re.search('INDETERMINATE', data): 129 | resultMap['status'] = 'TIMEOUT' 130 | resultMap['misc'] = "Found INDETERMINATE line - interpreting as TIMEOUT" 131 | 132 | return resultMap 133 | 134 | def _verify_SAT(self, model, solver_output): 135 | ''' 136 | verifies the model for self._instance 137 | Args: 138 | model : list with literals 139 | solver_output: filepointer to solver output 140 | Returns: 141 | True if model was correct 142 | False if model was not correct 143 | ''' 144 | cmd = [self.args.sat_checker, self._instance, solver_output.name] 145 | io = Popen(cmd, stdout=PIPE, universal_newlines=True) 146 | out_, err_ = io.communicate() 147 | for line in out_.split("\n"): 148 | if "Solution verified" in line: 149 | self.logger.debug("Solution verified") 150 | return True 151 | elif "Wrong solution" in line: 152 | return False 153 | return True # should never happen 154 | 155 | def _verify_via_solubility_file(self, sol): 156 | ''' 157 | looks in whether it is already known that the instance is UNSAT 158 | 159 | Args: 160 | sol: ["SAT", "UNSAT"] 161 | claimed status 162 | 163 | Returns: 164 | False if the instance is known as SAT 165 | True otherwise 166 | ''' 167 | 168 | with open(self.args.solubility_file) as fp: 169 | for line in fp: 170 | if line.startswith(self.data.instance): 171 | line = line.strip("\n") 172 | status = line.split(" ")[1] 173 | if status in ["SAT", "SATISFIABLE"] and sol=="UNSAT": 174 | return False 175 | elif status in ["UNSAT", "UNSATISFIABLE"] and sol=="SAT": 176 | return False 177 | else: 178 | self.logger.debug("Verified by solubility file") 179 | return True 180 | self.logger.debug("Could not find instance in solubility file") 181 | return True 182 | 183 | 184 | if __name__ == "__main__": 185 | wrapper = SatCSSCWrapper() 186 | wrapper.main() 187 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/Changelog: -------------------------------------------------------------------------------- 1 | version 3.3.4 2013-11-28 2 | 3 | - fix compilation problems on Ubuntu and get rid of compilation warnings 4 | 5 | version 3.3.3 2013-07-19 6 | 7 | - fixed a bug which occurs on very short executions of the solver 8 | (such as `echo test`). In such a case, runsolver did not have the time to 9 | get the correct process group id (i.e. the watcher read /proc 10 | before the child could run setpgid()) and in the end runsolver 11 | signalled its own process group and killed itself. Besides, the 12 | default ProcessTree::currentRootPID was set to 1, which means that 13 | we could kill our whole session (kill(-1,...)) 14 | 15 | - fixed 2 bugs in timestamping: the CPU time didn't take into 16 | account the lostCPUtime and the EOF line didn't appear on its own 17 | line when the solver didn't print an EOL at the end. 18 | 19 | version 3.3.2 2013-04-19 20 | 21 | - add option -v to save the most relevant information (times, ...) 22 | in a separate file which is easy to parse (VAR=VALUE format) 23 | 24 | - display option --core in the help message and clarified the core 25 | numbering scheme used by this option 26 | 27 | - new option --phys-core to select cores by their physical id 28 | 29 | - new option --add-eof: 30 | 31 | when timestamps are used, request to add an 'EOF' line at the 32 | end of the solver output 33 | 34 | version 3.3.1 2011-06-12 35 | 36 | - make sure to kill processes which are stopped and in their own 37 | session 38 | 39 | version 3.3.0 2011-05-01 40 | 41 | - support for core information and selection 42 | - fixed a bug in case of input redirection (runsolver cmd < file) 43 | - use long instead of int for memory limits 44 | 45 | version 3.2.9a 2010-03-09 46 | 47 | - release under the GPL 48 | 49 | version 3.2.9 2009-03-27 50 | 51 | - when the main process terminates, kill each children that could remain 52 | 53 | version 3.2.8 2009-03-27 54 | 55 | - fixed a bug in the --output-limit start,max option 56 | 57 | when the output size was between start and max, "start" bytes of 58 | garbage was appended to the ouput. 59 | 60 | - --output-limit now implies --timestamp 61 | 62 | version 3.2.7 2009-03-26 63 | 64 | - added the --cleanup-ipc-queues option 65 | 66 | version 3.2.6 2009-03-24 67 | 68 | - added support for identification of heavy processes run by another user 69 | 70 | version 3.2.5 2007-05-20 71 | 72 | - the stack size command line argument was incorrectly understood as a 73 | limit in GiB instead of a limit in MiB. 74 | 75 | version 3.2.4 2007-05-9 76 | 77 | - add a test to indicate if the solver has dumped a core (when 78 | supported by the system) 79 | 80 | version 3.2.3 2007-04-16 81 | 82 | - lostCPUTime must be taken into account when deciding when the solver 83 | times out 84 | 85 | - added tests to check that fgets() correctly reads the /proc/pid/stat 86 | and statm files in ProcessData::read(). It is hoped this will fix some 87 | incoherent data read such as: 88 | 89 | [startup+402.301 s] 90 | /proc/loadavg: 1.00 0.99 0.91 2/78 12763 91 | /proc/meminfo: memFree=1564840/2055920 swapFree=4169436/4192956 92 | [pid=12688] ppid=12686 vsize=19880 CPUtime=402.13 93 | /proc/12688/stat : 12688 (cmusat) R 12686 12688 12410 0 -1 4194304 44325 0 0 0 40175 38 0 0 25 0 1 0 323084685 20357120 4250 18446744073709551615 134512640 135508737 4294956704 18446744073709551615 135092575 0 0 4096 35 0 0 0 17 1 0 0 94 | /proc/12688/statm: 4970 4251 119 243 0 4724 0 95 | Current children cumulated CPU time (s) 402.13 96 | Current children cumulated vsize (KiB) 19880 97 | 98 | Solver just ended. Dumping a history of the last processes samples 99 | 100 | [startup+402.503 s] 101 | /proc/loadavg: 1.00 0.99 0.91 1/77 12763 102 | /proc/meminfo: memFree=1679792/2055920 swapFree=4169436/4192956 103 | [pid=12688] ppid=-1 vsize=0 CPUtime=0 104 | /proc/12688/stat : 7 (events/1) S 1 0 0 0 -1 33088 0 0 0 0 0 5 0 0 5 -10 1 0 27 0 0 18446744073709551615 0 0 0 0 0 0 2147483647 65536 0 18446744073709551615 0 0 17 1 0 0 105 | /proc/12688/statm: 0 0 0 0 0 0 0 106 | Current children cumulated CPU time (s) 0 107 | Current children cumulated vsize (KiB) 0 108 | 109 | Notice that in the last sample, we fetch information about process 110 | 12688 but actually get information about pid 7 (and ppid is set to 111 | -1). The most likely explanation is that the fopen("/proc/pid/stat") 112 | succeeds but the following fgets fails because the file has 113 | disappeared. 114 | 115 | 116 | version 3.2.2 2007-04-13 117 | 118 | - added code to detect when the time of a child is not reported to its 119 | parent. When this occurs, the 'lost time' is recorded and added at the 120 | end. 121 | 122 | - minors changes in the messages that are printed when the time of a 123 | child is not reported to its parent. 124 | 125 | version 3.2.1 2007-02-27 126 | 127 | - added option --wall-clock-limit to deal with frozen solvers 128 | 129 | - minor changes in the timer thread 130 | 131 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/CircularBufferFilter.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _CircularBufferFilter_hh_ 23 | #define _CircularBufferFilter_hh_ 24 | 25 | #include 26 | #include 27 | 28 | using namespace std; 29 | 30 | 31 | class AbstractFilter 32 | { 33 | public: 34 | virtual void write(const char *buffer, int len)=0; 35 | 36 | /** 37 | * handle partial writes and EINTR 38 | */ 39 | void systemWrite(int fd, const char *buf, size_t len) 40 | { 41 | const char *p=buf; 42 | int n; 43 | 44 | do 45 | { 46 | n=::write(fd,p,len); 47 | if(n<0) 48 | { 49 | if(errno==EINTR) 50 | continue; 51 | 52 | perror("write failed: "); 53 | break; 54 | } 55 | 56 | len-=n; 57 | p+=n; 58 | } 59 | while(len); 60 | } 61 | }; 62 | 63 | class NullFilter : public AbstractFilter 64 | { 65 | private: 66 | int fd; 67 | public: 68 | NullFilter(int fd): fd(fd) {} 69 | 70 | virtual void write(const char *buffer, int len) 71 | { 72 | systemWrite(fd,buffer,len); 73 | } 74 | }; 75 | 76 | /** 77 | * This filter enforces a limit on an output file size. When the file 78 | * exceeds the limit, only the first and last bytes of output are 79 | * saved in the file. 80 | * 81 | * This filter transmits directly to file descriptor fd the first 82 | * activateSize bytes and then it only transmits the last 83 | * maxSize-activateSize bytes. 84 | * 85 | * TODO ??? 86 | * 87 | * - we currently use a circular buffer in memory to do the job. We 88 | may instead work directly on the file, using lseek to rewind to 89 | position activateSize as soon as the file size exceeds 90 | maxSize. At the end, we have to reorder the bytes at the end of 91 | the file. This may save memory but requires to be able to lseek 92 | on the file. 93 | * 94 | * - the last part of the file to which we output doesn't necessarily 95 | start at the beginning of a line. This may cause problem in some 96 | applications. 97 | */ 98 | class CircularBufferFilter : public AbstractFilter 99 | { 100 | private: 101 | unsigned long long int total; // total number of bytes sent to this filter 102 | unsigned long long int activateSize,maxSize,bufferSize; 103 | 104 | char *data; // circular buffer 105 | unsigned int w; // position where to write in the circular buffer 106 | 107 | int fd; // file descriptor to write to 108 | 109 | public: 110 | CircularBufferFilter() 111 | { 112 | data=NULL; 113 | } 114 | 115 | CircularBufferFilter(int fd, 116 | unsigned long long int activateSize, 117 | unsigned long long int maxSize) 118 | { 119 | data=NULL; 120 | setup(fd,activateSize,maxSize); 121 | } 122 | 123 | void setup(int fd, 124 | unsigned long long int activateSize, 125 | unsigned long long int maxSize) 126 | { 127 | this->fd=fd; 128 | this->activateSize=activateSize; 129 | this->maxSize=maxSize; 130 | bufferSize=maxSize-activateSize; 131 | total=0; 132 | } 133 | 134 | ~CircularBufferFilter() 135 | { 136 | flush(); 137 | } 138 | 139 | virtual void write(const char *buffer, int len) 140 | { 141 | total+=len; 142 | 143 | if (totalbufferSize-w) 169 | n=bufferSize-w; 170 | 171 | memcpy(data+w,buffer+r,n); 172 | len-=n; 173 | r+=n; 174 | w+=n; 175 | if (w>=bufferSize) 176 | w=0; 177 | } while(len>0); 178 | } 179 | } 180 | 181 | /** 182 | * normally, this should only be called by the destructor. 183 | * 184 | * remember that the destructor is not called if we are an auto 185 | * object (local variable) and if we call exit() 186 | */ 187 | void flush() 188 | { 189 | if (!data) 190 | return; 191 | 192 | char msg[512]; 193 | 194 | if (total<=maxSize) 195 | systemWrite(fd,data,total-activateSize); 196 | else 197 | { 198 | snprintf(msg,sizeof(msg), 199 | "\n" 200 | "###########################################################\n" 201 | "# A total of %llu bytes were output by the program.\n" 202 | "# This exceeds the hard limit that is enforced.\n" 203 | "# Only the %llu first bytes are saved in this file before\n" 204 | "# this point and only the %llu last bytes are saved after\n" 205 | "# this point. A total of %llu bytes are lost.\n" 206 | "###########################################################\n", 207 | total,activateSize,bufferSize,total-maxSize); 208 | systemWrite(fd,msg,strlen(msg)); 209 | systemWrite(fd,data+w,bufferSize-w); 210 | systemWrite(fd,data,w); 211 | } 212 | } 213 | }; 214 | 215 | // Local Variables: 216 | // mode: C++ 217 | // End: 218 | #endif 219 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/Cores.hh: -------------------------------------------------------------------------------- 1 | #ifndef _Cores_hh_ 2 | #define _Cores_hh_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | /** 10 | * get the list of cores available on the system 11 | * 12 | * if physicalView is true, "list" will contain the id of existing 13 | * cores in increasing order (from 0 to n-1). 14 | * 15 | * if physicalView is false, "list" will contain the id of existing 16 | * cores ordered by the processor to which they belong. For example, 17 | * list could contain 0,2,4,6,1,3,5,7 if the first processor contains 18 | * cores 0,2,4,6 and the second processor contains cores 1,3,5,7. 19 | */ 20 | void getExistingCores(vector &list, bool physicalView) 21 | { 22 | char fname[128]; 23 | string buffer; 24 | ifstream f; 25 | cpu_set_t cores; 26 | 27 | CPU_ZERO(&cores); 28 | 29 | list.clear(); 30 | 31 | for(unsigned int cpu=0;cpu0) 54 | --len; 55 | 56 | int id=0,mask; 57 | for(int i=len;i>=0;--i,id+=4) 58 | if(buffer[i]!='0' && buffer[i]!=',') 59 | { 60 | if(buffer[i]>='0' && buffer[i]<='9') 61 | mask=buffer[i]-'0'; 62 | else 63 | if(buffer[i]>='a' && buffer[i]<='f') 64 | mask=10+buffer[i]-'a'; 65 | else 66 | if(buffer[i]>='A' && buffer[i]<='F') 67 | mask=10+buffer[i]-'A'; 68 | else 69 | throw runtime_error("invalid character in cpu mask"); 70 | 71 | for(int j=0;j<4;++j) 72 | { 73 | if((mask & 1) && !CPU_ISSET(id+j,&cores)) 74 | { 75 | list.push_back(id+j); 76 | CPU_SET(id+j,&cores); // don't count it twice! 77 | } 78 | 79 | mask>>=1; 80 | } 81 | } 82 | } // if(CPU_ISET(...)) 83 | } 84 | 85 | 86 | 87 | /** 88 | * return the list of cores allocated to this process, ordered by 89 | * physical cpu 90 | */ 91 | void getAllocatedCoresByProcessorOrder(vector &allocatedCores) 92 | { 93 | char fname[128]; 94 | string buffer; 95 | ifstream f; 96 | cpu_set_t affinityMask; 97 | 98 | allocatedCores.clear(); 99 | 100 | sched_getaffinity(0,sizeof(cpu_set_t),&affinityMask); 101 | 102 | for(unsigned int cpu=0;cpu0) 118 | --len; 119 | 120 | int id=0,mask; 121 | for(int i=len;i>=0;--i,id+=4) 122 | if(buffer[i]!='0' && buffer[i]!=',') 123 | { 124 | if(buffer[i]>='0' && buffer[i]<='9') 125 | mask=buffer[i]-'0'; 126 | else 127 | if(buffer[i]>='a' && buffer[i]<='f') 128 | mask=10+buffer[i]-'a'; 129 | else 130 | if(buffer[i]>='A' && buffer[i]<='F') 131 | mask=10+buffer[i]-'A'; 132 | else 133 | throw runtime_error("invalid character in cpu mask"); 134 | 135 | for(int j=0;j<4;++j) 136 | { 137 | if((mask & 1) && CPU_ISSET(id+j,&affinityMask)) 138 | { 139 | allocatedCores.push_back(id+j); 140 | CPU_CLR(id+j,&affinityMask); // don't count it twice! 141 | } 142 | 143 | mask>>=1; 144 | } 145 | } 146 | } // if(CPU_ISET(...)) 147 | } 148 | 149 | /** 150 | * get the list of cores allocated to this process 151 | */ 152 | void getAllocatedCores(vector &list, pid_t pid=0) 153 | { 154 | cpu_set_t mask; 155 | list.clear(); 156 | 157 | sched_getaffinity(pid,sizeof(cpu_set_t),&mask); 158 | 159 | for(unsigned int i=0;i &list) 169 | { 170 | size_t end; 171 | 172 | for(size_t beg=0;beg &cores) 192 | { 193 | cpu_set_t mask; 194 | 195 | CPU_ZERO(&mask); 196 | for(size_t i=0;i. 18 | */ 19 | 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | using namespace std; 29 | 30 | map list; 31 | 32 | int main() 33 | { 34 | #include "tmpSyscallList.cc" 35 | 36 | int max=0; 37 | map::iterator it; 38 | 39 | for(it=list.begin();it!=list.end();++it) 40 | if ((*it).first>max) 41 | max=(*it).first; 42 | 43 | ofstream Hfile("SyscallNames.hh"); 44 | 45 | Hfile << "#ifndef _SyscallNames_hh_" << endl 46 | << "#define _SyscallNames_hh_" << endl 47 | << endl; 48 | 49 | Hfile << "const int nbSyscallNames=" << max+1 << ";" << endl; 50 | 51 | Hfile << endl; 52 | 53 | Hfile << "const char *getSyscallName(int n);" << endl; 54 | 55 | Hfile << endl; 56 | 57 | Hfile << "#endif" << endl; 58 | 59 | Hfile.close(); 60 | 61 | ofstream CCfile("SyscallNames.cc"); 62 | 63 | CCfile << "#include \"SyscallNames.hh\"\n\n"; 64 | 65 | CCfile << "const char *syscallNames[nbSyscallNames]={\n"; 66 | 67 | for(int i=0;i<=max;++i) 68 | { 69 | string name; 70 | it=list.find(i); 71 | if (it==list.end()) 72 | name="???"; 73 | else 74 | name=(*it).second; 75 | 76 | CCfile << "\t\"" << name << "\""; 77 | if (i!=max) 78 | CCfile << ","; 79 | 80 | CCfile << "\n"; 81 | } 82 | 83 | CCfile << "};\n\n"; 84 | 85 | CCfile << "const char *getSyscallName(int n)\n" 86 | << "{\n" 87 | << " if (n>0 && n<=nbSyscallNames)\n" 88 | << " return syscallNames[n];\n" 89 | << " else\n" 90 | << " return \"???\";\n" 91 | << "}\n"; 92 | 93 | CCfile.close(); 94 | } 95 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/Makefile: -------------------------------------------------------------------------------- 1 | VERSION=3.3.4 2 | #SVNVERSION=`svnversion .` 3 | SVNVERSION=$(word 2,$$Rev: 1649 $$) 4 | #DEBUG=-g 5 | DEBUG=-O3 6 | 7 | STATIC= 8 | #STATIC=-static 9 | 10 | WSIZE:=$(shell if [ `uname -m` = 'x86_64' ] ; then echo 64; else echo 32; fi ) 11 | SYSCALLINCFILE:=$(shell for f in /usr/include/asm/unistd_$(WSIZE).h /usr/include/`uname -m`-linux-gnu/asm/unistd_$(WSIZE).h /usr/include/i386-linux-gnu/asm/unistd_$(WSIZE).h; do if [ -e $$f ] ; then echo $$f ; break ; fi ; done ) 12 | 13 | CFLAGS=-Dtmpdebug -Wall -DVERSION=\"$(VERSION)\" -DSVNVERSION=\"$(SVNVERSION)\" -DWSIZE=$(WSIZE) 14 | 15 | SRC=runsolver.cc SignalNames.cc SyscallNames.cc 16 | OBJ=$(SRC:.cc=.o) 17 | 18 | all:runsolver 19 | 20 | install: runsolver 21 | cp runsolver $(INSTROOT)/usr/bin 22 | 23 | include $(SRC:.cc=.d) 24 | 25 | .cc.o: 26 | g++ $(CFLAGS) $(DEBUG) -c $*.cc 27 | 28 | runsolver: $(OBJ) 29 | g++ $(STATIC) $(DEBUG) -o $@ $^ -lpthread 30 | 31 | testlimit: testlimit.cc 32 | g++ -o testlimit testlimit.cc 33 | 34 | testthread: testthread.cc 35 | g++ -o testthread testthread.cc -lpthread 36 | 37 | SyscallNames.cc SyscallNames.hh: CreateSyscallsNames.cc $(SYSCALLINCFILE) 38 | grep '#define[[:space:]]*__NR' $(SYSCALLINCFILE) | grep -v '^/' | awk '{print $$2}' | sed -e 's/^__NR_//' | awk '{printf "list[__NR_%s]=\"%s\";\n",$$1,$$1}' > tmpSyscallList.cc 39 | g++ -o CreateSyscallsNames CreateSyscallsNames.cc 40 | ./CreateSyscallsNames 41 | rm tmpSyscallList.cc CreateSyscallsNames 42 | 43 | .PHONY: clean realclean archive 44 | 45 | tar: /tmp/runsolver-$(VERSION).tar.bz2 46 | archive: /tmp/runsolver-$(VERSION).tar.bz2 47 | 48 | /tmp/runsolver-$(VERSION).tar.bz2: realclean $(SRC) Makefile 49 | sed -i -e 's/^Version:.*/Version:\t'$(VERSION)'/' runsolver.spec 50 | tar cvjf /tmp/runsolver-$(VERSION).tar.bz2 -C ../.. runsolver/src --exclude .svn 51 | 52 | rpm: /tmp/runsolver-$(VERSION).tar.bz2 53 | rpmbuild -tb /tmp/runsolver-$(VERSION).tar.bz2 54 | 55 | srpm: /tmp/runsolver-$(VERSION).tar.bz2 56 | rpmbuild -ts /tmp/runsolver-$(VERSION).tar.bz2 57 | 58 | clean: 59 | rm -f runsolver $(OBJ) *.class testlimit testtimestamper vlineSplitter testProcessTree runtestlimit testthread 60 | 61 | realclean: clean 62 | rm -f *.d *~ SyscallNames.* 63 | 64 | 65 | %.d: %.cc 66 | $(SHELL) -ec '$(CC) -MM $(CFLAGS) $< \ 67 | | sed -e '\''s/$*\.o[ :]*/$@ &/g'\'' > $@' 68 | 69 | 70 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/Makefile.back: -------------------------------------------------------------------------------- 1 | VERSION=3.3.4 2 | #SVNVERSION=`svnversion .` 3 | SVNVERSION=$(word 2,$$Rev: 1649 $$) 4 | #DEBUG=-g 5 | DEBUG=-O3 6 | 7 | STATIC= 8 | #STATIC=-static 9 | 10 | WSIZE:=$(shell if [ `uname -m` = 'x86_64' ] ; then echo 64; else echo 32; fi ) 11 | SYSCALLINCFILE:=$(shell for f in /usr/include/asm/unistd_$(WSIZE).h /usr/include/`uname -m`-linux-gnu/asm/unistd_$(WSIZE).h ; do if [ -e $$f ] ; then echo $$f ; break ; fi ; done ) 12 | 13 | CFLAGS=-Dtmpdebug -Wall -DVERSION=\"$(VERSION)\" -DSVNVERSION=\"$(SVNVERSION)\" -DWSIZE=$(WSIZE) 14 | 15 | SRC=runsolver.cc SignalNames.cc SyscallNames.cc 16 | OBJ=$(SRC:.cc=.o) 17 | 18 | all:runsolver 19 | 20 | install: runsolver 21 | cp runsolver $(INSTROOT)/usr/bin 22 | 23 | include $(SRC:.cc=.d) 24 | 25 | .cc.o: 26 | g++ $(CFLAGS) $(DEBUG) -c $*.cc 27 | 28 | runsolver: $(OBJ) 29 | g++ $(STATIC) $(DEBUG) -o $@ $^ -lpthread 30 | 31 | testlimit: testlimit.cc 32 | g++ -o testlimit testlimit.cc 33 | 34 | testthread: testthread.cc 35 | g++ -o testthread testthread.cc -lpthread 36 | 37 | SyscallNames.cc SyscallNames.hh: CreateSyscallsNames.cc $(SYSCALLINCFILE) 38 | grep '#define[[:space:]]*__NR' $(SYSCALLINCFILE) | grep -v '^/' | awk '{print $$2}' | sed -e 's/^__NR_//' | awk '{printf "list[__NR_%s]=\"%s\";\n",$$1,$$1}' > tmpSyscallList.cc 39 | g++ -o CreateSyscallsNames CreateSyscallsNames.cc 40 | ./CreateSyscallsNames 41 | rm tmpSyscallList.cc CreateSyscallsNames 42 | 43 | .PHONY: clean realclean archive 44 | 45 | tar: /tmp/runsolver-$(VERSION).tar.bz2 46 | archive: /tmp/runsolver-$(VERSION).tar.bz2 47 | 48 | /tmp/runsolver-$(VERSION).tar.bz2: realclean $(SRC) Makefile 49 | sed -i -e 's/^Version:.*/Version:\t'$(VERSION)'/' runsolver.spec 50 | tar cvjf /tmp/runsolver-$(VERSION).tar.bz2 -C ../.. runsolver/src --exclude .svn 51 | 52 | rpm: /tmp/runsolver-$(VERSION).tar.bz2 53 | rpmbuild -tb /tmp/runsolver-$(VERSION).tar.bz2 54 | 55 | srpm: /tmp/runsolver-$(VERSION).tar.bz2 56 | rpmbuild -ts /tmp/runsolver-$(VERSION).tar.bz2 57 | 58 | clean: 59 | rm -f runsolver $(OBJ) *.class testlimit testtimestamper vlineSplitter testProcessTree runtestlimit testthread 60 | 61 | realclean: clean 62 | rm -f *.d *~ SyscallNames.* 63 | 64 | 65 | %.d: %.cc 66 | $(SHELL) -ec '$(CC) -MM $(CFLAGS) $< \ 67 | | sed -e '\''s/$*\.o[ :]*/$@ &/g'\'' > $@' 68 | 69 | 70 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/Observer.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _Observer_hh_ 23 | #define _Observer_hh_ 24 | #endif 25 | 26 | /** 27 | * a class to watch file descriptors and wait for data to become 28 | * available on one of them 29 | * 30 | */ 31 | class Observer 32 | { 33 | private: 34 | vector desc; 35 | fd_set readable; 36 | public: 37 | /** 38 | * add a file descriptor to watch 39 | */ 40 | void add(int fd) 41 | { 42 | desc.push_back(fd); 43 | } 44 | 45 | /** 46 | * remove a file descriptor from the list of file descriptors to watch 47 | * 48 | * doit être appele avant de fermer la socket 49 | */ 50 | void remove(int fd) 51 | { 52 | vector::iterator i=find(desc.begin(),desc.end(),fd); 53 | if (i!=desc.end()) 54 | desc.erase(i); 55 | } 56 | 57 | /** 58 | * tell if there is some file descriptor left to watch 59 | */ 60 | bool empty() 61 | { 62 | return desc.empty(); 63 | } 64 | 65 | /** 66 | * wait for data to become available on one of the file descriptor 67 | * that is watched 68 | * 69 | * this is a blocking method 70 | */ 71 | void waitForData() 72 | { 73 | int max=0; 74 | 75 | FD_ZERO(&readable); 76 | 77 | for (int i=0;i. 18 | */ 19 | 20 | 21 | 22 | #ifndef _ProcessData_hh_ 23 | #define _ProcessData_hh_ 24 | 25 | #include 26 | using namespace std; 27 | 28 | // see man proc (/proc/[number]/stat) 29 | struct statData 30 | { 31 | int pid; 32 | char comm[64]; // ??? 33 | char state; 34 | int ppid; 35 | int pgrp; 36 | int session; 37 | int tty_nr; 38 | int tpgid; 39 | unsigned long int flags; 40 | unsigned long int minflt; 41 | unsigned long int cminflt; 42 | unsigned long int majflt; 43 | unsigned long int cmajflt; 44 | unsigned long int utime; 45 | unsigned long int stime; 46 | long int cutime; 47 | long int cstime; 48 | long int priority; 49 | long int nice; 50 | long int zero; 51 | long int itrealvalue; 52 | unsigned long int starttime; 53 | unsigned long int vsize; 54 | long int rss; 55 | unsigned long int rlim; 56 | unsigned long int startcode; 57 | unsigned long int endcode; 58 | unsigned long int startstack; 59 | unsigned long int kstkesp; 60 | unsigned long int kstkeip; 61 | unsigned long int signal; 62 | unsigned long int blocked; 63 | unsigned long int sigignore; 64 | unsigned long int sigcatch; 65 | unsigned long int wchan; 66 | unsigned long int nswap; 67 | unsigned long int cnswap; 68 | int exit_signal; 69 | int processor; 70 | unsigned long int rtprio; 71 | unsigned long int sched; 72 | 73 | // extra 74 | bool valid; 75 | }; 76 | 77 | /** 78 | * The information we keep on a process 79 | */ 80 | class ProcessData 81 | { 82 | private: 83 | bool valid; // did we collect meaningful data? 84 | 85 | static const unsigned long int clockTicksPerSecond; 86 | 87 | uid_t uid; 88 | gid_t gid; 89 | 90 | pid_t pid,tid,ppid,pgrp; 91 | unsigned long int utime,stime,cutime,cstime; 92 | unsigned long int starttime; 93 | unsigned long int vsize; 94 | 95 | vector children; 96 | 97 | char statLine[1024]; // ??? 98 | char statmLine[1024]; // ??? 99 | 100 | vector allocatedCores; 101 | 102 | bool selected; // a flag to select/unselect processes 103 | 104 | inline void init() 105 | { 106 | valid=false; 107 | pid=-1; 108 | tid=-1; 109 | ppid=-1; 110 | utime=stime=cutime=cstime=0; 111 | vsize=0; 112 | } 113 | 114 | public: 115 | ProcessData() {init();} 116 | 117 | ProcessData(pid_t pid, pid_t tid=0) 118 | { 119 | init(); 120 | read(pid,tid); 121 | } 122 | 123 | ProcessData(const ProcessData &pd) 124 | { 125 | uid=pd.uid; 126 | gid=pd.gid; 127 | 128 | pid=pd.pid; 129 | tid=pd.tid; 130 | ppid=pd.ppid; 131 | utime=pd.utime; 132 | stime=pd.stime; 133 | cutime=pd.cutime; 134 | cstime=pd.cstime; 135 | vsize=pd.vsize; 136 | 137 | for(size_t i=0;ipid=pid; 155 | this->tid=tid; 156 | 157 | 158 | if (tid) 159 | snprintf(fileName,sizeof(fileName),"/proc/%d/task/%d/stat",pid,tid); 160 | else 161 | snprintf(fileName,sizeof(fileName),"/proc/%d/stat",pid); 162 | 163 | if ((file=fopen(fileName,"r"))!=NULL) 164 | { 165 | struct stat info; 166 | 167 | fstat(fileno(file),&info); 168 | 169 | uid=info.st_uid; 170 | gid=info.st_gid; 171 | 172 | if (fgets(statLine,sizeof(statLine),file)==NULL) 173 | { 174 | #ifdef debug 175 | perror("failed to read stat file"); 176 | #endif 177 | 178 | strcpy(statLine,"-- couldn't read stat file --"); 179 | fclose(file); 180 | 181 | return false; 182 | } 183 | 184 | fclose(file); 185 | } 186 | else 187 | { 188 | #ifdef debug 189 | perror("failed to open stat file"); 190 | #endif 191 | 192 | strcpy(statLine,"-- couldn't open stat file --"); 193 | return false; 194 | } 195 | 196 | nbFields=sscanf(statLine, 197 | #if WSIZE==32 198 | "%*d " 199 | "%*s " 200 | "%*c " 201 | "%d %d %*d %*d %*d " 202 | "%*u %*u %*u %*u %*u " // lu lu lu lu lu 203 | "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ 204 | "%*d %*d " // ld ld 205 | "%*d " 206 | "%*d " // ld 207 | "%Lu " /* start_time */ 208 | "%lu ", 209 | #else 210 | "%*d " 211 | "%*s " 212 | "%*c " 213 | "%d %d %*d %*d %*d " 214 | "%*u %*u %*u %*u %*u " // lu lu lu lu lu 215 | "%lu %lu %lu %lu " /* utime stime cutime cstime */ 216 | "%*d %*d " // ld ld 217 | "%*d " 218 | "%*d " // ld 219 | "%lu " /* start_time */ 220 | "%lu ", 221 | #endif 222 | &ppid,&pgrp, 223 | &utime, &stime, &cutime, &cstime, 224 | &starttime, 225 | &vsize 226 | ); 227 | 228 | valid=(nbFields==8); 229 | 230 | #ifdef debug 231 | if(!valid) 232 | cout << "FAILED TO READ EACH FIELD\n"; 233 | #endif 234 | 235 | if (!tid) 236 | { 237 | snprintf(fileName,sizeof(fileName),"/proc/%d/statm",pid); 238 | 239 | if ((file=fopen(fileName,"r"))!=NULL) 240 | { 241 | if (fgets(statmLine,sizeof(statmLine),file)==NULL) 242 | { 243 | #ifdef debug 244 | perror("failed to read statm file"); 245 | #endif 246 | 247 | strcpy(statmLine,"-- couldn't read statm file --"); 248 | fclose(file); 249 | 250 | return false; 251 | } 252 | 253 | fclose(file); 254 | } 255 | else 256 | { 257 | #ifdef debug 258 | perror("failed to open statm file"); 259 | #endif 260 | 261 | strcpy(statmLine,"-- couldn't open statm file --"); 262 | } 263 | } 264 | 265 | getAllocatedCores(); 266 | 267 | return true; 268 | } 269 | 270 | /** 271 | * update data on this process 272 | * 273 | * return false iff the process doesn't exit any more 274 | */ 275 | bool update() 276 | { 277 | return read(pid,tid); 278 | } 279 | 280 | /** 281 | * return the % of CPU used by this process (and its children when 282 | * withChildren is true). The result is between 0 and 1 283 | */ 284 | float percentageCPU(float uptime, bool withChildren=false) const 285 | { 286 | float cputime=stime+utime; 287 | 288 | if (withChildren) 289 | cputime+=cstime+cutime; 290 | 291 | cputime/=clockTicksPerSecond; 292 | 293 | float wctime=uptime-static_cast(starttime)/clockTicksPerSecond; 294 | 295 | if (wctime==0) 296 | return 0; 297 | else 298 | return cputime/wctime; 299 | } 300 | 301 | 302 | void readProcessData(statData &s) 303 | { 304 | int nbFields; 305 | 306 | memset(&s,0,sizeof(statData)); 307 | 308 | nbFields=sscanf(statLine, 309 | #if WSIZE==32 310 | "%d " 311 | "%s " 312 | "%c " 313 | "%d %d %d %d %d " 314 | "%lu %lu %lu %lu %lu " 315 | "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ 316 | "%ld %ld " 317 | "%d " 318 | "%ld " 319 | "%Lu " /* start_time */ 320 | "%lu " 321 | "%ld " 322 | "%lu %lu %lu %lu %lu %lu " 323 | "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ 324 | "%lu %*u %*u " // lu lu lu 325 | "%d %d " 326 | "%lu %lu", 327 | #else 328 | "%d " 329 | "%s " 330 | "%c " 331 | "%d %d %d %d %d " 332 | "%lu %lu %lu %lu %lu " 333 | "%lu %lu %lu %lu " /* utime stime cutime cstime */ 334 | "%ld %ld " 335 | "%ld " 336 | "%ld " 337 | "%lu " /* start_time */ 338 | "%lu " 339 | "%ld " 340 | "%lu %lu %lu %lu %lu %lu " 341 | "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */ 342 | "%lu %*u %*u " // lu lu lu 343 | "%d %d " 344 | "%lu %lu", 345 | #endif 346 | &s.pid, 347 | s.comm, 348 | &s.state, 349 | &s.ppid, &s.pgrp, &s.session, &s.tty_nr, &s.tpgid, 350 | &s.flags, &s.minflt, &s.cminflt, 351 | &s.majflt, &s.cmajflt, 352 | &s.utime, &s.stime, &s.cutime, &s.cstime, 353 | &s.priority, &s.nice, 354 | &s.zero, 355 | &s.itrealvalue, 356 | &s.starttime, 357 | &s.vsize, 358 | &s.rss, 359 | &s.rlim, &s.startcode, &s.endcode, 360 | &s.startstack, &s.kstkesp, &s.kstkeip, 361 | /* s.signal, s.blocked, s.sigignore, s.sigcatch, */ /* can't use */ 362 | &s.wchan, 363 | /* &s.nswap, &s.cnswap, */ 364 | /* nswap and cnswap dead for 2.4.xx and up */ 365 | /* -- Linux 2.0.35 ends here -- */ 366 | &s.exit_signal, &s.processor, 367 | /* 2.2.1 ends with "exit_signal" */ 368 | /* -- Linux 2.2.8 to 2.5.17 end here -- */ 369 | &s.rtprio, &s.sched /* both added to 2.5.18 */ 370 | ); 371 | 372 | s.valid=(nbFields==35); 373 | 374 | #ifdef debug 375 | if(!s.valid) 376 | cout << "FAILED TO READ EACH FIELD OF STAT DATA\n"; 377 | #endif 378 | } 379 | 380 | bool isTask() const 381 | { 382 | return tid!=0; 383 | } 384 | 385 | void addChild(pid_t child) 386 | { 387 | children.push_back(child); 388 | } 389 | 390 | int getNbChildren() const 391 | { 392 | return children.size(); 393 | } 394 | 395 | pid_t getPIDChild(int i) const 396 | { 397 | return children[i]; 398 | } 399 | 400 | pid_t getppid() const 401 | { 402 | return ppid; 403 | } 404 | 405 | pid_t getProcessGroupId() const 406 | { 407 | return pgrp; 408 | } 409 | 410 | uid_t getUid() const 411 | { 412 | return uid; 413 | } 414 | 415 | void select() 416 | { 417 | selected=true; 418 | } 419 | 420 | void unselect() 421 | { 422 | selected=false; 423 | } 424 | 425 | bool isSelected() const 426 | { 427 | return selected; 428 | } 429 | 430 | float getOverallCPUTime() const 431 | { 432 | // note that cstime and cutime (child system and user time) are 433 | // only updated by the wait call in the parent (this is to say, 434 | // only once the child has terminated). Therefore, we can't rely 435 | // on these variables to limit the global cpu use of a process 436 | // and its children 437 | 438 | return (stime+(float)utime 439 | +cstime+(float)cutime 440 | )/clockTicksPerSecond; 441 | } 442 | 443 | float getOverallUserTime() const 444 | { 445 | // note that cstime and cutime (child system and user time) are 446 | // only updated by the wait call in the parent (this is to say, 447 | // only once the child has terminated). Therefore, we can't rely 448 | // on these variables to limit the global cpu use of a process 449 | // and its children 450 | 451 | return (utime+(float)cutime)/clockTicksPerSecond; 452 | } 453 | 454 | float getOverallSystemTime() const 455 | { 456 | // note that cstime and cutime (child system and user time) are 457 | // only updated by the wait call in the parent (this is to say, 458 | // only once the child has terminated). Therefore, we can't rely 459 | // on these variables to limit the global cpu use of a process 460 | // and its children 461 | 462 | return (stime+(float)cstime)/clockTicksPerSecond; 463 | } 464 | 465 | /** 466 | * return the current vsize in Kb 467 | */ 468 | long getVSize() const 469 | { 470 | return vsize/1024; 471 | } 472 | 473 | /** 474 | * get the list of cores allocated to this process 475 | */ 476 | void getAllocatedCores() 477 | { 478 | cpu_set_t mask; 479 | allocatedCores.clear(); 480 | 481 | sched_getaffinity(pid,sizeof(cpu_set_t),&mask); 482 | 483 | for(int i=0;i. 18 | */ 19 | 20 | 21 | 22 | #ifndef _ProcessHistory_hh_ 23 | #define _ProcessHistory_hh_ 24 | 25 | #include 26 | #include "ProcessTree.hh" 27 | 28 | using namespace std; 29 | 30 | /** 31 | * maintains a history of process trees 32 | */ 33 | class ProcessHistory 34 | { 35 | private: 36 | int nbcell; 37 | vector nbitem; 38 | vector history; 39 | 40 | public: 41 | ProcessHistory(int n) 42 | { 43 | nbcell=n; 44 | nbitem.resize(nbcell); 45 | history.resize(2*nbcell); 46 | for(int i=0;i0;++cell) 54 | for(int i=0;i0;++cell) 92 | { 93 | for(int i=0;i=0;--cell) 104 | { 105 | if (nbitem[cell]==0 || 106 | history[2*cell]->getElapsedTime()<=elapsedLimit) 107 | continue; 108 | 109 | history[2*cell]->dumpProcessTree(s); 110 | history[2*cell]->dumpCPUTimeAndVSize(s); 111 | } 112 | 113 | if (nbitem[0]==2) 114 | { 115 | // also dump the most recent 116 | history[1]->dumpProcessTree(s); 117 | history[1]->dumpCPUTimeAndVSize(s); 118 | } 119 | } 120 | 121 | protected: 122 | void drop(ProcessTree *elem) 123 | { 124 | delete elem; 125 | } 126 | }; 127 | 128 | // Local Variables: 129 | // mode: C++ 130 | // End: 131 | #endif 132 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/ProcessList.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _ProcessList_hh_ 23 | #define _ProcessList_hh_ 24 | 25 | #include 26 | 27 | using namespace std; 28 | 29 | /** 30 | * a class to store a list of process IDs 31 | * 32 | * ??? should be optimized !!! 33 | */ 34 | class ProcessList 35 | { 36 | private: 37 | set s; 38 | public: 39 | typedef set::iterator iterator; 40 | 41 | inline void add(pid_t pid) 42 | { 43 | s.insert(pid); 44 | } 45 | 46 | inline void remove(pid_t pid) 47 | { 48 | s.erase(pid); 49 | } 50 | 51 | inline bool contains(pid_t pid) const 52 | { 53 | return s.find(pid)!=s.end(); 54 | } 55 | 56 | iterator begin() const {return s.begin();} 57 | iterator end() const {return s.end();} 58 | }; 59 | 60 | 61 | #endif 62 | 63 | // Local Variables: 64 | // mode: C++ 65 | // End: 66 | 67 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/README: -------------------------------------------------------------------------------- 1 | runsolver with fixes from Steve Ramage 2 | 3 | Please note that we implemented some bug fixes in the runsolver-3.3.4. 4 | Please see below the original README from the runsolver by Olivier Roussel. 5 | 6 | ========================================================================== 7 | 8 | runsolver Copyright (C) 2010 Olivier ROUSSEL (roussel@cril.univ-artois.fr) 9 | 10 | runsolver is a program meant to control the ressources used by a 11 | solver. Basically, it can be seen as the integration of the time and 12 | ulimit commands, but it has several other features. It is able to 13 | timestamp each line output by a program, is able to handle correctly 14 | multithreads or multiprocesses programs (don't loose the time of the 15 | child even when the parent doesn't call wait()), is able to enforce 16 | strict limits on the memory usage, logs information on each process 17 | generated by the solver and is able to limit the size of the solver 18 | output. 19 | 20 | This program is especially useful when you want to run a program and 21 | strictly control the ressources it uses. 22 | 23 | This program was first used in the competitions of Pseudo-Boolean 24 | solvers (2005) and was later used in the SAT and CSP competitions. 25 | 26 | For now, the code is Linux specific. 27 | 28 | 29 | runsolver is free software, distributed under the terms of the [GNU] General 30 | Public License as published by the Free Software Foundation, 31 | version 3 of the License (or any later version). For more information, 32 | see the file LICENSE-GPL-3.0.txt. 33 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/SignalNames.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #include "SignalNames.hh" 23 | 24 | const char *signalNames[]={ 25 | "???", 26 | "SIGHUP", 27 | "SIGINT", 28 | "SIGQUIT", 29 | "SIGILL", 30 | "SIGTRAP", 31 | "SIGABRT", 32 | "SIGBUS", 33 | "SIGFPE", 34 | "SIGKILL", 35 | "SIGUSR1", 36 | "SIGSEGV", 37 | "SIGUSR2", 38 | "SIGPIPE", 39 | "SIGALRM", 40 | "SIGTERM", 41 | "SIGSTKFLT", 42 | "SIGCHLD", 43 | "SIGCONT", 44 | "SIGSTOP", 45 | "SIGTSTP", 46 | "SIGTTIN", 47 | "SIGTTOU", 48 | "SIGURG", 49 | "SIGXCPU", 50 | "SIGXFSZ", 51 | "SIGVTALRM", 52 | "SIGPROF", 53 | "SIGWINCH", 54 | "SIGIO", 55 | "SIGPWR", 56 | "SIGSYS"}; 57 | 58 | 59 | const char *getSignalName(int sig) 60 | { 61 | if (sig>0 && sig<=static_cast(sizeof(signalNames)/sizeof(char *))) 62 | return signalNames[sig]; 63 | else 64 | return "???"; 65 | } 66 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/SignalNames.d: -------------------------------------------------------------------------------- 1 | SignalNames.d SignalNames.o: SignalNames.cc SignalNames.hh 2 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/SignalNames.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _SignalNames_hh_ 23 | #define _SignalNames_hh_ 24 | 25 | const char *getSignalName(int sig); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/SyscallNames.cc: -------------------------------------------------------------------------------- 1 | #include "SyscallNames.hh" 2 | 3 | const char *syscallNames[nbSyscallNames]={ 4 | "read", 5 | "write", 6 | "open", 7 | "close", 8 | "stat", 9 | "fstat", 10 | "lstat", 11 | "poll", 12 | "lseek", 13 | "mmap", 14 | "mprotect", 15 | "munmap", 16 | "brk", 17 | "rt_sigaction", 18 | "rt_sigprocmask", 19 | "rt_sigreturn", 20 | "ioctl", 21 | "pread64", 22 | "pwrite64", 23 | "readv", 24 | "writev", 25 | "access", 26 | "pipe", 27 | "select", 28 | "sched_yield", 29 | "mremap", 30 | "msync", 31 | "mincore", 32 | "madvise", 33 | "shmget", 34 | "shmat", 35 | "shmctl", 36 | "dup", 37 | "dup2", 38 | "pause", 39 | "nanosleep", 40 | "getitimer", 41 | "alarm", 42 | "setitimer", 43 | "getpid", 44 | "sendfile", 45 | "socket", 46 | "connect", 47 | "accept", 48 | "sendto", 49 | "recvfrom", 50 | "sendmsg", 51 | "recvmsg", 52 | "shutdown", 53 | "bind", 54 | "listen", 55 | "getsockname", 56 | "getpeername", 57 | "socketpair", 58 | "setsockopt", 59 | "getsockopt", 60 | "clone", 61 | "fork", 62 | "vfork", 63 | "execve", 64 | "exit", 65 | "wait4", 66 | "kill", 67 | "uname", 68 | "semget", 69 | "semop", 70 | "semctl", 71 | "shmdt", 72 | "msgget", 73 | "msgsnd", 74 | "msgrcv", 75 | "msgctl", 76 | "fcntl", 77 | "flock", 78 | "fsync", 79 | "fdatasync", 80 | "truncate", 81 | "ftruncate", 82 | "getdents", 83 | "getcwd", 84 | "chdir", 85 | "fchdir", 86 | "rename", 87 | "mkdir", 88 | "rmdir", 89 | "creat", 90 | "link", 91 | "unlink", 92 | "symlink", 93 | "readlink", 94 | "chmod", 95 | "fchmod", 96 | "chown", 97 | "fchown", 98 | "lchown", 99 | "umask", 100 | "gettimeofday", 101 | "getrlimit", 102 | "getrusage", 103 | "sysinfo", 104 | "times", 105 | "ptrace", 106 | "getuid", 107 | "syslog", 108 | "getgid", 109 | "setuid", 110 | "setgid", 111 | "geteuid", 112 | "getegid", 113 | "setpgid", 114 | "getppid", 115 | "getpgrp", 116 | "setsid", 117 | "setreuid", 118 | "setregid", 119 | "getgroups", 120 | "setgroups", 121 | "setresuid", 122 | "getresuid", 123 | "setresgid", 124 | "getresgid", 125 | "getpgid", 126 | "setfsuid", 127 | "setfsgid", 128 | "getsid", 129 | "capget", 130 | "capset", 131 | "rt_sigpending", 132 | "rt_sigtimedwait", 133 | "rt_sigqueueinfo", 134 | "rt_sigsuspend", 135 | "sigaltstack", 136 | "utime", 137 | "mknod", 138 | "uselib", 139 | "personality", 140 | "ustat", 141 | "statfs", 142 | "fstatfs", 143 | "sysfs", 144 | "getpriority", 145 | "setpriority", 146 | "sched_setparam", 147 | "sched_getparam", 148 | "sched_setscheduler", 149 | "sched_getscheduler", 150 | "sched_get_priority_max", 151 | "sched_get_priority_min", 152 | "sched_rr_get_interval", 153 | "mlock", 154 | "munlock", 155 | "mlockall", 156 | "munlockall", 157 | "vhangup", 158 | "modify_ldt", 159 | "pivot_root", 160 | "_sysctl", 161 | "prctl", 162 | "arch_prctl", 163 | "adjtimex", 164 | "setrlimit", 165 | "chroot", 166 | "sync", 167 | "acct", 168 | "settimeofday", 169 | "mount", 170 | "umount2", 171 | "swapon", 172 | "swapoff", 173 | "reboot", 174 | "sethostname", 175 | "setdomainname", 176 | "iopl", 177 | "ioperm", 178 | "create_module", 179 | "init_module", 180 | "delete_module", 181 | "get_kernel_syms", 182 | "query_module", 183 | "quotactl", 184 | "nfsservctl", 185 | "getpmsg", 186 | "putpmsg", 187 | "afs_syscall", 188 | "tuxcall", 189 | "security", 190 | "gettid", 191 | "readahead", 192 | "setxattr", 193 | "lsetxattr", 194 | "fsetxattr", 195 | "getxattr", 196 | "lgetxattr", 197 | "fgetxattr", 198 | "listxattr", 199 | "llistxattr", 200 | "flistxattr", 201 | "removexattr", 202 | "lremovexattr", 203 | "fremovexattr", 204 | "tkill", 205 | "time", 206 | "futex", 207 | "sched_setaffinity", 208 | "sched_getaffinity", 209 | "set_thread_area", 210 | "io_setup", 211 | "io_destroy", 212 | "io_getevents", 213 | "io_submit", 214 | "io_cancel", 215 | "get_thread_area", 216 | "lookup_dcookie", 217 | "epoll_create", 218 | "epoll_ctl_old", 219 | "epoll_wait_old", 220 | "remap_file_pages", 221 | "getdents64", 222 | "set_tid_address", 223 | "restart_syscall", 224 | "semtimedop", 225 | "fadvise64", 226 | "timer_create", 227 | "timer_settime", 228 | "timer_gettime", 229 | "timer_getoverrun", 230 | "timer_delete", 231 | "clock_settime", 232 | "clock_gettime", 233 | "clock_getres", 234 | "clock_nanosleep", 235 | "exit_group", 236 | "epoll_wait", 237 | "epoll_ctl", 238 | "tgkill", 239 | "utimes", 240 | "vserver", 241 | "mbind", 242 | "set_mempolicy", 243 | "get_mempolicy", 244 | "mq_open", 245 | "mq_unlink", 246 | "mq_timedsend", 247 | "mq_timedreceive", 248 | "mq_notify", 249 | "mq_getsetattr", 250 | "kexec_load", 251 | "waitid", 252 | "add_key", 253 | "request_key", 254 | "keyctl", 255 | "ioprio_set", 256 | "ioprio_get", 257 | "inotify_init", 258 | "inotify_add_watch", 259 | "inotify_rm_watch", 260 | "migrate_pages", 261 | "openat", 262 | "mkdirat", 263 | "mknodat", 264 | "fchownat", 265 | "futimesat", 266 | "newfstatat", 267 | "unlinkat", 268 | "renameat", 269 | "linkat", 270 | "symlinkat", 271 | "readlinkat", 272 | "fchmodat", 273 | "faccessat", 274 | "pselect6", 275 | "ppoll", 276 | "unshare", 277 | "set_robust_list", 278 | "get_robust_list", 279 | "splice", 280 | "tee", 281 | "sync_file_range", 282 | "vmsplice", 283 | "move_pages", 284 | "utimensat", 285 | "epoll_pwait", 286 | "signalfd", 287 | "timerfd_create", 288 | "eventfd", 289 | "fallocate", 290 | "timerfd_settime", 291 | "timerfd_gettime", 292 | "accept4", 293 | "signalfd4", 294 | "eventfd2", 295 | "epoll_create1", 296 | "dup3", 297 | "pipe2", 298 | "inotify_init1", 299 | "preadv", 300 | "pwritev", 301 | "rt_tgsigqueueinfo", 302 | "perf_event_open", 303 | "recvmmsg", 304 | "fanotify_init", 305 | "fanotify_mark", 306 | "prlimit64", 307 | "name_to_handle_at", 308 | "open_by_handle_at", 309 | "clock_adjtime", 310 | "syncfs", 311 | "sendmmsg", 312 | "setns", 313 | "getcpu", 314 | "process_vm_readv", 315 | "process_vm_writev", 316 | "kcmp", 317 | "finit_module" 318 | }; 319 | 320 | const char *getSyscallName(int n) 321 | { 322 | if (n>0 && n<=nbSyscallNames) 323 | return syscallNames[n]; 324 | else 325 | return "???"; 326 | } 327 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/SyscallNames.d: -------------------------------------------------------------------------------- 1 | SyscallNames.d SyscallNames.o: SyscallNames.cc SyscallNames.hh 2 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/SyscallNames.hh: -------------------------------------------------------------------------------- 1 | #ifndef _SyscallNames_hh_ 2 | #define _SyscallNames_hh_ 3 | 4 | const int nbSyscallNames=314; 5 | 6 | const char *getSyscallName(int n); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/TimeStamper.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _TimeStamper_hh_ 23 | #define _TimeStamper_hh_ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | // if we use the TimeStamper in a threaded program, we may have to use 35 | // mutexes 36 | #include 37 | 38 | #include "CircularBufferFilter.hh" 39 | 40 | using namespace std; 41 | 42 | /** 43 | * a class that intercepts the data on some watched file descriptors 44 | * and adds a timestamp at the beginning of each line. 45 | */ 46 | class TimeStamper 47 | { 48 | public: 49 | TimeStamper(bool withCPUtime=true) : withCPUtime(withCPUtime) 50 | { 51 | // initialize select() data 52 | FD_ZERO(&watcher); 53 | max=1; 54 | 55 | // in case the user forgets to call it 56 | resetTimeStamp(); 57 | 58 | lastKnownCPUtime=0; 59 | pthread_mutex_init(&cputimeMutex,NULL); 60 | 61 | addEOFLine=false; 62 | 63 | incompleteLineSent=false; 64 | } 65 | 66 | /** 67 | * specifies if a special 'EOF' line should be added at the end of 68 | * output. This line allows to get the value of the timestamps when 69 | * the process ends. 70 | * 71 | * @parm add: true iff the 'EOF' line must be added 72 | */ 73 | void addEOF(bool add) 74 | { 75 | addEOFLine=add; 76 | } 77 | 78 | /** 79 | * add a file descriptor (inputfd) to the list of timestamped files 80 | * 81 | * @parm inputfd: file descriptor of the file that must be timestamped 82 | * @parm letter: one letter name of the timestamped stream (0 if unused) 83 | * @parm outputfd: file descriptor to use to output the 84 | * timestamped stream (stdout by default) 85 | */ 86 | void watch(int inputfd, char letter=0, int outputfd=STDOUT_FILENO) 87 | { 88 | FD_SET(inputfd,&watcher); 89 | if(inputfd>=max) 90 | max=inputfd+1; 91 | 92 | watched.push_back(info(inputfd,outputfd,letter,true)); 93 | } 94 | 95 | /** 96 | * add a file descriptor (inputfd) to the list of timestamped files 97 | * 98 | * @parm inputfd: file descriptor of the file that must be timestamped 99 | * @parm letter: one letter name of the timestamped stream (0 if unused) 100 | * @parm outputfilter: filter to use to output the timestamped stream 101 | */ 102 | void watch(int inputfd, AbstractFilter *outputfilter, char letter=0) 103 | { 104 | FD_SET(inputfd,&watcher); 105 | if(inputfd>=max) 106 | max=inputfd+1; 107 | 108 | watched.push_back(info(inputfd,outputfilter,letter,true)); 109 | } 110 | 111 | /** 112 | * reset the time stamp 113 | */ 114 | void resetTimeStamp() 115 | { 116 | gettimeofday(&tvStart,NULL); 117 | } 118 | 119 | /** 120 | * obtain the current time stamp 121 | * 122 | * @return the current timestamp (for external use) 123 | */ 124 | struct timeval getTimeStamp() 125 | { 126 | gettimeofday(&tv,NULL); 127 | tv.tv_usec-=tvStart.tv_usec; 128 | tv.tv_sec-=tvStart.tv_sec; 129 | if(tv.tv_usec<0) 130 | { 131 | tv.tv_sec-=1; 132 | tv.tv_usec+=1000000; 133 | } 134 | 135 | return tv; 136 | } 137 | 138 | /** 139 | * loop that waits for data on one of the watched files 140 | * and timestamps each line read from these files 141 | * 142 | * the loop ends when all watched files are closed 143 | * 144 | * should be called from a separate thread of process (in most cases) 145 | */ 146 | void timeStampLines() 147 | { 148 | fd_set tmp; 149 | int result,watchDog=0; 150 | 151 | while (watched.size()) 152 | { 153 | tmp=watcher; 154 | 155 | // wait for data to become available on one of the watched files 156 | result=select(max,&tmp,NULL,NULL,NULL); 157 | 158 | if(result<0) 159 | { 160 | if(++watchDog<10) 161 | continue; 162 | else 163 | { 164 | cout << "Error in TimeStamper::timeStampLines(), select() keeps returning errors, exiting." << endl; 165 | break; 166 | } 167 | } 168 | 169 | watchDog=0; 170 | 171 | for(size_t i=0;i=max) 195 | max=watched[i].inputdescr+1; 196 | } 197 | else 198 | ++i; 199 | } 200 | } 201 | 202 | 203 | if(addEOFLine) 204 | { 205 | const char *lastLine="EOF\n"; 206 | 207 | if(incompleteLineSent) 208 | watched[0].write("\n",strlen("\n")); 209 | 210 | prepareTimeStamp(0); 211 | watched[0].write(tstampbuffer,tstampsize); 212 | watched[0].write(lastLine,strlen(lastLine)); 213 | } 214 | } 215 | 216 | /** 217 | * communicate the current CPU time to the time stamper 218 | * 219 | * must only be called from another thread than the one running 220 | * timeStampLines() !! 221 | */ 222 | void setCPUtimeFromAnotherThread(float cputime) 223 | { 224 | pthread_mutex_lock(&cputimeMutex); 225 | lastKnownCPUtime=cputime; 226 | pthread_mutex_unlock(&cputimeMutex); 227 | } 228 | 229 | protected: 230 | 231 | /** 232 | * get the current time and store the ascii representation of the 233 | * time stamp in tstampbuffer (tstampsize will contain the number of 234 | * characters of the representation) 235 | * 236 | * @parm name=one letter name of the watched file (0 if unused) 237 | */ 238 | void prepareTimeStamp(char name) 239 | { 240 | float cputimeCopy; 241 | 242 | getTimeStamp(); 243 | pthread_mutex_lock(&cputimeMutex); 244 | cputimeCopy=lastKnownCPUtime; 245 | pthread_mutex_unlock(&cputimeMutex); 246 | 247 | // store time stamp in tstampbuffer 248 | if(withCPUtime) 249 | { 250 | // CPU time+Wall Clock time 251 | if(name) 252 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 253 | #if WSIZE==32 254 | "%c%.2f/%d.%02d\t", 255 | #else 256 | "%c%.2f/%ld.%02ld\t", 257 | #endif 258 | name,cputimeCopy,tv.tv_sec,tv.tv_usec/10000); 259 | else 260 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 261 | #if WSIZE==32 262 | "%.2f/%d.%02d\t", 263 | #else 264 | "%.2f/%ld.%02ld\t", 265 | #endif 266 | cputimeCopy, 267 | tv.tv_sec,tv.tv_usec/10000); 268 | } 269 | else 270 | { 271 | // no CPU time 272 | if(name) 273 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 274 | #if WSIZE==32 275 | "%c%d.%02d\t", 276 | #else 277 | "%c%ld.%02ld\t", 278 | #endif 279 | name,tv.tv_sec,tv.tv_usec/10000); 280 | else 281 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 282 | #if WSIZE==32 283 | "%d.%02d\t", 284 | #else 285 | "%ld.%02ld\t", 286 | #endif 287 | tv.tv_sec,tv.tv_usec/10000); 288 | } 289 | 290 | } 291 | 292 | private: 293 | /** 294 | * read data available on watched file with index id (in the watched 295 | * vector) and output the timestamp stream 296 | * 297 | * @return false on EOF 298 | */ 299 | bool readFrom(int id) 300 | { 301 | char buffer[1024]; 302 | 303 | int size=read(watched[id].inputdescr,buffer,sizeof(buffer)); 304 | 305 | // PTY seem to be special (this is a quick fix that must be cleaned ???) 306 | if(size<0) 307 | return false; // ??? 308 | 309 | if(size<0) 310 | throw runtime_error(string("TimeStamper::readFrom(): read failed: ") 311 | +strerror(errno)); 312 | 313 | if(size==0) 314 | return false; // indicate EOF 315 | 316 | // create the time stamp once for all the lines we read 317 | prepareTimeStamp(watched[id].name); 318 | 319 | if(watched[id].EOLBefore) 320 | { 321 | watched[id].write(tstampbuffer,tstampsize); 322 | watched[id].EOLBefore=false; 323 | } 324 | 325 | char *s=buffer; 326 | char *eol; 327 | 328 | // split into lines 329 | while (size>0 && (eol=(char*)memchr(s,'\n',size))!=NULL) 330 | { 331 | // output up to EOL included 332 | watched[id].write(s,eol-s+1); 333 | size-=eol-s+1; 334 | s=eol+1; 335 | 336 | if(size>0) 337 | watched[id].write(tstampbuffer,tstampsize); 338 | else 339 | watched[id].EOLBefore=true; 340 | } 341 | 342 | // output the last incomplete line 343 | if(size>0) 344 | { 345 | watched[id].write(s,size); 346 | incompleteLineSent=true; 347 | } 348 | else 349 | incompleteLineSent=false; 350 | 351 | return true; 352 | } 353 | 354 | private: 355 | bool withCPUtime; // do we display CPU time in the timestamp ? 356 | 357 | float lastKnownCPUtime; // current CPU time (provided by an external source) 358 | pthread_mutex_t cputimeMutex; // a mutex to protect access to cputime 359 | 360 | struct timeval tvStart,tv; // first timestamp and current timestamp 361 | 362 | int max; // max(fd)+1 for select 363 | fd_set watcher; // set of watched file descriptors for use by select 364 | 365 | // buffer that contains the ascii representation of the timestamp 366 | char tstampbuffer[64]; // a buffer to output the time stamps 367 | int tstampsize; // size of the timestamp 368 | 369 | bool incompleteLineSent; // true iff the last line we sent didn't have an EOL 370 | 371 | bool addEOFLine; // true if we must add an 'EOF' line at the end of output 372 | 373 | /** 374 | * internal information kept on each file to be watched 375 | */ 376 | struct info 377 | { 378 | bool filteredOutput; 379 | int inputdescr; // file descriptor to watch 380 | int outputdescr; // file descriptor to use to output the timestamped stream (when filteredOutput is false) 381 | AbstractFilter *outputfilter; // filter to write to (when filteredOutput is true) 382 | char name; // a letter that identifies the watched file 383 | bool EOLBefore; // true iff the first character we read is the start of 384 | // a new line 385 | 386 | info(int inputfd, int outputfd, char letter, bool lineStart) 387 | { 388 | filteredOutput=false; 389 | inputdescr=inputfd; 390 | outputdescr=outputfd; 391 | name=letter; 392 | EOLBefore=lineStart; 393 | } 394 | 395 | info(int inputfd, AbstractFilter *filter, char letter, bool lineStart) 396 | { 397 | filteredOutput=true; 398 | inputdescr=inputfd; 399 | outputfilter=filter; 400 | name=letter; 401 | EOLBefore=lineStart; 402 | } 403 | 404 | void write(const char *buffer, int len) 405 | { 406 | if(filteredOutput) 407 | outputfilter->write(buffer,len); 408 | else 409 | systemWrite(outputdescr,buffer,len); 410 | } 411 | 412 | /** 413 | * handle partial writes and EINTR 414 | */ 415 | void systemWrite(int fd, const char *buf, size_t len) 416 | { 417 | const char *p=buf; 418 | int n; 419 | 420 | do 421 | { 422 | n=::write(fd,p,len); 423 | if(n<0) 424 | { 425 | if(errno==EINTR) 426 | continue; 427 | 428 | perror("write failed: "); 429 | break; 430 | } 431 | 432 | len-=n; 433 | p+=n; 434 | } 435 | while(len); 436 | } 437 | }; 438 | 439 | vector watched; // list of files we watch 440 | }; 441 | 442 | #endif 443 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/aeatk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * aeatk.c 3 | * 4 | * Created on: May 7, 2014 5 | * Author: sjr 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | 15 | /** 16 | * This function is called by the timerThread at the end of updating runsolvers internal 17 | * time measure and will send a message to the port on the local machine. 18 | * 19 | * Written by Stephen Ramage 20 | */ 21 | void writeCPUTimeToSocket(double cpuTime) { 22 | 23 | static char* portstr = getenv("AEATK_PORT"); 24 | 25 | static int noMessageDisplay = 0; 26 | 27 | if (portstr == NULL) { 28 | if (noMessageDisplay == 0) { 29 | noMessageDisplay++; 30 | printf( 31 | "[AEATK] No environment variable \"AEATK_PORT\" detected not sending updates\n\n"); 32 | } 33 | return; 34 | } 35 | 36 | //Safely convert port to int 37 | int port = strtol(portstr, NULL, 10); 38 | 39 | if (port < 1024 || port > 65535) { 40 | //Invalid port, probably nothing 41 | 42 | if (noMessageDisplay == 0) { 43 | noMessageDisplay++; 44 | printf( 45 | "[AEATK] Invalid port set in \"AEATK_PORT\" must be in [1024, 65535]\n\n"); 46 | } 47 | return; 48 | 49 | } 50 | 51 | static struct sockaddr_in servaddr; 52 | 53 | static double updateFreqDbl = 1; 54 | static int lastUpdate = -1; 55 | 56 | static int sockfd = -1; 57 | 58 | static char* updateFreq = getenv("AEATK_CPU_TIME_FREQUENCY"); 59 | 60 | if (sockfd == -1) { 61 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 62 | 63 | bzero(&servaddr, sizeof(servaddr)); 64 | servaddr.sin_family = AF_INET; 65 | servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 66 | servaddr.sin_port = htons(port); 67 | 68 | } 69 | 70 | if (updateFreq != NULL) { 71 | //Runsolver won't actually call this function faster than every 2 seconds 72 | //But we set it to 1 second anyway 73 | updateFreqDbl = strtod(updateFreq, NULL); 74 | 75 | if (updateFreqDbl < 1) { 76 | updateFreqDbl = 1; 77 | } 78 | } 79 | 80 | if ((time(NULL) - lastUpdate) > updateFreqDbl) { 81 | lastUpdate = time(NULL); 82 | 83 | static char buf[100]; 84 | 85 | int length = sprintf(buf, "%f\n", cpuTime); 86 | 87 | //Not sure if MSG_DONTWAIT flag is appropriate but it didn't seem to matter when I tried a few times 88 | 89 | if (noMessageDisplay >= 2) { 90 | noMessageDisplay++; 91 | printf( 92 | "[AEATK] Sending CPUTime updates to 127.0.0.1 on port %d every %.3f seconds, last time %.3f \n\n", 93 | port, updateFreqDbl, cpuTime); 94 | } 95 | 96 | sendto(sockfd, buf, length, 0, (struct sockaddr*) &servaddr, 97 | sizeof(servaddr)); 98 | return; 99 | } 100 | 101 | return; 102 | } 103 | 104 | void updateCores() { 105 | 106 | char* set_affinity = getenv("AEATK_SET_TASK_AFFINITY"); 107 | 108 | if ((set_affinity == NULL) || strcmp(set_affinity, "1") != 0) { 109 | printf( 110 | "[AEATK] No environment variable \"AEATK_SET_TASK_AFFINITY\" detected, cores will be treated normally\n\n"); 111 | return; 112 | 113 | } 114 | 115 | char* taskstr = getenv("AEATK_CONCURRENT_TASK_ID"); 116 | 117 | if (taskstr == NULL) { 118 | printf( 119 | "[AEATK] No environment variable \"AEATK_CONCURRENT_TASK_ID\" detected, cores are treated normally\n\n"); 120 | return; 121 | 122 | } 123 | 124 | unsigned int taskid = strtoul(taskstr, NULL, 10); 125 | 126 | printf( 127 | "[AEATK] This version of runsolver restricts subprocesses to only one core when \"AEATK_CONCURRENT_TASK_ID\" is set.\n"); 128 | 129 | vector cores2; 130 | 131 | getAllocatedCoresByProcessorOrder(cores2); 132 | 133 | if (taskid >= cores2.size()) { 134 | cout << "[AEATK] taskid: " << taskid 135 | << " is greater than the number of cores we have available cores: " 136 | << cores2.size() << " affinity: "; 137 | 138 | printAllocatedCores(cout, cores2); 139 | 140 | cout << " something is wrong, exiting" << endl; 141 | exit(1); 142 | } 143 | 144 | vector cores; 145 | cores.push_back(cores2[taskid]); 146 | 147 | cpu_set_t mask = affinityMask(cores); 148 | if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) != 0) { 149 | perror("sched_setaffinity failed: "); 150 | cout << "[AEATK] Couldn't set affinity " << endl; 151 | exit(1); 152 | } 153 | 154 | return; 155 | } 156 | 157 | 158 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/runsolver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/runsolver/runsolver-3.3.4-patched/src/runsolver -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/runsolver.d: -------------------------------------------------------------------------------- 1 | runsolver.d runsolver.o: runsolver.cc Cores.hh SignalNames.hh ProcessList.hh \ 2 | CircularBufferFilter.hh TimeStamper.hh ProcessTree.hh ProcessData.hh \ 3 | ProcessHistory.hh aeatk.c 4 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.3.4-patched/src/vlineSplitter.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | using namespace std; 32 | 33 | int main(int argc, char **argv) 34 | { 35 | string s,timestamp; 36 | bool withTimestamp; 37 | 38 | withTimestamp=argc==2 && strcmp(argv[1],"--timestamp")==0; 39 | 40 | try 41 | { 42 | while(cin.good()) 43 | { 44 | if (withTimestamp) 45 | { 46 | cin >> timestamp; 47 | cin.get(); // skip tabulation 48 | 49 | if (!cin.good()) 50 | break; 51 | } 52 | 53 | getline(cin,s); 54 | 55 | if (!cin.good() && s.length()==0) 56 | break; 57 | 58 | // we're only concerned by a "v " line 59 | if (s.length()>=2 && s[0]=='v' && s[1]==' ') 60 | { 61 | istringstream f(s); 62 | string word; 63 | int len=0; 64 | 65 | f >> word; // skip "v " 66 | 67 | while (f.good()) 68 | { 69 | // read a literal 70 | word=""; 71 | f >> word; 72 | if (word=="") 73 | break; 74 | 75 | if (len==0) 76 | { 77 | if (withTimestamp) 78 | cout << timestamp << "\t"; 79 | cout << "v"; 80 | } 81 | 82 | cout << " " << word; 83 | len+=word.length(); 84 | 85 | if (len>100) 86 | { 87 | cout << endl; 88 | len=0; 89 | } 90 | } 91 | 92 | if (len!=0) 93 | cout << endl; 94 | 95 | s.clear(); 96 | } 97 | else 98 | { 99 | // copy 100 | if (withTimestamp) 101 | cout << timestamp << "\t"; 102 | cout << s << endl; 103 | } 104 | } 105 | } 106 | catch (exception &e) 107 | { 108 | cout.flush(); 109 | cerr << "\n\tUnexpected exception :\n"; 110 | cerr << "\t" << e.what() << endl; 111 | exit(1); 112 | } 113 | } 114 | 115 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/Changelog: -------------------------------------------------------------------------------- 1 | version 3.4.0 2017-08-12 2 | 3 | - use (and require) prctl(PR_SET_CHILD_SUBREAPER,...) (available since Linux 3.4) 4 | - fixed incorrect parsing of SwapFree/SwapTotal 5 | 6 | version 3.3.7 2016- 7 | 8 | - introduction of a new memory limit (-R, --rss-swap-limit) to cope with programs that map a lot of virtual memory but actually use only a portion of it (such as Java). This limit is set on the sum of RSS (Resident Set Size, or in other words, amount of RAM used) and swap. 9 | 10 | - renaming of (-M, --mem-limit) as (-V, --vsize-limit). (-M, --mem-limit) becomes deprecated because its name is ambiguous. It will be removed in a future release. 11 | 12 | version 3.3.6 2016- 13 | 14 | - introduction of the --sig option to select which signal to send to the solver 15 | 16 | - introduction of the --bin-var option to ease the transmission of 17 | the statistics to a calling program 18 | 19 | - introduction of a separate Watcher class, in charge of watching the processes 20 | 21 | - added a --watchdog option, in order to kill runsolver after a given delay (for debugging) 22 | 23 | - fixed a bug which caused runsolver to kill itself sometimes just after the solver end 24 | 25 | version 3.3.5 2015-02-03 26 | 27 | - fixed problem with concurrent access to process tree, which caused some 28 | random crashes 29 | 30 | - removed the interception of system calls, which is unused, too costly and 31 | complicates compilation. 32 | 33 | version 3.3.4 2013-11-28 34 | 35 | - fix compilation problems on Ubuntu and get rid of compilation warnings 36 | 37 | version 3.3.3 2013-07-19 38 | 39 | - fixed a bug which occurs on very short executions of the solver 40 | (such as `echo test`). In such a case, runsolver did not have the time to 41 | get the correct process group id (i.e. the watcher read /proc 42 | before the child could run setpgid()) and in the end runsolver 43 | signalled its own process group and killed itself. Besides, the 44 | default ProcessTree::currentRootPID was set to 1, which means that 45 | we could kill our whole session (kill(-1,...)) 46 | 47 | - fixed 2 bugs in timestamping: the CPU time didn't take into 48 | account the lostCPUtime and the EOF line didn't appear on its own 49 | line when the solver didn't print an EOL at the end. 50 | 51 | version 3.3.2 2013-04-19 52 | 53 | - add option -v to save the most relevant information (times, ...) 54 | in a separate file which is easy to parse (VAR=VALUE format) 55 | 56 | - display option --core in the help message and clarified the core 57 | numbering scheme used by this option 58 | 59 | - new option --phys-core to select cores by their physical id 60 | 61 | - new option --add-eof: 62 | 63 | when timestamps are used, request to add an 'EOF' line at the 64 | end of the solver output 65 | 66 | version 3.3.1 2011-06-12 67 | 68 | - make sure to kill processes which are stopped and in their own 69 | session 70 | 71 | version 3.3.0 2011-05-01 72 | 73 | - support for core information and selection 74 | - fixed a bug in case of input redirection (runsolver cmd < file) 75 | - use long instead of int for memory limits 76 | 77 | version 3.2.9a 2010-03-09 78 | 79 | - release under the GPL 80 | 81 | version 3.2.9 2009-03-27 82 | 83 | - when the main process terminates, kill each children that could remain 84 | 85 | version 3.2.8 2009-03-27 86 | 87 | - fixed a bug in the --output-limit start,max option 88 | 89 | when the output size was between start and max, "start" bytes of 90 | garbage was appended to the ouput. 91 | 92 | - --output-limit now implies --timestamp 93 | 94 | version 3.2.7 2009-03-26 95 | 96 | - added the --cleanup-ipc-queues option 97 | 98 | version 3.2.6 2009-03-24 99 | 100 | - added support for identification of heavy processes run by another user 101 | 102 | version 3.2.5 2007-05-20 103 | 104 | - the stack size command line argument was incorrectly understood as a 105 | limit in GiB instead of a limit in MiB. 106 | 107 | version 3.2.4 2007-05-9 108 | 109 | - add a test to indicate if the solver has dumped a core (when 110 | supported by the system) 111 | 112 | version 3.2.3 2007-04-16 113 | 114 | - lostCPUTime must be taken into account when deciding when the solver 115 | times out 116 | 117 | - added tests to check that fgets() correctly reads the /proc/pid/stat 118 | and statm files in ProcessData::read(). It is hoped this will fix some 119 | incoherent data read such as: 120 | 121 | [startup+402.301 s] 122 | /proc/loadavg: 1.00 0.99 0.91 2/78 12763 123 | /proc/meminfo: memFree=1564840/2055920 swapFree=4169436/4192956 124 | [pid=12688] ppid=12686 vsize=19880 CPUtime=402.13 125 | /proc/12688/stat : 12688 (cmusat) R 12686 12688 12410 0 -1 4194304 44325 0 0 0 40175 38 0 0 25 0 1 0 323084685 20357120 4250 18446744073709551615 134512640 135508737 4294956704 18446744073709551615 135092575 0 0 4096 35 0 0 0 17 1 0 0 126 | /proc/12688/statm: 4970 4251 119 243 0 4724 0 127 | Current children cumulated CPU time (s) 402.13 128 | Current children cumulated vsize (KiB) 19880 129 | 130 | Solver just ended. Dumping a history of the last processes samples 131 | 132 | [startup+402.503 s] 133 | /proc/loadavg: 1.00 0.99 0.91 1/77 12763 134 | /proc/meminfo: memFree=1679792/2055920 swapFree=4169436/4192956 135 | [pid=12688] ppid=-1 vsize=0 CPUtime=0 136 | /proc/12688/stat : 7 (events/1) S 1 0 0 0 -1 33088 0 0 0 0 0 5 0 0 5 -10 1 0 27 0 0 18446744073709551615 0 0 0 0 0 0 2147483647 65536 0 18446744073709551615 0 0 17 1 0 0 137 | /proc/12688/statm: 0 0 0 0 0 0 0 138 | Current children cumulated CPU time (s) 0 139 | Current children cumulated vsize (KiB) 0 140 | 141 | Notice that in the last sample, we fetch information about process 142 | 12688 but actually get information about pid 7 (and ppid is set to 143 | -1). The most likely explanation is that the fopen("/proc/pid/stat") 144 | succeeds but the following fgets fails because the file has 145 | disappeared. 146 | 147 | 148 | version 3.2.2 2007-04-13 149 | 150 | - added code to detect when the time of a child is not reported to its 151 | parent. When this occurs, the 'lost time' is recorded and added at the 152 | end. 153 | 154 | - minors changes in the messages that are printed when the time of a 155 | child is not reported to its parent. 156 | 157 | version 3.2.1 2007-02-27 158 | 159 | - added option --wall-clock-limit to deal with frozen solvers 160 | 161 | - minor changes in the timer thread 162 | 163 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/CircularBufferFilter.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _CircularBufferFilter_hh_ 23 | #define _CircularBufferFilter_hh_ 24 | 25 | #include 26 | #include 27 | 28 | using namespace std; 29 | 30 | 31 | class AbstractFilter 32 | { 33 | public: 34 | virtual void write(const char *buffer, int len)=0; 35 | 36 | /** 37 | * handle partial writes and EINTR 38 | */ 39 | void systemWrite(int fd, const char *buf, size_t len) 40 | { 41 | const char *p=buf; 42 | int n; 43 | 44 | do 45 | { 46 | n=::write(fd,p,len); 47 | if(n<0) 48 | { 49 | if(errno==EINTR) 50 | continue; 51 | 52 | perror("write failed: "); 53 | break; 54 | } 55 | 56 | len-=n; 57 | p+=n; 58 | } 59 | while(len); 60 | } 61 | }; 62 | 63 | class NullFilter : public AbstractFilter 64 | { 65 | private: 66 | int fd; 67 | public: 68 | NullFilter(int fd): fd(fd) {} 69 | 70 | virtual void write(const char *buffer, int len) 71 | { 72 | systemWrite(fd,buffer,len); 73 | } 74 | }; 75 | 76 | /** 77 | * This filter enforces a limit on an output file size. When the file 78 | * exceeds the limit, only the first and last bytes of output are 79 | * saved in the file. 80 | * 81 | * This filter transmits directly to file descriptor fd the first 82 | * activateSize bytes and then it only transmits the last 83 | * maxSize-activateSize bytes. 84 | * 85 | * TODO ??? 86 | * 87 | * - we currently use a circular buffer in memory to do the job. We 88 | may instead work directly on the file, using lseek to rewind to 89 | position activateSize as soon as the file size exceeds 90 | maxSize. At the end, we have to reorder the bytes at the end of 91 | the file. This may save memory but requires to be able to lseek 92 | on the file. 93 | * 94 | * - the last part of the file to which we output doesn't necessarily 95 | start at the beginning of a line. This may cause problem in some 96 | applications. 97 | */ 98 | class CircularBufferFilter : public AbstractFilter 99 | { 100 | private: 101 | unsigned long long int total; // total number of bytes sent to this filter 102 | unsigned long long int activateSize,maxSize,bufferSize; 103 | 104 | char *data; // circular buffer 105 | unsigned int w; // position where to write in the circular buffer 106 | 107 | int fd; // file descriptor to write to 108 | 109 | public: 110 | CircularBufferFilter() 111 | { 112 | data=NULL; 113 | } 114 | 115 | CircularBufferFilter(int fd, 116 | unsigned long long int activateSize, 117 | unsigned long long int maxSize) 118 | { 119 | data=NULL; 120 | setup(fd,activateSize,maxSize); 121 | } 122 | 123 | void setup(int fd, 124 | unsigned long long int activateSize, 125 | unsigned long long int maxSize) 126 | { 127 | this->fd=fd; 128 | this->activateSize=activateSize; 129 | this->maxSize=maxSize; 130 | bufferSize=maxSize-activateSize; 131 | total=0; 132 | } 133 | 134 | ~CircularBufferFilter() 135 | { 136 | flush(); 137 | } 138 | 139 | virtual void write(const char *buffer, int len) 140 | { 141 | total+=len; 142 | 143 | if (totalbufferSize-w) 169 | n=bufferSize-w; 170 | 171 | memcpy(data+w,buffer+r,n); 172 | len-=n; 173 | r+=n; 174 | w+=n; 175 | if (w>=bufferSize) 176 | w=0; 177 | } while(len>0); 178 | } 179 | } 180 | 181 | /** 182 | * normally, this should only be called by the destructor. 183 | * 184 | * remember that the destructor is not called if we are an auto 185 | * object (local variable) and if we call exit() 186 | */ 187 | void flush() 188 | { 189 | if (!data) 190 | return; 191 | 192 | char msg[512]; 193 | 194 | if (total<=maxSize) 195 | systemWrite(fd,data,total-activateSize); 196 | else 197 | { 198 | snprintf(msg,sizeof(msg), 199 | "\n" 200 | "###########################################################\n" 201 | "# A total of %llu bytes were output by the program.\n" 202 | "# This exceeds the hard limit that is enforced.\n" 203 | "# Only the %llu first bytes are saved in this file before\n" 204 | "# this point and only the %llu last bytes are saved after\n" 205 | "# this point. A total of %llu bytes are lost.\n" 206 | "###########################################################\n", 207 | total,activateSize,bufferSize,total-maxSize); 208 | systemWrite(fd,msg,strlen(msg)); 209 | systemWrite(fd,data+w,bufferSize-w); 210 | systemWrite(fd,data,w); 211 | } 212 | } 213 | }; 214 | 215 | // Local Variables: 216 | // mode: C++ 217 | // End: 218 | #endif 219 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/Cores.hh: -------------------------------------------------------------------------------- 1 | #ifndef _Cores_hh_ 2 | #define _Cores_hh_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | /** 10 | * get the list of cores available on the system 11 | * 12 | * if physicalView is true, "list" will contain the id of existing 13 | * cores in increasing order (from 0 to n-1). 14 | * 15 | * if physicalView is false, "list" will contain the id of existing 16 | * cores ordered by the processor to which they belong. For example, 17 | * list could contain 0,2,4,6,1,3,5,7 if the first processor contains 18 | * cores 0,2,4,6 and the second processor contains cores 1,3,5,7. 19 | */ 20 | void getExistingCores(vector &list, bool physicalView) 21 | { 22 | char fname[128]; 23 | string buffer; 24 | ifstream f; 25 | cpu_set_t cores; 26 | 27 | CPU_ZERO(&cores); 28 | 29 | list.clear(); 30 | 31 | for(unsigned int cpu=0;cpu0) 54 | --len; 55 | 56 | int id=0,mask; 57 | for(int i=len;i>=0;--i,id+=4) 58 | if(buffer[i]!='0' && buffer[i]!=',') 59 | { 60 | if(buffer[i]>='0' && buffer[i]<='9') 61 | mask=buffer[i]-'0'; 62 | else 63 | if(buffer[i]>='a' && buffer[i]<='f') 64 | mask=10+buffer[i]-'a'; 65 | else 66 | if(buffer[i]>='A' && buffer[i]<='F') 67 | mask=10+buffer[i]-'A'; 68 | else 69 | throw runtime_error("invalid character in cpu mask"); 70 | 71 | for(int j=0;j<4;++j) 72 | { 73 | if((mask & 1) && !CPU_ISSET(id+j,&cores)) 74 | { 75 | list.push_back(id+j); 76 | CPU_SET(id+j,&cores); // don't count it twice! 77 | } 78 | 79 | mask>>=1; 80 | } 81 | } 82 | } // if(CPU_ISET(...)) 83 | } 84 | 85 | 86 | 87 | /** 88 | * return the list of cores allocated to this process, ordered by 89 | * physical cpu 90 | */ 91 | void getAllocatedCoresByProcessorOrder(vector &allocatedCores) 92 | { 93 | char fname[128]; 94 | string buffer; 95 | ifstream f; 96 | cpu_set_t affinityMask; 97 | 98 | allocatedCores.clear(); 99 | 100 | sched_getaffinity(0,sizeof(cpu_set_t),&affinityMask); 101 | 102 | for(unsigned int cpu=0;cpu0) 118 | --len; 119 | 120 | int id=0,mask; 121 | for(int i=len;i>=0;--i,id+=4) 122 | if(buffer[i]!='0' && buffer[i]!=',') 123 | { 124 | if(buffer[i]>='0' && buffer[i]<='9') 125 | mask=buffer[i]-'0'; 126 | else 127 | if(buffer[i]>='a' && buffer[i]<='f') 128 | mask=10+buffer[i]-'a'; 129 | else 130 | if(buffer[i]>='A' && buffer[i]<='F') 131 | mask=10+buffer[i]-'A'; 132 | else 133 | throw runtime_error("invalid character in cpu mask"); 134 | 135 | for(int j=0;j<4;++j) 136 | { 137 | if((mask & 1) && CPU_ISSET(id+j,&affinityMask)) 138 | { 139 | allocatedCores.push_back(id+j); 140 | CPU_CLR(id+j,&affinityMask); // don't count it twice! 141 | } 142 | 143 | mask>>=1; 144 | } 145 | } 146 | } // if(CPU_ISET(...)) 147 | } 148 | 149 | /** 150 | * get the list of cores allocated to this process 151 | */ 152 | void getAllocatedCores(vector &list, pid_t pid=0) 153 | { 154 | cpu_set_t mask; 155 | list.clear(); 156 | 157 | sched_getaffinity(pid,sizeof(cpu_set_t),&mask); 158 | 159 | for(unsigned int i=0;i &list) 169 | { 170 | size_t end; 171 | 172 | for(size_t beg=0;beg &cores) 192 | { 193 | cpu_set_t mask; 194 | 195 | CPU_ZERO(&mask); 196 | for(size_t i=0;i. 18 | */ 19 | 20 | 21 | 22 | #ifndef _ExecutionSummary_hh_ 23 | #define _ExecutionSummary_hh_ 24 | 25 | struct ExecutionSummary 26 | { 27 | int byteOrder; // used to detect byte ordering if needed (=0x01020304) 28 | int version; // version number of this format 29 | char runsolverVersion[16]; // version of runsolver 30 | float wcTime; // wall-clock time in seconds 31 | float cpuTime; // CPU time in seconds (userTime+systemTime) 32 | float userTime; // user CPU time in seconds 33 | float systemTime; // system CPU time in seconds 34 | float cpuUsage; // cpuTime/wcTime (in percent) 35 | long maxVM; // maximum virtual memory used in KiB 36 | long maxMem; // maximum memory used in KiB 37 | bool timeOut; // did the solver exceed the time limit? 38 | bool memOut; // did the solver exceed the memory limit? 39 | 40 | 41 | ExecutionSummary() 42 | { 43 | set(); 44 | } 45 | 46 | void set() 47 | { 48 | version=3; 49 | byteOrder=0x01020304; 50 | } 51 | 52 | void reset() 53 | { 54 | byteOrder=0; 55 | } 56 | 57 | bool ok() const 58 | { 59 | return byteOrder==0x01020304 && version==3; 60 | } 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/Makefile: -------------------------------------------------------------------------------- 1 | VERSION=3.4.0 2 | #SVNVERSION=`svnversion .` 3 | SVNVERSION=$(word 2,$$Rev: 3018 $$) 4 | DEBUG=-g 5 | #DEBUG=-O3 -g 6 | 7 | STATIC= 8 | #STATIC=-static 9 | 10 | WSIZE:=$(shell if [ `uname -m` = 'x86_64' ] ; then echo 64; else echo 32; fi ) 11 | 12 | CFLAGS=-std=c++11 -DWITH_NUMA -Dtmpdebug -Wall -DVERSION=\"$(VERSION)\" -DSVNVERSION=\"$(SVNVERSION)\" -DWSIZE=$(WSIZE) 13 | LDFLAGS= $(STATIC) -Wl,--build-id 14 | LIBS=-lnuma 15 | 16 | ifneq ($(findstring alineos.net,$(HOSTNAME)),) 17 | # if needed, path to the dynamic library we use 18 | LDFLAGS+=-Wl,-rpath,$(HOME)/tools-centos7/lib64 19 | endif 20 | 21 | SRC=runsolver.cc SignalNames.cc 22 | OBJ=$(SRC:.cc=.o) 23 | 24 | all:runsolver 25 | 26 | install: runsolver 27 | cp runsolver $(INSTROOT)/usr/bin 28 | 29 | include $(SRC:.cc=.d) 30 | 31 | .cc.o: 32 | g++ $(CFLAGS) $(DEBUG) -c $*.cc 33 | 34 | runsolver: $(OBJ) 35 | g++ $(LDFLAGS) $(DEBUG) -o $@ $^ -pthread $(LIBS) 36 | 37 | testlimit: testlimit.cc 38 | g++ -o testlimit testlimit.cc 39 | 40 | testthread: testthread.cc 41 | g++ -o testthread testthread.cc -pthread 42 | 43 | .PHONY: clean realclean archive 44 | 45 | tar: /tmp/runsolver-$(VERSION).tar.bz2 46 | archive: /tmp/runsolver-$(VERSION).tar.bz2 47 | 48 | /tmp/runsolver-$(VERSION).tar.bz2: realclean $(SRC) Makefile 49 | sed -i -e 's/^Version:.*/Version:\t'$(VERSION)'/' runsolver.spec 50 | tar cvjf /tmp/runsolver-$(VERSION).tar.bz2 -C ../.. runsolver/src --exclude .svn 51 | 52 | rpm: /tmp/runsolver-$(VERSION).tar.bz2 53 | rpmbuild -tb /tmp/runsolver-$(VERSION).tar.bz2 54 | 55 | srpm: /tmp/runsolver-$(VERSION).tar.bz2 56 | rpmbuild -ts /tmp/runsolver-$(VERSION).tar.bz2 57 | 58 | clean: 59 | rm -f runsolver $(OBJ) *.class testlimit testtimestamper vlineSplitter testProcessTree runtestlimit testthread 60 | 61 | realclean: clean 62 | rm -f *.d *~ 63 | 64 | 65 | %.d: %.cc 66 | $(SHELL) -ec '$(CC) -MM $(CFLAGS) $< \ 67 | | sed -e '\''s/$*\.o[ :]*/$@ &/g'\'' > $@' 68 | 69 | 70 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/Observer.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _Observer_hh_ 23 | #define _Observer_hh_ 24 | 25 | /** 26 | * a class to watch file descriptors and wait for data to become 27 | * available on one of them 28 | * 29 | */ 30 | class Observer 31 | { 32 | private: 33 | vector desc; 34 | fd_set readable; 35 | public: 36 | /** 37 | * add a file descriptor to watch 38 | */ 39 | void add(int fd) 40 | { 41 | desc.push_back(fd); 42 | } 43 | 44 | /** 45 | * remove a file descriptor from the list of file descriptors to watch 46 | * 47 | * doit être appele avant de fermer la socket 48 | */ 49 | void remove(int fd) 50 | { 51 | vector::iterator i=find(desc.begin(),desc.end(),fd); 52 | if (i!=desc.end()) 53 | desc.erase(i); 54 | } 55 | 56 | /** 57 | * tell if there is some file descriptor left to watch 58 | */ 59 | bool empty() 60 | { 61 | return desc.empty(); 62 | } 63 | 64 | /** 65 | * wait for data to become available on one of the file descriptor 66 | * that is watched 67 | * 68 | * this is a blocking method 69 | */ 70 | void waitForData() 71 | { 72 | int max=0; 73 | 74 | FD_ZERO(&readable); 75 | 76 | for (int i=0;i. 18 | */ 19 | 20 | 21 | 22 | #ifndef _ProcessData_hh_ 23 | #define _ProcessData_hh_ 24 | 25 | #include 26 | using namespace std; 27 | 28 | /** 29 | * The information we keep on a process 30 | */ 31 | class ProcessData 32 | { 33 | private: 34 | bool valid; // did we collect meaningful data? 35 | 36 | static const unsigned long int clockTicksPerSecond; 37 | 38 | uid_t uid; 39 | gid_t gid; 40 | 41 | pid_t pid,tid,ppid,pgrp; 42 | unsigned long int utime,stime,cutime,cstime; 43 | unsigned long int starttime; 44 | unsigned long int vsize; 45 | 46 | unsigned long int rss,swap; // in kB, see /proc/[pid]/status 47 | 48 | vector children; 49 | 50 | char statLine[1024]; // ??? 51 | char statmLine[1024]; // ??? 52 | 53 | vector allocatedCores; 54 | 55 | bool selected; // a flag to select/unselect processes 56 | 57 | inline void init() 58 | { 59 | valid=false; 60 | pid=-1; 61 | tid=-1; 62 | ppid=-1; 63 | utime=stime=cutime=cstime=0; 64 | vsize=0; 65 | } 66 | 67 | public: 68 | ProcessData() {init();} 69 | 70 | ProcessData(pid_t pid, pid_t tid=0) 71 | { 72 | init(); 73 | read(pid,tid); 74 | } 75 | 76 | ProcessData(const ProcessData &pd) 77 | { 78 | valid=false; 79 | 80 | uid=pd.uid; 81 | gid=pd.gid; 82 | 83 | pid=pd.pid; 84 | tid=pd.tid; 85 | ppid=pd.ppid; 86 | pgrp=pd.pgrp; 87 | utime=pd.utime; 88 | stime=pd.stime; 89 | cutime=pd.cutime; 90 | cstime=pd.cstime; 91 | starttime=pd.starttime; 92 | vsize=pd.vsize; 93 | 94 | statLine[0]=0; 95 | statmLine[0]=0; 96 | 97 | for(size_t i=0;ipid=pid; 116 | this->tid=tid; 117 | 118 | valid=false; 119 | 120 | if (tid) 121 | snprintf(fileName,sizeof(fileName),"/proc/%d/task/%d/stat",pid,tid); 122 | else 123 | snprintf(fileName,sizeof(fileName),"/proc/%d/stat",pid); 124 | 125 | if ((file=fopen(fileName,"r"))!=NULL) 126 | { 127 | struct stat info; 128 | 129 | fstat(fileno(file),&info); 130 | 131 | uid=info.st_uid; 132 | gid=info.st_gid; 133 | 134 | if (fgets(statLine,sizeof(statLine),file)==NULL) 135 | { 136 | #ifdef debug 137 | perror("failed to read stat file"); 138 | #endif 139 | 140 | strcpy(statLine,"-- couldn't read stat file --"); 141 | fclose(file); 142 | 143 | return valid=false; 144 | } 145 | 146 | fclose(file); 147 | } 148 | else 149 | { 150 | #ifdef debug 151 | perror("failed to open stat file"); 152 | #endif 153 | 154 | strcpy(statLine,"-- couldn't open stat file --"); 155 | 156 | return valid=false; 157 | } 158 | 159 | nbFields=sscanf(statLine, 160 | #if WSIZE==32 161 | "%*d " 162 | "%*s " 163 | "%*c " 164 | "%d %d %*d %*d %*d " 165 | "%*u %*u %*u %*u %*u " // lu lu lu lu lu 166 | "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ 167 | "%*d %*d " // ld ld 168 | "%*d " 169 | "%*d " // ld 170 | "%Lu " /* start_time */ 171 | "%lu ", 172 | #else 173 | "%*d " 174 | "%*s " 175 | "%*c " 176 | "%d %d %*d %*d %*d " 177 | "%*u %*u %*u %*u %*u " // lu lu lu lu lu 178 | "%lu %lu %lu %lu " /* utime stime cutime cstime */ 179 | "%*d %*d " // ld ld 180 | "%*d " 181 | "%*d " // ld 182 | "%lu " /* start_time */ 183 | "%lu ", 184 | #endif 185 | &ppid,&pgrp, 186 | &utime, &stime, &cutime, &cstime, 187 | &starttime, 188 | &vsize 189 | ); 190 | 191 | if(nbFields!=8) 192 | { 193 | #ifdef debug 194 | cout << "FAILED TO READ EACH FIELD (got " << nbFields << " fields)\n"; 195 | #endif 196 | 197 | return valid=false; 198 | } 199 | 200 | if (!tid) 201 | { 202 | snprintf(fileName,sizeof(fileName),"/proc/%d/statm",pid); 203 | 204 | if ((file=fopen(fileName,"r"))!=NULL) 205 | { 206 | if (fgets(statmLine,sizeof(statmLine),file)==NULL) 207 | { 208 | #ifdef debug 209 | perror("failed to read statm file"); 210 | #endif 211 | 212 | strcpy(statmLine,"-- couldn't read statm file --"); 213 | fclose(file); 214 | 215 | return valid=false; 216 | } 217 | 218 | fclose(file); 219 | } 220 | else 221 | { 222 | #ifdef debug 223 | perror("failed to open statm file"); 224 | #endif 225 | 226 | strcpy(statmLine,"-- couldn't open statm file --"); 227 | } 228 | } 229 | 230 | if (!tid) 231 | { 232 | // read /proc/%d/status 233 | snprintf(fileName,sizeof(fileName),"/proc/%d/status",pid); 234 | ifstream in(fileName); 235 | string tmp; 236 | int nbFieldsToRead=2; 237 | 238 | while(in.good() && nbFieldsToRead>0) 239 | { 240 | in >> tmp; 241 | if(tmp=="VmRSS:") 242 | { 243 | in >> rss; 244 | --nbFieldsToRead; 245 | } 246 | else 247 | if(tmp=="VmSwap:") 248 | { 249 | in >> swap; 250 | --nbFieldsToRead; 251 | } 252 | getline(in,tmp); 253 | } 254 | 255 | if(nbFieldsToRead!=0) 256 | { 257 | #ifdef debug 258 | cout << "FAILED TO READ EACH FIELD in /proc/" << pid << "/status\n"; 259 | #endif 260 | 261 | return valid=false; 262 | } 263 | } 264 | 265 | getAllocatedCores(); 266 | 267 | return valid=true; 268 | } 269 | 270 | /** 271 | * update data on this process 272 | * 273 | * return false iff the process doesn't exit any more 274 | */ 275 | bool update() 276 | { 277 | return read(pid,tid); 278 | } 279 | 280 | /** 281 | * do we have valid data? 282 | */ 283 | bool isValid() const {return valid;} 284 | 285 | /** 286 | * return the % of CPU used by this process (and its children when 287 | * withChildren is true). The result is between 0 and 1 288 | */ 289 | float percentageCPU(float uptime, bool withChildren=false) const 290 | { 291 | float cputime=stime+utime; 292 | 293 | if (withChildren) 294 | cputime+=cstime+cutime; 295 | 296 | cputime/=clockTicksPerSecond; 297 | 298 | float wctime=uptime-static_cast(starttime)/clockTicksPerSecond; 299 | 300 | if (wctime==0) 301 | return 0; 302 | else 303 | return cputime/wctime; 304 | } 305 | 306 | 307 | bool isTask() const 308 | { 309 | return tid!=0; 310 | } 311 | 312 | 313 | const vector &getChildren() const 314 | { 315 | return children; 316 | } 317 | 318 | void addChild(pid_t child) 319 | { 320 | children.push_back(child); 321 | } 322 | 323 | int getNbChildren() const 324 | { 325 | return children.size(); 326 | } 327 | 328 | pid_t getPIDChild(int i) const 329 | { 330 | return children[i]; 331 | } 332 | 333 | pid_t getppid() const 334 | { 335 | return ppid; 336 | } 337 | 338 | pid_t getProcessGroupId() const 339 | { 340 | return pgrp; 341 | } 342 | 343 | uid_t getUid() const 344 | { 345 | return uid; 346 | } 347 | 348 | void select() 349 | { 350 | selected=true; 351 | } 352 | 353 | void unselect() 354 | { 355 | selected=false; 356 | } 357 | 358 | bool isSelected() const 359 | { 360 | return selected; 361 | } 362 | 363 | float getOverallCPUTime() const 364 | { 365 | // note that cstime and cutime (child system and user time) are 366 | // only updated by the wait call in the parent (this is to say, 367 | // only once the child has terminated). Therefore, we can't rely 368 | // on these variables to limit the global cpu use of a process 369 | // and its children 370 | 371 | return (stime+(float)utime 372 | +cstime+(float)cutime 373 | )/clockTicksPerSecond; 374 | } 375 | 376 | float getOverallUserTime() const 377 | { 378 | // note that cstime and cutime (child system and user time) are 379 | // only updated by the wait call in the parent (this is to say, 380 | // only once the child has terminated). Therefore, we can't rely 381 | // on these variables to limit the global cpu use of a process 382 | // and its children 383 | 384 | return (utime+(float)cutime)/clockTicksPerSecond; 385 | } 386 | 387 | float getOverallSystemTime() const 388 | { 389 | // note that cstime and cutime (child system and user time) are 390 | // only updated by the wait call in the parent (this is to say, 391 | // only once the child has terminated). Therefore, we can't rely 392 | // on these variables to limit the global cpu use of a process 393 | // and its children 394 | 395 | return (stime+(float)cstime)/clockTicksPerSecond; 396 | } 397 | 398 | /** 399 | * return the current vsize in kB 400 | */ 401 | long getVSize() const 402 | { 403 | return vsize/1024; 404 | } 405 | 406 | /** 407 | * return the current memory consumption in kB 408 | */ 409 | long getMemory() const 410 | { 411 | return rss+swap; 412 | } 413 | 414 | /** 415 | * get the list of cores allocated to this process 416 | */ 417 | void getAllocatedCores() 418 | { 419 | //return; // ??? 420 | 421 | cpu_set_t mask; 422 | allocatedCores.clear(); 423 | 424 | sched_getaffinity(pid,sizeof(cpu_set_t),&mask); 425 | 426 | #warning "don't watse time converting to a vector, just keep the cpu_set_t" 427 | for(int i=0;i. 18 | */ 19 | 20 | 21 | 22 | #ifndef _ProcessHistory_hh_ 23 | #define _ProcessHistory_hh_ 24 | 25 | #include 26 | #include "ProcessTree.hh" 27 | 28 | using namespace std; 29 | 30 | /** 31 | * maintains a history of process trees 32 | */ 33 | class ProcessHistory 34 | { 35 | private: 36 | int nbcell; 37 | vector nbitem; 38 | vector history; 39 | 40 | public: 41 | ProcessHistory(int n) 42 | { 43 | nbcell=n; 44 | nbitem.resize(nbcell); 45 | history.resize(2*nbcell); 46 | for(int i=0;i0;++cell) 54 | for(int i=0;i0;++cell) 92 | { 93 | for(int i=0;i=0;--cell) 104 | { 105 | if (nbitem[cell]==0 || 106 | history[2*cell]->getElapsedTime()<=elapsedLimit) 107 | continue; 108 | 109 | history[2*cell]->dumpProcessTree(s); 110 | history[2*cell]->dumpCPUTimeAndVSize(s); 111 | } 112 | 113 | if (nbitem[0]==2) 114 | { 115 | // also dump the most recent 116 | history[1]->dumpProcessTree(s); 117 | history[1]->dumpCPUTimeAndVSize(s); 118 | } 119 | } 120 | 121 | protected: 122 | void drop(ProcessTree *elem) 123 | { 124 | delete elem; 125 | } 126 | }; 127 | 128 | // Local Variables: 129 | // mode: C++ 130 | // End: 131 | #endif 132 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/ProcessList.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _ProcessList_hh_ 23 | #define _ProcessList_hh_ 24 | 25 | #include 26 | 27 | using namespace std; 28 | 29 | /** 30 | * a class to store a list of process IDs 31 | * 32 | * ??? should be optimized !!! 33 | */ 34 | class ProcessList 35 | { 36 | private: 37 | set s; 38 | public: 39 | typedef set::iterator iterator; 40 | 41 | inline void add(pid_t pid) 42 | { 43 | s.insert(pid); 44 | } 45 | 46 | inline void remove(pid_t pid) 47 | { 48 | s.erase(pid); 49 | } 50 | 51 | inline bool contains(pid_t pid) const 52 | { 53 | return s.find(pid)!=s.end(); 54 | } 55 | 56 | iterator begin() const {return s.begin();} 57 | iterator end() const {return s.end();} 58 | }; 59 | 60 | 61 | #endif 62 | 63 | // Local Variables: 64 | // mode: C++ 65 | // End: 66 | 67 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/README: -------------------------------------------------------------------------------- 1 | runsolver Copyright (C) 2010 Olivier ROUSSEL (roussel@cril.univ-artois.fr) 2 | 3 | runsolver is a program meant to control the ressources used by a 4 | solver. Basically, it can be seen as the integration of the time and 5 | ulimit commands, but it has several other features. It is able to 6 | timestamp each line output by a program, is able to handle correctly 7 | multithreads or multiprocesses programs (don't loose the time of the 8 | child even when the parent doesn't call wait()), is able to enforce 9 | strict limits on the memory usage, logs information on each process 10 | generated by the solver and is able to limit the size of the solver 11 | output. 12 | 13 | This program is especially useful when you want to run a program and 14 | strictly control the ressources it uses. 15 | 16 | This program was first used in the competitions of Pseudo-Boolean 17 | solvers (2005) and was later used in the SAT and CSP competitions. 18 | 19 | For now, the code is Linux specific. 20 | 21 | 22 | runsolver is free software, distributed under the terms of the [GNU] General 23 | Public License as published by the Free Software Foundation, 24 | version 3 of the License (or any later version). For more information, 25 | see the file LICENSE-GPL-3.0.txt. 26 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/SignalNames.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | 23 | #include "SignalNames.hh" 24 | 25 | const char *signalNames[]={ 26 | "???", 27 | "SIGHUP", 28 | "SIGINT", 29 | "SIGQUIT", 30 | "SIGILL", 31 | "SIGTRAP", 32 | "SIGABRT", 33 | "SIGBUS", 34 | "SIGFPE", 35 | "SIGKILL", 36 | "SIGUSR1", 37 | "SIGSEGV", 38 | "SIGUSR2", 39 | "SIGPIPE", 40 | "SIGALRM", 41 | "SIGTERM", 42 | "SIGSTKFLT", 43 | "SIGCHLD", 44 | "SIGCONT", 45 | "SIGSTOP", 46 | "SIGTSTP", 47 | "SIGTTIN", 48 | "SIGTTOU", 49 | "SIGURG", 50 | "SIGXCPU", 51 | "SIGXFSZ", 52 | "SIGVTALRM", 53 | "SIGPROF", 54 | "SIGWINCH", 55 | "SIGIO", 56 | "SIGPWR", 57 | "SIGSYS"}; 58 | 59 | 60 | const char *getSignalName(int sig) 61 | { 62 | if (sig>0 && sig<=static_cast(sizeof(signalNames)/sizeof(char *))) 63 | return signalNames[sig]; 64 | else 65 | return "???"; 66 | } 67 | 68 | int getSignalNum(const char *name) 69 | { 70 | std::string uc=name,ucsig; 71 | 72 | for(char &c: uc) 73 | c=toupper(c); 74 | 75 | ucsig="SIG"+uc; 76 | 77 | int nbSig=sizeof(signalNames)/sizeof(char *); 78 | 79 | for(int i=0;i. 18 | */ 19 | 20 | 21 | 22 | #ifndef _SignalNames_hh_ 23 | #define _SignalNames_hh_ 24 | 25 | const char *getSignalName(int sig); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/SignalNames.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/runsolver/runsolver-3.4.0/src/SignalNames.o -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/TimeStamper.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #ifndef _TimeStamper_hh_ 23 | #define _TimeStamper_hh_ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | // if we use the TimeStamper in a threaded program, we may have to use 35 | // mutexes 36 | #include 37 | 38 | #include "CircularBufferFilter.hh" 39 | 40 | using namespace std; 41 | 42 | /** 43 | * a class that intercepts the data on some watched file descriptors 44 | * and adds a timestamp at the beginning of each line. 45 | */ 46 | class TimeStamper 47 | { 48 | public: 49 | TimeStamper(bool withCPUtime=true) : withCPUtime(withCPUtime) 50 | { 51 | // initialize select() data 52 | FD_ZERO(&watcher); 53 | max=1; 54 | 55 | // in case the user forgets to call it 56 | resetTimeStamp(); 57 | 58 | lastKnownCPUtime=0; 59 | pthread_mutex_init(&cputimeMutex,NULL); 60 | 61 | addEOFLine=false; 62 | 63 | incompleteLineSent=false; 64 | } 65 | 66 | /** 67 | * specifies if a special 'EOF' line should be added at the end of 68 | * output. This line allows to get the value of the timestamps when 69 | * the process ends. 70 | * 71 | * @parm add: true iff the 'EOF' line must be added 72 | */ 73 | void addEOF(bool add) 74 | { 75 | addEOFLine=add; 76 | } 77 | 78 | /** 79 | * add a file descriptor (inputfd) to the list of timestamped files 80 | * 81 | * @parm inputfd: file descriptor of the file that must be timestamped 82 | * @parm letter: one letter name of the timestamped stream (0 if unused) 83 | * @parm outputfd: file descriptor to use to output the 84 | * timestamped stream (stdout by default) 85 | */ 86 | void watch(int inputfd, char letter=0, int outputfd=STDOUT_FILENO) 87 | { 88 | FD_SET(inputfd,&watcher); 89 | if(inputfd>=max) 90 | max=inputfd+1; 91 | 92 | watched.push_back(info(inputfd,outputfd,letter,true)); 93 | } 94 | 95 | /** 96 | * add a file descriptor (inputfd) to the list of timestamped files 97 | * 98 | * @parm inputfd: file descriptor of the file that must be timestamped 99 | * @parm letter: one letter name of the timestamped stream (0 if unused) 100 | * @parm outputfilter: filter to use to output the timestamped stream 101 | */ 102 | void watch(int inputfd, AbstractFilter *outputfilter, char letter=0) 103 | { 104 | FD_SET(inputfd,&watcher); 105 | if(inputfd>=max) 106 | max=inputfd+1; 107 | 108 | watched.push_back(info(inputfd,outputfilter,letter,true)); 109 | } 110 | 111 | /** 112 | * reset the time stamp 113 | */ 114 | void resetTimeStamp() 115 | { 116 | gettimeofday(&tvStart,NULL); 117 | } 118 | 119 | /** 120 | * obtain the current time stamp 121 | * 122 | * @return the current timestamp (for external use) 123 | */ 124 | struct timeval getTimeStamp() 125 | { 126 | gettimeofday(&tv,NULL); 127 | tv.tv_usec-=tvStart.tv_usec; 128 | tv.tv_sec-=tvStart.tv_sec; 129 | if(tv.tv_usec<0) 130 | { 131 | tv.tv_sec-=1; 132 | tv.tv_usec+=1000000; 133 | } 134 | 135 | return tv; 136 | } 137 | 138 | /** 139 | * loop that waits for data on one of the watched files 140 | * and timestamps each line read from these files 141 | * 142 | * the loop ends when all watched files are closed 143 | * 144 | * should be called from a separate thread of process (in most cases) 145 | */ 146 | void timeStampLines() 147 | { 148 | fd_set tmp; 149 | int result,watchDog=0; 150 | 151 | while (watched.size()) 152 | { 153 | tmp=watcher; 154 | 155 | // wait for data to become available on one of the watched files 156 | result=select(max,&tmp,NULL,NULL,NULL); 157 | 158 | if(result<0) 159 | { 160 | cout << "timestamper::select: " << strerror(errno) << endl; // ??? 161 | 162 | if(++watchDog<10) 163 | continue; 164 | else 165 | { 166 | cout << "Error in TimeStamper::timeStampLines(), select() keeps returning errors, exiting." << endl; 167 | break; 168 | } 169 | } 170 | 171 | watchDog=0; 172 | 173 | for(size_t i=0;i=max) 197 | max=watched[i].inputdescr+1; 198 | } 199 | else 200 | ++i; 201 | } 202 | } 203 | 204 | 205 | if(addEOFLine) 206 | { 207 | const char *lastLine="EOF\n"; 208 | 209 | if(incompleteLineSent) 210 | watched[0].write("\n",strlen("\n")); 211 | 212 | prepareTimeStamp(0); 213 | watched[0].write(tstampbuffer,tstampsize); 214 | watched[0].write(lastLine,strlen(lastLine)); 215 | } 216 | } 217 | 218 | /** 219 | * communicate the current CPU time to the time stamper 220 | * 221 | * must only be called from another thread than the one running 222 | * timeStampLines() !! 223 | */ 224 | void setCPUtimeFromAnotherThread(float cputime) 225 | { 226 | pthread_mutex_lock(&cputimeMutex); 227 | lastKnownCPUtime=cputime; 228 | pthread_mutex_unlock(&cputimeMutex); 229 | } 230 | 231 | protected: 232 | 233 | /** 234 | * get the current time and store the ascii representation of the 235 | * time stamp in tstampbuffer (tstampsize will contain the number of 236 | * characters of the representation) 237 | * 238 | * @parm name=one letter name of the watched file (0 if unused) 239 | */ 240 | void prepareTimeStamp(char name) 241 | { 242 | float cputimeCopy; 243 | 244 | getTimeStamp(); 245 | pthread_mutex_lock(&cputimeMutex); 246 | cputimeCopy=lastKnownCPUtime; 247 | pthread_mutex_unlock(&cputimeMutex); 248 | 249 | // store time stamp in tstampbuffer 250 | if(withCPUtime) 251 | { 252 | // CPU time+Wall Clock time 253 | if(name) 254 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 255 | #if WSIZE==32 256 | "%c%.2f/%d.%02d\t", 257 | #else 258 | "%c%.2f/%ld.%02ld\t", 259 | #endif 260 | name,cputimeCopy,tv.tv_sec,tv.tv_usec/10000); 261 | else 262 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 263 | #if WSIZE==32 264 | "%.2f/%d.%02d\t", 265 | #else 266 | "%.2f/%ld.%02ld\t", 267 | #endif 268 | cputimeCopy, 269 | tv.tv_sec,tv.tv_usec/10000); 270 | } 271 | else 272 | { 273 | // no CPU time 274 | if(name) 275 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 276 | #if WSIZE==32 277 | "%c%d.%02d\t", 278 | #else 279 | "%c%ld.%02ld\t", 280 | #endif 281 | name,tv.tv_sec,tv.tv_usec/10000); 282 | else 283 | tstampsize=snprintf(tstampbuffer,sizeof(tstampbuffer), 284 | #if WSIZE==32 285 | "%d.%02d\t", 286 | #else 287 | "%ld.%02ld\t", 288 | #endif 289 | tv.tv_sec,tv.tv_usec/10000); 290 | } 291 | 292 | } 293 | 294 | private: 295 | /** 296 | * read data available on watched file with index id (in the watched 297 | * vector) and output the timestamp stream 298 | * 299 | * @return false on EOF 300 | */ 301 | bool readFrom(int id) 302 | { 303 | char buffer[1024]; 304 | 305 | int size=read(watched[id].inputdescr,buffer,sizeof(buffer)); 306 | 307 | // PTY seem to be special (this is a quick fix that must be cleaned ???) 308 | if(size<0) 309 | return false; // ??? 310 | 311 | if(size<0) 312 | throw runtime_error(string("TimeStamper::readFrom(): read failed: ") 313 | +strerror(errno)); 314 | 315 | if(size==0) 316 | return false; // indicate EOF 317 | 318 | // create the time stamp once for all the lines we read 319 | prepareTimeStamp(watched[id].name); 320 | 321 | if(watched[id].EOLBefore) 322 | { 323 | watched[id].write(tstampbuffer,tstampsize); 324 | watched[id].EOLBefore=false; 325 | } 326 | 327 | char *s=buffer; 328 | char *eol; 329 | 330 | // split into lines 331 | while (size>0 && (eol=(char*)memchr(s,'\n',size))!=NULL) 332 | { 333 | // output up to EOL included 334 | watched[id].write(s,eol-s+1); 335 | size-=eol-s+1; 336 | s=eol+1; 337 | 338 | if(size>0) 339 | watched[id].write(tstampbuffer,tstampsize); 340 | else 341 | watched[id].EOLBefore=true; 342 | } 343 | 344 | // output the last incomplete line 345 | if(size>0) 346 | { 347 | watched[id].write(s,size); 348 | incompleteLineSent=true; 349 | } 350 | else 351 | incompleteLineSent=false; 352 | 353 | return true; 354 | } 355 | 356 | private: 357 | bool withCPUtime; // do we display CPU time in the timestamp ? 358 | 359 | float lastKnownCPUtime; // current CPU time (provided by an external source) 360 | pthread_mutex_t cputimeMutex; // a mutex to protect access to cputime 361 | 362 | struct timeval tvStart,tv; // first timestamp and current timestamp 363 | 364 | int max; // max(fd)+1 for select 365 | fd_set watcher; // set of watched file descriptors for use by select 366 | 367 | // buffer that contains the ascii representation of the timestamp 368 | char tstampbuffer[64]; // a buffer to output the time stamps 369 | int tstampsize; // size of the timestamp 370 | 371 | bool incompleteLineSent; // true iff the last line we sent didn't have an EOL 372 | 373 | bool addEOFLine; // true if we must add an 'EOF' line at the end of output 374 | 375 | /** 376 | * internal information kept on each file to be watched 377 | */ 378 | struct info 379 | { 380 | bool filteredOutput; 381 | int inputdescr; // file descriptor to watch 382 | int outputdescr; // file descriptor to use to output the timestamped stream (when filteredOutput is false) 383 | AbstractFilter *outputfilter; // filter to write to (when filteredOutput is true) 384 | char name; // a letter that identifies the watched file 385 | bool EOLBefore; // true iff the first character we read is the start of 386 | // a new line 387 | 388 | info(int inputfd, int outputfd, char letter, bool lineStart) 389 | { 390 | filteredOutput=false; 391 | inputdescr=inputfd; 392 | outputdescr=outputfd; 393 | name=letter; 394 | EOLBefore=lineStart; 395 | } 396 | 397 | info(int inputfd, AbstractFilter *filter, char letter, bool lineStart) 398 | { 399 | filteredOutput=true; 400 | inputdescr=inputfd; 401 | outputfilter=filter; 402 | name=letter; 403 | EOLBefore=lineStart; 404 | } 405 | 406 | void write(const char *buffer, int len) 407 | { 408 | if(filteredOutput) 409 | outputfilter->write(buffer,len); 410 | else 411 | systemWrite(outputdescr,buffer,len); 412 | } 413 | 414 | /** 415 | * handle partial writes and EINTR 416 | */ 417 | void systemWrite(int fd, const char *buf, size_t len) 418 | { 419 | const char *p=buf; 420 | int n; 421 | 422 | do 423 | { 424 | n=::write(fd,p,len); 425 | if(n<0) 426 | { 427 | if(errno==EINTR) 428 | continue; 429 | 430 | perror("write failed: "); 431 | break; 432 | } 433 | 434 | len-=n; 435 | p+=n; 436 | } 437 | while(len); 438 | } 439 | }; 440 | 441 | vector watched; // list of files we watch 442 | }; 443 | 444 | #endif 445 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/runsolver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/runsolver/runsolver-3.4.0/src/runsolver -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/runsolver.d: -------------------------------------------------------------------------------- 1 | runsolver.d runsolver.o: runsolver.cc Cores.hh SignalNames.hh ProcessList.hh \ 2 | CircularBufferFilter.hh ExecutionSummary.hh Watcher.hh ProcessTree.hh \ 3 | ProcessData.hh ProcessHistory.hh TimeStamper.hh 4 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/runsolver.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/runsolver/runsolver-3.4.0/src/runsolver.o -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/server/Makefile: -------------------------------------------------------------------------------- 1 | server: server.cc 2 | g++ -std=c++11 -o server server.cc 3 | 4 | run: server 5 | ./server 6 | 7 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/server/Makefile~: -------------------------------------------------------------------------------- 1 | server: server.cc 2 | g++ -std=c++11 -o server server.cc 3 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/server/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/runsolver/runsolver-3.4.0/src/server/server -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/server/server.cc: -------------------------------------------------------------------------------- 1 | /* 2 | https://lwn.net/Articles/230975/ saved as ELC: How much memory are applications really using? [LWN.net].html 3 | http://eqware.net/Articles/CapturingProcessMemoryUsageUnderLinux/index.html saved as Capturing Process Memory Usage Under Linux.html 4 | https://stackoverflow.com/questions/561245/virtual-memory-usage-from-java-under-linux-too-much-memory-used/561450#561450 saved as Virtual Memory Usage from Java under Linux, too much memory used - Stack Overflow.html 5 | https://www.selenic.com/smem/ 6 | pmap 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | using namespace std; 20 | 21 | /** 22 | * /proc/xx/maps [beg,end( 23 | * 24 | */ 25 | 26 | class MemoryUsage 27 | { 28 | protected: 29 | //enum PageMapType 30 | 31 | uint64_t unmappedPages,ramPages,swapPages,sharedPages; 32 | 33 | public: 34 | MemoryUsage() 35 | { 36 | struct utsname unam; 37 | 38 | uname(&unam); 39 | 40 | vector ver; 41 | boost::split(ver,unam.release, boost::is_any_of(".")); 42 | 43 | cout << "rel=" << ver[0] << "." << ver[1] << endl; 44 | } 45 | 46 | bool readMaps(const vector &pidList) 47 | { 48 | #warning must add support for hugepages 49 | uint64_t lastUnmappedPages,lastRamPages,lastSwapPages,lastSharedPages; 50 | uint64_t pagesize=sysconf(_SC_PAGESIZE); 51 | 52 | set pagesList; 53 | pair::iterator,bool> ret; 54 | 55 | unmappedPages=ramPages=swapPages=sharedPages=0; 56 | 57 | for(pid_t pid: pidList) 58 | { 59 | ostringstream mapsfname,pagemapfname; 60 | mapsfname << "/proc/" << pid << "/maps"; 61 | pagemapfname << "/proc/" << pid << "/pagemap"; 62 | 63 | ifstream maps(mapsfname.str()); 64 | if(!maps.good()) 65 | return false; 66 | 67 | int pagemap=open(pagemapfname.str().c_str(),O_RDONLY); 68 | if(pagemap<0) 69 | cout << "access to " << pagemapfname.str() << " denied\n"; 70 | 71 | unsigned long beg,end,inode; 72 | string perm,path,tmp; 73 | char c; 74 | 75 | while(true) 76 | { 77 | path.clear(); 78 | maps >> hex >> beg >> c >> end >> dec >> perm >> tmp >> tmp >> inode; 79 | while((c=maps.peek()) && isspace(c) && c!='\n') 80 | maps.get(); 81 | getline(maps,path); 82 | if(maps.fail() && path.empty()) 83 | break; 84 | 85 | 86 | cout << (end-beg)/pagesize << "\t" << hex << beg << "-" << end << dec << " " << perm << " path=" << path << endl; 87 | 88 | lastUnmappedPages=unmappedPages; 89 | lastRamPages=ramPages; 90 | lastSwapPages=swapPages; 91 | lastSharedPages=sharedPages; 92 | 93 | if(pagemap>=0) 94 | { 95 | uint64_t desc; 96 | off_t pos=sizeof(desc)*(beg/pagesize); 97 | off_t res=lseek(pagemap,pos,SEEK_SET); 98 | if(res<0 || res!=pos) 99 | cout << "lseek failed:" << strerror(errno) << endl; 100 | 101 | //cout << "res=" << hex << res << dec << endl; 102 | 103 | for(unsigned long p=beg;p " 124 | << (present?"Present ":"") 125 | << (swap?"Swp ":"") 126 | << (map?"Map ":"") 127 | << (excl?"Excl ":"") 128 | << (softDirty?"SoftD ":"") 129 | << " " 130 | << ((desc>>57)&0xF) 131 | << " " << (desc&((1UL<<55)-1)) << dec << endl; 132 | 133 | if(pfn) 134 | { 135 | ret=pagesList.insert(pfn); 136 | if(!ret.second) 137 | ++sharedPages; 138 | else 139 | if(swap) 140 | ++swapPages; 141 | else 142 | ++ramPages; 143 | } 144 | else 145 | ++unmappedPages; 146 | } 147 | } //if(pagemap>=0 148 | 149 | cout << "=> total=" << (end-beg)/1024 << "KB" 150 | << " unmapped=" << (unmappedPages-lastUnmappedPages)*(pagesize/1024) << "KB" 151 | << " ram=" << (ramPages-lastRamPages)*(pagesize/1024) << "KB" 152 | << " swap=" << (swapPages-lastSwapPages)*(pagesize/1024) << "KB" 153 | << " shared=" << (sharedPages-lastSharedPages)*(pagesize/1024) << "KB" << endl; 154 | 155 | 156 | }//while(true) 157 | 158 | close(pagemap); 159 | }//for(pid_t pid... 160 | 161 | 162 | cout << "pagesList (size=" << pagesList.size() << "):"; 163 | //for(uint64_t p: pagesList) 164 | // cout << " " << hex << p << dec; 165 | cout << endl; 166 | 167 | cout << "unmapped=" << unmappedPages*(pagesize/1024) << "KB\n" 168 | << "ram=" << ramPages*(pagesize/1024) << "KB\n" 169 | << "swap=" << swapPages*(pagesize/1024) << "KB\n" 170 | << "shared=" << sharedPages*(pagesize/1024) << "KB\n" 171 | << "VSS=all=" << (ramPages+unmappedPages+swapPages+sharedPages)*(pagesize/1024) << "KB\n" 172 | << "RSS=ram+shared=" << (ramPages+sharedPages)*(pagesize/1024) << "KB\n"; 173 | 174 | return true; 175 | } 176 | }; 177 | 178 | int main() 179 | { 180 | MemoryUsage mu; 181 | 182 | 183 | mu.readMaps({getpid()}); 184 | 185 | sleep(1); 186 | cout << "pid=" << getpid() << endl; 187 | ostringstream cmd; 188 | 189 | for(const char *fname: {"status","stat","statm","smaps","maps"}) 190 | { 191 | cmd.str(""); 192 | cmd << "/bin/cat /proc/" << getpid() << "/" << fname; 193 | cout << "\n\n#######################################################################\n" 194 | << cmd.str() << endl; 195 | system(cmd.str().c_str()); 196 | } 197 | //sleep(30); 198 | 199 | /* 200 | ./server>/tmp/res 201 | awk '/^Rss:/ {s=s+$2} END {print s}' /tmp/res 202 | 203 | status ne semble pas donner la bonne valeur de RSS (incohérent avec la somme des RSS de smaps) 204 | 205 | il y a quelques petites différences avec les valeurs données par smaps 206 | */ 207 | } 208 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/server/server.cc~: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | 6 | bool readMaps(pid_t pid) 7 | { 8 | ostringstream fname; 9 | fname << "/proc/" << pid << "/maps"; 10 | 11 | ifstream in(fname.str()); 12 | if(!in.good()) 13 | return false; 14 | 15 | long beg,end,inode; 16 | string perm,path,tmp; 17 | char sep; 18 | 19 | while(true) 20 | { 21 | in >> hex >> beg >> sep >> end >> dec >> perm >> tmp >> tmp >> inode; 22 | getline(in,path); 23 | if(in.fail() &&path.empty()) 24 | break; 25 | 26 | cout << hex << beg << "-" << end << " " << perm <<<< endl; 27 | } 28 | 29 | return true; 30 | } 31 | 32 | int main() 33 | { 34 | 35 | } 36 | -------------------------------------------------------------------------------- /runsolver/runsolver-3.4.0/src/vlineSplitter.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Olivier ROUSSEL 3 | * 4 | * This file is part of runsolver. 5 | * 6 | * runsolver is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * runsolver is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with runsolver. If not, see . 18 | */ 19 | 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | using namespace std; 32 | 33 | int main(int argc, char **argv) 34 | { 35 | string s,timestamp; 36 | bool withTimestamp; 37 | 38 | withTimestamp=argc==2 && strcmp(argv[1],"--timestamp")==0; 39 | 40 | try 41 | { 42 | while(cin.good()) 43 | { 44 | if (withTimestamp) 45 | { 46 | cin >> timestamp; 47 | cin.get(); // skip tabulation 48 | 49 | if (!cin.good()) 50 | break; 51 | } 52 | 53 | getline(cin,s); 54 | 55 | if (!cin.good() && s.length()==0) 56 | break; 57 | 58 | // we're only concerned by a "v " line 59 | if (s.length()>=2 && s[0]=='v' && s[1]==' ') 60 | { 61 | istringstream f(s); 62 | string word; 63 | int len=0; 64 | 65 | f >> word; // skip "v " 66 | 67 | while (f.good()) 68 | { 69 | // read a literal 70 | word=""; 71 | f >> word; 72 | if (word=="") 73 | break; 74 | 75 | if (len==0) 76 | { 77 | if (withTimestamp) 78 | cout << timestamp << "\t"; 79 | cout << "v"; 80 | } 81 | 82 | cout << " " << word; 83 | len+=word.length(); 84 | 85 | if (len>100) 86 | { 87 | cout << endl; 88 | len=0; 89 | } 90 | } 91 | 92 | if (len!=0) 93 | cout << endl; 94 | 95 | s.clear(); 96 | } 97 | else 98 | { 99 | // copy 100 | if (withTimestamp) 101 | cout << timestamp << "\t"; 102 | cout << s << endl; 103 | } 104 | } 105 | } 106 | catch (exception &e) 107 | { 108 | cout.flush(); 109 | cerr << "\n\tUnexpected exception :\n"; 110 | cerr << "\t" << e.what() << endl; 111 | exit(1); 112 | } 113 | } 114 | 115 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import subprocess 4 | import sys 5 | import traceback 6 | import setuptools 7 | from subprocess import Popen 8 | from setuptools.command.install import install 9 | 10 | RUNSOLVER_LOCATION = os.path.join(os.path.dirname(__file__), 'runsolver', 11 | 'runsolver-3.4.0', 'src') 12 | BINARIES_DIRECTORY = 'genericWrapper4AC/binaries' 13 | TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), 'test', 14 | 'test_binaries') 15 | 16 | 17 | class InstallRunsolver(install): 18 | 19 | def run(self): 20 | # Build the runsolver 21 | #sys.stdout.write('Building runsolver\n') 22 | #cur_pwd = os.getcwd() 23 | 24 | #os.chdir(RUNSOLVER_LOCATION) 25 | #subprocess.check_call('make') 26 | #os.chdir(cur_pwd) 27 | 28 | # Create a fresh binaries directory 29 | try: 30 | shutil.rmtree(BINARIES_DIRECTORY) 31 | except Exception: 32 | pass 33 | 34 | try: 35 | os.makedirs(BINARIES_DIRECTORY) 36 | except Exception: 37 | pass 38 | 39 | # Copy the runsolver into the test directory so tests can be run 40 | try: 41 | os.makedirs(TEST_DIRECTORY) 42 | except Exception: 43 | pass 44 | shutil.copy(os.path.join(RUNSOLVER_LOCATION, 'runsolver'), 45 | os.path.join(TEST_DIRECTORY, 'runsolver')) 46 | 47 | # Copy the runsolver into the sources so it gets copied 48 | shutil.copy(os.path.join(RUNSOLVER_LOCATION, 'runsolver'), 49 | os.path.join(BINARIES_DIRECTORY, 'runsolver')) 50 | 51 | #install.do_egg_install(self) 52 | install.run(self) 53 | 54 | sys.stdout.write('Testing runsolver\n') 55 | p = Popen("%s --version" %(os.path.join(BINARIES_DIRECTORY, 'runsolver')), shell=True) 56 | p.communicate() 57 | if p.returncode != 0: 58 | raise Exception("runsolver was not properly installed. Please check the README for troubleshooting.") 59 | 60 | try: 61 | shutil.rmtree(BINARIES_DIRECTORY) 62 | except OSError: 63 | sys.stderr.write('Failed to delete %s\n' %(BINARIES_DIRECTORY)) 64 | pass 65 | 66 | 67 | setuptools.setup( 68 | name='GenericWrapper4AC', 69 | description='Generic Wrapper to interface between algorithm configurators and algorithms to tune', 70 | version='2.0.0', 71 | packages=setuptools.find_packages(exclude=['test']), 72 | python_requires='>=3.5', 73 | test_suite='nose.collector', 74 | tests_require=["nose", "numpy", "scipy", "scikit-learn"], 75 | cmdclass={'install': InstallRunsolver}, 76 | include_package_data=True, 77 | package_data={"genericWrapper4AC": ["binaries/runsolver"]}, 78 | author='Marius Lindauer and Katharina Eggensperger', 79 | author_email='lindauer@informatik.uni-freiburg.de', 80 | license='BSD', 81 | platforms=['Linux'], 82 | classifiers=[], 83 | url='www.automl.org') 84 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/test/__init__.py -------------------------------------------------------------------------------- /test/test_calls/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/test/test_calls/__init__.py -------------------------------------------------------------------------------- /test/test_calls/test_calls.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | import os 4 | 5 | from examples.MiniSAT.MiniSATWrapper import MiniSATWrapper 6 | from examples.SGD.SGDWrapper import SGDWrapper 7 | 8 | 9 | class TestCalls(unittest.TestCase): 10 | 11 | def setUp(self): 12 | self.runsolver = os.path.join( 13 | os.path.dirname(os.path.dirname(__file__)), 14 | "test_binaries", "runsolver") 15 | 16 | def test_minisat_old(self): 17 | 18 | wrapper = MiniSATWrapper() 19 | 20 | sys.argv = "examples/MiniSAT/SATCSSCWrapper.py examples/MiniSAT/gzip_vc1071.cnf SAT 10 0 42 -rnd-freq 0 -var-decay 0.001 -cla-decay 0.001 -gc-frac 0.000001 -rfirst 1000" 21 | sys.argv += " --runsolver-path " + self.runsolver 22 | sys.argv = sys.argv.split(" ") 23 | 24 | wrapper.main(exit=False) 25 | 26 | self.assertEqual(wrapper.data.status, "SUCCESS") 27 | self.assertGreater(2, wrapper.data.time) 28 | self.assertEqual(wrapper.data.seed, 42) 29 | self.assertEqual(wrapper.data.runlength, 0) 30 | self.assertFalse(wrapper.data.new_format) 31 | 32 | def test_minisat_new(self): 33 | 34 | wrapper = MiniSATWrapper() 35 | 36 | sys.argv = "python examples/MiniSAT/SATCSSCWrapper.py --instance examples/MiniSAT/gzip_vc1071.cnf --cutoff 10 --seed 42 --config -rnd-freq 0 -var-decay 0.001 -cla-decay 0.001 -gc-frac 0.000001 -rfirst 1000" 37 | sys.argv += " --runsolver-path " + self.runsolver 38 | sys.argv = sys.argv.split(" ") 39 | 40 | wrapper.main(exit=False) 41 | 42 | self.assertEqual(wrapper.data.status, "SUCCESS") 43 | self.assertGreater(2, wrapper.data.time) 44 | self.assertEqual(wrapper.data.seed, 42) 45 | # important hack for irace that cost and time is equal 46 | # if cost was not set 47 | self.assertEqual(wrapper.data.cost, wrapper.data.time) 48 | self.assertIsNone(wrapper.data.runlength) 49 | self.assertTrue(wrapper.data.new_format) 50 | 51 | def test_sgd_old(self): 52 | 53 | wrapper = SGDWrapper() 54 | 55 | sys.argv = "examples/SGD/SGDWrapper.py train 0 5 0 9 -learning_rate constant -eta0 1 -loss hinge -penalty l2 -alpha 0.0001 -learning_rate optimal -eta0 0.0 -n_iter 2" 56 | sys.argv += " --runsolver-path " + self.runsolver 57 | sys.argv = sys.argv.split(" ") 58 | 59 | wrapper.main(exit=False) 60 | 61 | self.assertEqual(wrapper.data.status, "SUCCESS") 62 | self.assertGreater(2, wrapper.data.time) 63 | self.assertGreater(1, wrapper.data.cost) 64 | # the irace hack should not change the results 65 | # for set cost values 66 | self.assertNotEqual(wrapper.data.cost, wrapper.data.time) 67 | self.assertEqual(wrapper.data.seed, 9) 68 | self.assertEqual(wrapper.data.runlength, 0) 69 | self.assertFalse(wrapper.data.new_format) 70 | 71 | def test_sgd_new(self): 72 | 73 | wrapper = SGDWrapper() 74 | 75 | sys.argv = "examples/SGD/SGDWrapper.py --instance train --seed 9 --config -learning_rate constant -eta0 1 -loss hinge -penalty l2 -alpha 0.0001 -learning_rate optimal -eta0 0.0 -n_iter 2" 76 | sys.argv += " --runsolver-path " + self.runsolver 77 | sys.argv = sys.argv.split(" ") 78 | 79 | wrapper.main(exit=False) 80 | 81 | self.assertEqual(wrapper.data.status, "SUCCESS") 82 | self.assertGreater(2, wrapper.data.time) 83 | self.assertGreater(1, wrapper.data.cost) 84 | # the irace hack should not change the results 85 | # for set cost values 86 | self.assertNotEqual(wrapper.data.cost, wrapper.data.time) 87 | self.assertEqual(wrapper.data.seed, 9) 88 | self.assertTrue(wrapper.data.new_format) -------------------------------------------------------------------------------- /test/test_calls/test_checker.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import io 3 | import os 4 | import tempfile 5 | 6 | from genericWrapper4AC.domain_specific.satwrapper import SatWrapper 7 | from genericWrapper4AC.argparser.parse import parse 8 | 9 | 10 | class TestChecker(unittest.TestCase): 11 | def setUp(self): 12 | self.runsolver = os.path.join( 13 | os.path.dirname(os.path.dirname(__file__)), 14 | "test_binaries", "runsolver") 15 | 16 | self.res_template = """ 17 | WARNING: for repeatability, setting FPU to use double precision 18 | ============================[ Problem Statistics ]============================= 19 | | | 20 | | Number of variables: 10001 | 21 | | Number of clauses: 20601 | 22 | | Parse time: 0.00 s | 23 | | | 24 | ============================[ Search Statistics ]============================== 25 | | Conflicts | ORIGINAL | LEARNT | Progress | 26 | | | Vars Clauses Literals | Limit Clauses Lit/Cl | | 27 | =============================================================================== 28 | =============================================================================== 29 | restarts : 1 30 | conflicts : 26 (3250 /sec) 31 | decisions : 13738 (0.00 %% random) (1717250 /sec) 32 | propagations : 52754 (6594250 /sec) 33 | conflict literals : 71 (0.00 %% deleted) 34 | Memory used : 22.00 MB 35 | CPU time : 0.008 s 36 | 37 | %s 38 | """ 39 | self.call = "python examples/MiniSAT/SATCSSCWrapper.py --script " \ 40 | "examples/MiniSAT/MiniSATWrapper.py --instance examples" \ 41 | "/MiniSAT/gzip_vc1071.cnf --cutoff 10 --seed 42 --config " \ 42 | "-rnd-freq 0 -var-decay 0.001 -cla-decay 0.001 " \ 43 | "-gc-frac 0.000001 -rfirst 1000" 44 | self.call = self.call.split(" ") 45 | 46 | # Add a solubility file 47 | self.sat_sol_file = tempfile.NamedTemporaryFile(mode="w+") 48 | self.sat_sol_file.write( 49 | "examples/MiniSAT/gzip_vc1071.cnf SATISFIABLE") 50 | self.sat_sol_file.flush() 51 | 52 | self.unsat_sol_file = tempfile.NamedTemporaryFile(mode="w+") 53 | self.unsat_sol_file.write( 54 | "examples/MiniSAT/gzip_vc1071.cnf UNSATISFIABLE") 55 | self.unsat_sol_file.flush() 56 | 57 | self.unknown_sol_file = tempfile.NamedTemporaryFile(mode="w+") 58 | self.unknown_sol_file.write( 59 | "examples/MiniSAT/gzip_vc1071.cnf UNKNOWN") 60 | self.unknown_sol_file.flush() 61 | 62 | def parse_results(self, solver, specific, sol_file): 63 | wrapper = SatWrapper() 64 | wrapper.data, wrapper.args = parse(cmd_arguments=self.call, 65 | parser=wrapper.parser) 66 | if sol_file == "SATISFIABLE": 67 | wrapper.args.solubility_file = self.sat_sol_file.name 68 | elif sol_file == "UNSATISFIABLE": 69 | wrapper.args.solubility_file = self.unsat_sol_file.name 70 | else: 71 | wrapper.args.solubility_file = self.unknown_sol_file.name 72 | 73 | res_file = io.StringIO(self.res_template % solver) 74 | res_file.name = "FAKE" 75 | wrapper.data.specifics = specific 76 | 77 | res_map = wrapper.process_results(res_file, exit_code=0) 78 | return res_map 79 | 80 | def test_all_agree(self): 81 | # RES SPECIFIC SOLFILE 82 | # SAT SAT SAT 83 | res_map = self.parse_results(solver="SATISFIABLE", 84 | specific="SATISFIABLE", 85 | sol_file="SATISFIABLE") 86 | self.assertEqual(res_map["status"], "SAT") 87 | 88 | # UNSAT UNSAT UNSAT 89 | res_map = self.parse_results(solver="UNSATISFIABLE", 90 | specific="UNSATISFIABLE", 91 | sol_file="UNSATISFIABLE") 92 | self.assertEqual(res_map["status"], "UNSAT") 93 | 94 | # SAT None None 95 | res_map = self.parse_results(solver="SATISFIABLE", 96 | specific="UNKNOWN", 97 | sol_file="UNKNOWN") 98 | self.assertEqual(res_map["status"], "SAT") 99 | 100 | # SAT something else 101 | res_map = self.parse_results(solver="SATISFIABLE", 102 | specific="SOMETHING", 103 | sol_file="ELSE") 104 | self.assertEqual(res_map["status"], "SAT") 105 | 106 | # bla something else 107 | res_map = self.parse_results(solver="BLA", 108 | specific="SOMETHING", 109 | sol_file="ELSE") 110 | self.assertFalse("status" in res_map) 111 | 112 | def test_SAT_but_UNSAT(self): 113 | # RES SPECIFIC SOLFILE 114 | # SAT None UNSAT 115 | res_map = self.parse_results(solver="SATISFIABLE", 116 | specific="UNKNOWN", 117 | sol_file="UNSATISFIABLE") 118 | self.assertEqual(res_map["status"], "CRASHED", res_map["misc"]) 119 | 120 | # SAT UNSAT None 121 | res_map = self.parse_results(solver="SATISFIABLE", 122 | specific="UNSATISFIABLE", 123 | sol_file="UNKNOWN") 124 | self.assertEqual(res_map["status"], "CRASHED", res_map["misc"]) 125 | 126 | def test_UNSAT_but_SAT(self): 127 | # RES SPECIFIC SOLFILE 128 | # UNSAT None SAT 129 | res_map = self.parse_results(solver="UNSATISFIABLE", 130 | specific="UNKNOWN", 131 | sol_file="SATISFIABLE") 132 | self.assertEqual(res_map["status"], "CRASHED", res_map["misc"]) 133 | 134 | # UNSAT SAT None 135 | res_map = self.parse_results(solver="UNSATISFIABLE", 136 | specific="SATISFIABLE", 137 | sol_file="UNKNOWN") 138 | self.assertEqual(res_map["status"], "CRASHED", res_map["misc"]) -------------------------------------------------------------------------------- /test/test_resources/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automl/GenericWrapper4AC/a60d760bb5dacd5deedaefdd143bc92464cec68b/test/test_resources/__init__.py -------------------------------------------------------------------------------- /test/test_resources/mem_str.py: -------------------------------------------------------------------------------- 1 | s = ["a"] 2 | 3 | for i in range(1, 100000000): 4 | # To prevent receiving a MEMOUT faster than a TIMEOUT 5 | s = s + s[:100000] -------------------------------------------------------------------------------- /test/test_resources/pi.py: -------------------------------------------------------------------------------- 1 | # calc pi 2 | # source https://stackoverflow.com/questions/28284996/python-pi-calculation 3 | 4 | from decimal import Decimal, getcontext 5 | getcontext().prec=10000 6 | print(sum(1/Decimal(16)**k * (Decimal(4)/(8*k+1) - Decimal(2)/(8*k+4) - Decimal(1)/(8*k+5) - Decimal(1)/(8*k+6)) for k in range(10000))) 7 | 8 | -------------------------------------------------------------------------------- /test/test_resources/test_limits.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os 3 | 4 | from genericWrapper4AC.generic_wrapper import AbstractWrapper 5 | from genericWrapper4AC.data.data import Data 6 | 7 | 8 | class TestResourceLimits(unittest.TestCase): 9 | 10 | def setUp(self): 11 | self.runsolver = os.path.join( 12 | os.path.dirname(os.path.dirname(__file__)), 13 | "test_binaries", "runsolver") 14 | 15 | def test_memlimit(self): 16 | 17 | wrapper = AbstractWrapper() 18 | 19 | data = Data() 20 | 21 | wrapper.data = data 22 | data.tmp_dir = "." 23 | data.runsolver = self.runsolver 24 | data.mem_limit = 50 # mb 25 | data.cutoff = 100000 26 | 27 | target_cmd = "python test/test_resources/mem_str.py" 28 | 29 | wrapper.call_target(target_cmd) 30 | 31 | wrapper.read_runsolver_output() 32 | 33 | wrapper._watcher_file.close() 34 | wrapper._solver_file.close() 35 | os.remove(wrapper._watcher_file.name) 36 | os.remove(wrapper._solver_file.name) 37 | 38 | self.assertEqual(wrapper.data.status, "TIMEOUT") 39 | self.assertEqual(wrapper.data.additional, " memory limit was exceeded") 40 | 41 | def test_timelimit(self): 42 | 43 | wrapper = AbstractWrapper() 44 | 45 | data = Data() 46 | 47 | wrapper.data = data 48 | data.tmp_dir = "." 49 | data.runsolver = self.runsolver 50 | data.mem_limit = 500 # mb 51 | data.cutoff = 1 52 | 53 | target_cmd = "python test/test_resources/pi.py" 54 | 55 | wrapper.call_target(target_cmd) 56 | 57 | wrapper.read_runsolver_output() 58 | 59 | self.assertEqual(wrapper.data.status, "TIMEOUT") 60 | self.assertNotEqual(wrapper.data.additional, 61 | " memory limit was exceeded") 62 | 63 | wrapper._watcher_file.close() 64 | wrapper._solver_file.close() 65 | os.remove(wrapper._watcher_file.name) 66 | os.remove(wrapper._solver_file.name) 67 | 68 | def test_nolimit(self): 69 | 70 | wrapper = AbstractWrapper() 71 | 72 | data = Data() 73 | 74 | wrapper.data = data 75 | data.tmp_dir = "." 76 | data.runsolver = self.runsolver 77 | data.mem_limit = 500 # mb 78 | data.cutoff = 5 79 | 80 | target_cmd = "time" 81 | 82 | wrapper.call_target(target_cmd) 83 | 84 | wrapper.read_runsolver_output() 85 | 86 | # since there was no timeout/memout 87 | # the status is still on its default: CRASHED 88 | self.assertEqual(wrapper.data.status, "CRASHED") 89 | self.assertNotEqual(wrapper.data.additional, 90 | " memory limit was exceeded") 91 | 92 | wrapper._watcher_file.close() 93 | wrapper._solver_file.close() 94 | os.remove(wrapper._watcher_file.name) 95 | os.remove(wrapper._solver_file.name) 96 | --------------------------------------------------------------------------------