<commit_before>#!/usr/bin/python
# coding=utf-8

import logging
logger = logging.getLogger(__name__)
from uuid import uuid4
from singleton import Singleton
from container import Container
import pymongo
from hosts import Hosts
import time
import errors
import tempfile
import sys
import traceback

Hosts()


class ReplicaSet(object):
    """class represents ReplicaSet"""

    _hosts = Hosts()  # singleton to manage hosts instances
    # replica set's default parameters
    default_params = {'arbiterOnly': False, 'buildIndexes': False, 'hidden': False, 'slaveDelay': 0}

    def __init__(self, rs_params):
        """create replica set according members config
        Args:
            rs_params - replica set configuration
        """
        self.host_map = {}
        self.auth_key = rs_params.get('auth_key', None)
        self.login = rs_params.get('login', '')
        self.password = rs_params.get('password', '')
        self.repl_id = rs_params.get('id', None) or "rs-" + str(uuid4())

        config = {"_id": self.repl_id, "members": [
                  self.member_create(member, index) for index, member in enumerate(rs_params.get('members', {}))
                  ]}
        logger.debug("replica config: {config}".format(**locals()))
        if not self.repl_init(config):
            self.cleanup()
            raise errors.ReplicaSetError("replica can't started")

        if self.login:
            logger.debug("add admin user {login}/{password}".format(login=self.login, password=self.password))
            try:
                c = self.connection()
                c.admin.add_user(self.login, self.password)
            except pymongo.errors.OperationFailure:
                pass
            finally:
                c.close()

    def __len__(self):
        return len(self.host_map)

    def cleanup(self):
        """remove all members without reconfig"""
        for item in self.host_map:
            self.member_del(item, reconfig=False)
        self.host_map.clear()

    def id2host(self, member_id):
        """return hostname by member id"""
        return self.host_map[member_id]

    def host2id(self, hostname):
        """return member id by hostname"""
        for key, value in self.host_map.items():
            if value == hostname:
                return key

    def update_host_map(self, config):
        """update host_map ({member_id:hostname})"""
        self.host_map = dict([(member['_id'], member['host']) for member in config['members']])

    def repl_init(self, config):
        """create replica set by config
        return True if replica set created successfuly, else False"""
        self.update_host_map(config)
        # init_host - host which can init replica set
        init_host = [member['host'] for member in config['members']
                     if not (member.get('arbiterOnly', False)
                             or member.get('priority', 1) == 0)][0]
        if not self.wait_while_reachable([member['host'] for member in config['members']]):
            logger.error("all hosts must be reachable")
            self.cleanup()
            return False

        result = self.connection(init_host).admin.command("replSetInitiate", config)
        logger.debug("replica init result: {result}".format(**locals()))
        if int(result.get('ok', 0)) == 1:
            # wait while real state equals config
            return self.waiting_config_state()
        else:
            self.cleanup()
            return False<commit_msg>use 3 attempts to init replica to prevent 'OperationFailure: all members and seeds must be reachable to initiate set' issue on mongodb legacy(2.0.7) version<commit_after>#!/usr/bin/python
# coding=utf-8

import logging
logger = logging.getLogger(__name__)
from uuid import uuid4
from singleton import Singleton
from container import Container
import pymongo
from hosts import Hosts
import time
import errors
import tempfile
import sys
import traceback

Hosts()


class ReplicaSet(object):
    """class represents ReplicaSet"""

    _hosts = Hosts()  # singleton to manage hosts instances
    # replica set's default parameters
    default_params = {'arbiterOnly': False, 'buildIndexes': False, 'hidden': False, 'slaveDelay': 0}

    def __init__(self, rs_params):
        """create replica set according members config
        Args:
            rs_params - replica set configuration
        """
        self.host_map = {}
        self.auth_key = rs_params.get('auth_key', None)
        self.login = rs_params.get('login', '')
        self.password = rs_params.get('password', '')
        self.repl_id = rs_params.get('id', None) or "rs-" + str(uuid4())

        config = {"_id": self.repl_id, "members": [
                  self.member_create(member, index) for index, member in enumerate(rs_params.get('members', {}))
                  ]}
        logger.debug("replica config: {config}".format(**locals()))
        if not self.repl_init(config):
            self.cleanup()
            raise errors.ReplicaSetError("replica can't started")

        if self.login:
            logger.debug("add admin user {login}/{password}".format(login=self.login, password=self.password))
            try:
                c = self.connection()
                c.admin.add_user(self.login, self.password)
            except pymongo.errors.OperationFailure:
                pass
            finally:
                c.close()

    def __len__(self):
        return len(self.host_map)

    def cleanup(self):
        """remove all members without reconfig"""
        for item in self.host_map:
            self.member_del(item, reconfig=False)
        self.host_map.clear()

    def id2host(self, member_id):
        """return hostname by member id"""
        return self.host_map[member_id]

    def host2id(self, hostname):
        """return member id by hostname"""
        for key, value in self.host_map.items():
            if value == hostname:
                return key

    def update_host_map(self, config):
        """update host_map ({member_id:hostname})"""
        self.host_map = dict([(member['_id'], member['host']) for member in config['members']])

    def repl_init(self, config):
        """create replica set by config
        return True if replica set created successfuly, else False"""
        self.update_host_map(config)
        # init_host - host which can init replica set
        init_host = [member['host'] for member in config['members']
                     if not (member.get('arbiterOnly', False)
                             or member.get('priority', 1) == 0)][0]

        hosts = [member['host'] for member in config['members']]
        # TODO: looks ugly, change it
        attempts = 3
        while attempts >= 0:
            attempts -= 1
            if not self.wait_while_reachable(hosts, timeout=90):
                continue
            try:
                result = self.connection(init_host).admin.command("replSetInitiate", config)
                logger.debug("replica init result: {result}".format(**locals()))
                if int(result.get('ok', 0)) == 1 and self.waiting_config_state():
                    return True
                    # wait while real state equals config
                    return self.waiting_config_state()
            except pymongo.errors.PyMongoError:
                # sometimes mongodb 2.0.7 has OperationFailure: all members and seeds must be reachable to initiate set
                # to prevent this issue uses 3 attempts to init replica
                if attempts >= 0:
                    time.sleep(3)
                else:
                    raise
        self.cleanup()
        return False
{'fraction_non_alphanumeric': 0.11087947882736156, 'fraction_numerical': 0.004820846905537459, 'mean_word_length': 2.277540563620837, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6130174', 'n_tokens_mistral': 2148, 'n_tokens_neox': 2056, 'n_words': 593}