from ctypes import *
from errno import *
from socket import gethostname
import os

def die (msg):
    raise IOError, msg
    
class cr_checkpoint_args_t (Structure):
    _fields_ = [("cr_version", c_int),
                ("cr_scope", c_int),
                ("cr_target", c_int),
                ("cr_fd", c_int),
                ("cr_signal", c_int),
                ("cr_timeout", c_int),
                ("cr_flags", c_int)]
    
class timeval_t (Structure):
    _fields_ = [("tv_sec", c_long),
                ("tv_usec", c_long)]

libcr = CDLL ('/usr/lib64/libcr.so.0')

ERRNO = c_int.in_dll (libcr, 'errno')
print ERRNO

cr_args = cr_checkpoint_args_t()
cr_args.cr_version = 1
CR_SCOPE_PROC = 1

libcr.cri_initialize_checkpoint_args_t (byref(cr_args))
cr_args.cr_scope = CR_SCOPE_PROC
cr_args.cr_target = 0
cr_args.cr_signal = 0
cr_args.cr_timeout = 0
cr_args.cr_flags = 0

_id = libcr.cr_init()

if (_id < 0):
    die ("libcr cr_init failed")

libcr.cr_request_checkpoint.argtypes = [POINTER(cr_checkpoint_args_t), POINTER (c_ulong)]
libcr.cr_poll_checkpoint.argtypes = [POINTER(c_ulong), POINTER (timeval_t)]

cr_handle = c_ulong()

name = "checkpoint.%s.%d" % (gethostname(), os.getpid())
newname = name + '.new'

cp_file = open (newname, 'w')
cr_args.cr_fd = cp_file.fileno()

err = libcr.cr_request_checkpoint (byref(cr_args), byref(cr_handle))

err = -1
while (err < 0):
    err = libcr.cr_poll_checkpoint (byref(cr_handle), POINTER(timeval_t)())
    ##print 'e:', err, ERRNO, os.strerror(ERRNO.value)
    if (err < 0):
        if (ERRNO.value == EINVAL):
            break
        elif (ERRNO.value == EINTR):
            continue
        else:
            die ("cr_poll_checkpoint")
    elif (err == 0):
        die ("cr_poll_checkpoint returned unexpected 0")

try:
    ## This will fail in restart, because already closed
    cp_file.close()
    os.rename (newname, name)
except IOError:
    pass


