From: Neal Becker (ndbecker2_at_gmail.com)
Date: Sun Jul 29 2007 - 11:14:18 PDT
Based on studying the code in cr_checkpoint.c, I have come up with the following. Any comments appreciated. I'm guessing that the call to cr_request_checkpoint, followed by the cr_poll_checkpoint, will efficiently do the checkpoint and then wait for it to complete (but not necessarily be flushed to the disk). static void doit () { int newfd = creat (newname.c_str(), 0600); if (newfd < 0) die ("creat failed"); cr_args.cr_fd = newfd; cr_args.cr_scope = ... cr_checkpoint_handle_t cr_handle; int err = cr_request_checkpoint (&cr_args, &cr_handle); if (err < 0) die ("cr_request_checkpoint failed"); do { int err = cr_poll_checkpoint (&cr_handle, NULL); if (err < 0) { if (errno == EINVAL) { return; // restarted } else if (errno == EINTR) { ; } else { perror ("cr_poll_checkpoint"); break; } } else if (err == 0) { die ("cr_poll_checkpoint returned unexepected 0"); } } while (err < 0); if (err == -1) { die (std::string ("cr_poll_checkpoint") + strerror (err)); } else if (err == -2) { if (err == CR_ETEMPFAIL) { die("Checkpoint cancelled by application: try again later\n"); } else if (err == ESRCH) { die("Checkpoint failed: no processes checkpointed\n"); } else if (err == CR_EPERMFAIL) { die("Checkpoint cancelled by application: unable to checkpoint\n"); } else if (err == CR_ENOSUPPORT) { die("Checkpoint failed: support missing from application\n"); } else { die(std::string ("ioctl") + strerror (err)); } } else if (err < 0) { die(std::string ("cr_poll_checkpoint") + strerror (err)); } if (rename (newname.c_str(), name.c_str()) != 0) die ("rename failed"); }