# Path: mongoctl/utils.py
# def document_pretty_string(document):
#     return json.dumps(document, indent=4, default=json_util.default)
# 
# def wait_for(predicate, timeout=None, sleep_duration=2, grace=True):
#     start_time = now()
#     must_retry = may_retry = not predicate()
# 
#     if must_retry and grace:
#         # optimizing for predicates whose first invocations may be slooooooow
#         log_verbose("GRACE: First eval finished in %d secs - resetting timer." %
#                     (now() - start_time))
#         start_time = now()
# 
#     while must_retry and may_retry:
# 
#         must_retry = not predicate()
#         if must_retry:
#             net_time = now() - start_time
#             if timeout and net_time + sleep_duration > timeout:
#                 may_retry = False
#             else:
#                 left = "[-%d sec] " % (timeout - net_time) if timeout else ""
#                 log_info("-- waiting %s--" % left)
#                 time.sleep(sleep_duration)
# 
#     return not must_retry
# 
# def kill_process(pid, force=False):
#     sig = signal.SIGKILL if force else signal.SIGTERM
#     try:
#         os.kill(pid, sig)
#         return True
#     except OSError:
#         return False
# 
# def is_pid_alive(pid):
# 
#     try:
#         os.kill(pid,0)
#         return True
#     except OSError:
#         return False
# 
# Path: mongoctl/errors.py
# class MongoctlException(Exception):
#     def __init__(self, message, cause=None):
#         super(MongoctlException, self).__init__(message)
#         self._cause = cause


from bson.son import SON
from mongoctl.utils import (
    document_pretty_string, wait_for, kill_process, is_pid_alive
)
from mongoctl.mongoctl_logging import *
from mongoctl.errors import MongoctlException
from start import server_stopped_predicate
from mongoctl.prompt import prompt_execute_task
import mongoctl.repository
import mongoctl.objects.server


###############################################################################
def step_server_down(server, force=False):
    log_info("Stepping down server '%s'..." % server.id)

    try:
        cmd = SON( [('replSetStepDown', 10),('force', force)])
        server.disconnecting_db_command(cmd, "admin")
        log_info("Server '%s' stepped down successfully!" % server.id)
        return True
    except Exception, e:
        log_exception(e)
        log_error("Failed to step down server '%s'. Cause: %s" %
                  (server.id, e))
        return False

###############################################################################
def prompt_step_server_down(server, force):
    def step_down_func():
        step_server_down(server, force)

    return prompt_execute_task("Server '%s' is a primary server. "
                               "Step it down before proceeding to shutdown?" %
                               server.id,
                               step_down_func)

###############################################################################
def pid_dead_predicate(pid):
    def pid_dead():

# Path: mongoctl/utils.py
# def document_pretty_string(document):
#     return json.dumps(document, indent=4, default=json_util.default)
# 
# def wait_for(predicate, timeout=None, sleep_duration=2, grace=True):
#     start_time = now()
#     must_retry = may_retry = not predicate()
# 
#     if must_retry and grace:
#         # optimizing for predicates whose first invocations may be slooooooow
#         log_verbose("GRACE: First eval finished in %d secs - resetting timer." %
#                     (now() - start_time))
#         start_time = now()
# 
#     while must_retry and may_retry:
# 
#         must_retry = not predicate()
#         if must_retry:
#             net_time = now() - start_time
#             if timeout and net_time + sleep_duration > timeout:
#                 may_retry = False
#             else:
#                 left = "[-%d sec] " % (timeout - net_time) if timeout else ""
#                 log_info("-- waiting %s--" % left)
#                 time.sleep(sleep_duration)
# 
#     return not must_retry
# 
# def kill_process(pid, force=False):
#     sig = signal.SIGKILL if force else signal.SIGTERM
#     try:
#         os.kill(pid, sig)
#         return True
#     except OSError:
#         return False
# 
# def is_pid_alive(pid):
# 
#     try:
#         os.kill(pid,0)
#         return True
#     except OSError:
#         return False
# 
# Path: mongoctl/errors.py
# class MongoctlException(Exception):
#     def __init__(self, message, cause=None):
#         super(MongoctlException, self).__init__(message)
#         self._cause = cause


# Path: mongoctl/commands/server/stop.py
from bson.son import SON
from mongoctl.utils import (
    document_pretty_string, wait_for, kill_process, is_pid_alive
)
from mongoctl.mongoctl_logging import *
from mongoctl.errors import MongoctlException
from start import server_stopped_predicate
from mongoctl.prompt import prompt_execute_task
import mongoctl.repository
import mongoctl.objects.server



###############################################################################
def step_server_down(server, force=False):
    log_info("Stepping down server '%s'..." % server.id)

    try:
        cmd = SON( [('replSetStepDown', 10),('force', force)])
        server.disconnecting_db_command(cmd, "admin")
        log_info("Server '%s' stepped down successfully!" % server.id)
        return True
    except Exception, e:
        log_exception(e)
        log_error("Failed to step down server '%s'. Cause: %s" %
                  (server.id, e))
        return False

###############################################################################
def prompt_step_server_down(server, force):
    def step_down_func():
        step_server_down(server, force)

    return prompt_execute_task("Server '%s' is a primary server. "
                               "Step it down before proceeding to shutdown?" %
                               server.id,
                               step_down_func)

###############################################################################
def pid_dead_predicate(pid):
    def pid_dead():

        return not is_pid_alive(pid)