#! /usr/bin/env python3 from argparse import ArgumentParser from datetime import datetime from multiprocessing import Process, Queue from pathlib import Path from queue import Empty from sqlalchemy import exists, desc from tempfile import TemporaryDirectory import logging from .mutation import generation, flip, seed_shell from .orm import db_config, ScrapNode def sins(): now = '{0:%Y%m%dT%H%M%S}'.format(datetime.utcnow()) parser = ArgumentParser( description='position independent code (PIC) mutation experiment.') parser.add_argument('-v', '--verbose', action='count') parser.add_argument('-s', '--seed', help='path to PIC image.') parser.add_argument('-o', '--output', help='path to results directory.') parser.add_argument('-l', '--lineage', default=10, help='max count of unsuccessful generation.') args = parser.parse_args() log_level = logging.INFO log_format = logging.Formatter('%(message)s') if args.verbose: log_level = logging.DEBUG log_format = logging.Formatter( '%(levelname)s %(filename)s:%(lineno)d\n%(message)s\n') logger = logging.getLogger('sins') logger.setLevel(log_level) stream_handler = logging.StreamHandler() stream_handler.setLevel(log_level) stream_handler.setFormatter(log_format) logger.addHandler(stream_handler) if args.output: log_path = f'{args.output}/sins-{now}.log' file_handler = logging.FileHandler(log_path) file_handler.setLevel(log_level) file_handler.setFormatter(log_format) logger.addHandler(file_handler) logger.info(now) seed_data = seed_shell if args.seed: seed = Path(args.seed) with seed.open('rb') as seed_file: seed_data = seed_file.read() seed = ScrapNode(child=seed_data) logger.debug(f'seed:\n{seed}') if args.output: db_path = Path(f'{args.output}/sins.sqlite') else: temp_dir = TemporaryDirectory() db_path = Path(f'{temp_dir.name}/sins.sqlite') session = db_config(db_path) logger.info(f'db_path: {db_path}') if args.seed: exists = session.query(ScrapNode).filter( ScrapNode.checksum == seed.checksum) if exists: seed = exists[0] else: session.add(seed) session.commit() else: recent = session.query(ScrapNode).order_by(desc('ctime')).first() if recent: logger.debug(f'recent:\n{recent}') seed = recent parent = seed queue = Queue() while True: lineage = 0 scrap = flip(parent.image) while lineage < args.lineage: logger.debug(f'lineage: {lineage}') result = None proc = Process(target=generation, args=(queue, scrap)) proc.start() try: result = queue.get(timeout=1) except Empty: lineage += 1 continue if not result: lineage += 1 continue parent = ScrapNode(child=scrap, parent_id=parent.id) parent.length = result session.add(parent) session.commit() logger.info(f'scrap:\n{parent}') lineage = 0 scrap = flip(parent.image)