ROOT logo

From $ROOTSYS/tutorials/proof/getProof.C

//
// This macro attaches to a PROOF session, possibly at the indicated URL.
// If no existing PROOF session is found and no URL is given, the macro
// tries to start a local PROOF session.

#include "Bytes.h"
#include "Getline.h"
#include "TEnv.h"
#include "TProof.h"
#include "TSocket.h"
#include "TString.h"
#include "TSystem.h"

// Auxilliary functions
Int_t getXrootdPid(Int_t port, const char *subdir = "xpdtut");
Int_t checkXrootdAt(Int_t port, const char *host = "localhost");
Int_t checkXproofdAt(Int_t port, const char *host = "localhost");
Int_t startXrootdAt(Int_t port, const char *exportdirs = 0, Bool_t force = kFALSE);
Int_t killXrootdAt(Int_t port, const char *id = 0);

// Auxilliary structures for Xrootd/Xproofd pinging ...
// The client request
typedef struct {
   int first;
   int second;
   int third;
   int fourth;
   int fifth;
} clnt_HS_t;
// The body received after the first handshake's header
typedef struct {
   int msglen;
   int protover;
   int msgval;
} srv_HS_t;

// By default we start a cluster on the local machine
const char *refloc = "proof://localhost:40000";

TProof *getProof(const char *url = "proof://localhost:40000", Int_t nwrks = -1, const char *dir = 0,
                 const char *opt = "ask", Bool_t dyn = kFALSE, Bool_t tutords = kFALSE)
{
   // Arguments:
   //     'url'      URL of the master where to start/attach the PROOF session;
   //                this is also the place where to force creation of a new session,
   //                if needed (use option 'N', e.g. "proof://mymaster:myport/?N")
   //
   // The following arguments apply to xrootd responding at 'refloc' only:
   //     'nwrks'    Number of workers to be started. []
   //     'dir'      Directory to be used for the files and working areas []. When starting a new
   //                instance of the daemon this directory is cleaned with 'rm -fr'. If 'dir'
   //                is null, the default is used: '/tmp/<user>/.getproof'
   //     'opt'      Defines what to do if an existing xrootd uses the same ports; possible
   //                options are: "ask", ask the user; "force", kill the xrootd and start
   //                a new one; if any other string is specified the existing xrootd will be
   //                used ["ask"].
   //                NB: for a change in 'nwrks' to be effective you need to specify opt = "force"
   //     'dyn'      This flag can be used to switch on dynamic, per-job worker setup scheduling
   //                [kFALSE].
   //     'tutords'  This flag can be used to force a dataset dir under the tutorial dir [kFALSE]
   //
   // It is possible to trigger the automatic valgrind setup by defining the env GETPROOF_VALGRIND.
   // E.g. to run the master in valgrind do
   //
   //     $ export GETPROOF_VALGRIND="valgrind=master"
   //
   // (or
   //     $ export GETPROOF_VALGRIND="valgrind=master valgrind_opts:--leak-check=full"
   //
   // to set some options) before running getProof. Note that 'getProof' is also called by 'stressProof',
   // so this holds for 'stressProof' runs too.

#ifdef __CINT__
   Printf("getProof: this script can only be executed via ACliC:");
   Printf("getProof:      root [] .x <path>/getProof.C+");
   Printf("getProof: or   root [] .L <path>/getProof.C+");
   Printf("getProof:      root [] getProof(...)");
   return;
#endif

   TProof *p = 0;

   // Valgrind options, if any
   TString vopt, vopts;
#ifndef WIN32
   if (gSystem->Getenv("GETPROOF_VALGRIND")) {
      TString s(gSystem->Getenv("GETPROOF_VALGRIND")), t;
      Int_t from = 0;
      while (s.Tokenize(t, from , " ")) {
         if (t.BeginsWith("valgrind_opts:"))
            vopts = t;
         else
            vopt = t;
      }
      if (vopts.IsNull()) vopts = "valgrind_opts:--leak-check=full --track-origins=yes";
      TProof::AddEnvVar("PROOF_WRAPPERCMD", vopts.Data());
      Printf("getProof: valgrind run: '%s' (opts: '%s')", vopt.Data(), vopts.Data());
   }
#endif

   // If an URL has specified get a session there
   TUrl uu(url), uref(refloc);
   Bool_t ext = (strcmp(uu.GetHost(), uref.GetHost()) ||
                 (uu.GetPort() != uref.GetPort())) ? kTRUE : kFALSE;
   if (ext && url && strlen(url) > 0) {
      Printf("getProof: trying to open a session on the external cluster at '%s'", url);
      if (!strcmp(url, "lite://")) {
         if (dir && strlen(dir) > 0) gEnv->SetValue("Proof.Sandbox", dir);
         if (nwrks > 0) uu.SetOptions(Form("workers=%d", nwrks));
      }
      p = TProof::Open(uu.GetUrl(), vopt);
      if (p && p->IsValid()) {
         // Check consistency
         if (ext && nwrks > 0) {
            Printf("getProof: WARNING: started/attached a session on external cluster (%s):"
                   " 'nwrks=%d' ignored", url, nwrks);
         }
         if (ext && dir && strlen(dir) > 0) {
            Printf("getProof: WARNING: started/attached a session on external cluster (%s):"
                   " 'dir=\"%s\"' ignored", url, dir);
         }
         if (ext && !strcmp(opt,"force")) {
            Printf("getProof: WARNING: started/attached a session on external cluster (%s):"
                   " 'opt=\"force\"' ignored", url);
         }
         if (ext && dyn) {
            Printf("getProof: WARNING: started/attached a session on external cluster (%s):"
                   " 'dyn=kTRUE' ignored", url);
         }
         // Done
         return p;
      } else {
 	 if (ext) {
            Printf("getProof: could not get/start a valid session at %s", url);
            return p;
         } else {
            Printf("getProof: could not get/start a valid session at %s - try resarting the daemon", url);
         }
      }
      if (p) delete p;
      p = 0;
   }

#ifdef WIN32
   // No support for local PROOF on Win32 (yet; the optimized local Proof will work there too)
   Printf("getProof: local PROOF not yet supported on Windows, sorry!");
   return p;
#else

   // Temp dir for tutorial daemons
   TString tutdir = dir;
   if (!tutdir.IsNull()) {
      if (gSystem->AccessPathName(tutdir)) {
         // Directory does not exist: try to make it
         gSystem->mkdir(tutdir.Data(), kTRUE);
         if (gSystem->AccessPathName(tutdir, kWritePermission)) {
            if (gSystem->AccessPathName(tutdir)) {
               Printf("getProof: unable to create the working area at the requested path: '%s'"
                      " - cannot continue", tutdir.Data());
            } else {
               Printf("getProof: working area at the requested path '%s'"
                      " created but it is not writable - cannot continue", tutdir.Data());
            }
            return p;
         }
      } else {
         // Check if it is writable ...
         if (gSystem->AccessPathName(dir, kWritePermission)) {
            // ... fail if not
            Printf("getProof: working area at the requested path '%s'"
                      " exists but is not writable - cannot continue", tutdir.Data());
            return p;
         }
      }
   } else {
      // Notify
      Printf("getProof: working area not specified temp ");
      // Force "/tmp/<user>" whenever possible to avoid length problems on MacOsX
      tutdir="/tmp"; 
      if (gSystem->AccessPathName(tutdir, kWritePermission)) tutdir = gSystem->TempDirectory();
      TString us;
      UserGroup_t *ug = gSystem->GetUserInfo(gSystem->GetUid());
      if (!ug) {
         Printf("getProof: could not get user info");
         return p;
      }
      us.Form("/%s", ug->fUser.Data());
      if (!tutdir.EndsWith(us.Data())) tutdir += us;
      // Add our own subdir
      tutdir += "/.getproof";
      if (gSystem->AccessPathName(tutdir)) {
         gSystem->mkdir(tutdir.Data(), kTRUE);
         if (gSystem->AccessPathName(tutdir, kWritePermission)) {
            Printf("getProof: unable to get a writable working area (tried: %s)"
                  " - cannot continue", tutdir.Data());
            return p;
         }
      }
   }
   Printf("getProof: working area (tutorial dir): %s", tutdir.Data());

   // Dataset dir
   TString datasetdir;
   if (tutords) {
      datasetdir = Form("%s/dataset", tutdir.Data());
      if (gSystem->AccessPathName(datasetdir, kWritePermission)) {
         gSystem->mkdir(datasetdir, kTRUE);
         if (gSystem->AccessPathName(datasetdir, kWritePermission)) {
            Printf("getProof: unable to get a writable dataset directory (tried: %s)"
                   " - cannot continue", datasetdir.Data());
            return p;
         }
         Printf("getProof: dataset dir: %s", datasetdir.Data());
      }
   }

   // Local url (use a special port to try to not disturb running daemons)
   TUrl u(refloc);
   u.SetProtocol("proof");
   if (!strcmp(uu.GetHost(), uref.GetHost()) && (uu.GetPort() != uref.GetPort()))
      u.SetPort(uu.GetPort());
   Int_t lportp = u.GetPort();
   Int_t lportx = lportp + 1;
   TString lurl = u.GetUrl();

   // Prepare to start the daemon
   TString workarea = Form("%s/proof", tutdir.Data());
   TString xpdcf(Form("%s/xpd.cf",tutdir.Data()));
   TString xpdlog(Form("%s/xpd.log",tutdir.Data()));
   TString xpdlogprt(Form("%s/xpdtut/xpd.log",tutdir.Data()));
   TString xpdpid(Form("%s/xpd.pid",tutdir.Data()));
   TString proofsessions(Form("%s/sessions",tutdir.Data()));
   TString cmd;
   Int_t rc = 0;

   // Is there something listening already ?
   Int_t pid = -1;
   Bool_t restart = kTRUE;
   if ((rc = checkXproofdAt(lportp)) == 1) {
      Printf("getProof: something else the a XProofd service is running on"
             " port %d - cannot continue", lportp);
      return p;

   } else if (rc == 0) {

      restart = kFALSE;

      pid = getXrootdPid(lportx);
      Printf("getProof: daemon found listening on dedicated ports {%d,%d} (pid: %d)",
              lportx, lportp, pid);
      if (isatty(0) == 0 || isatty(1) == 0) {
         // Cannot ask: always restart
         restart = kTRUE;
      } else {
         if (!strcmp(opt,"ask")) {
            char *answer = (char *) Getline("getProof: would you like to restart it (N,Y)? [N] ");
            if (answer && (answer[0] == 'Y' || answer[0] == 'y'))
               restart = kTRUE;
         }
      }
      if (!strcmp(opt,"force"))
         // Always restart
         restart = kTRUE;

      // Cleanup, if required
      if (restart) {
         Printf("getProof: cleaning existing instance ...");
         // Cleaning up existing daemon
         cmd = Form("kill -9 %d", pid);
         if ((rc = gSystem->Exec(cmd)) != 0)
            Printf("getProof: problems stopping xrootd process %d (%d)", pid, rc);
         // Wait for all previous connections being cleaned
         Printf("getProof: wait 5 secs so that previous connections are cleaned ...");
         gSystem->Sleep(5000);
      }
   }

   if (restart) {
      // Try to start something locally; make sure that everything is there
      char *xrootd = gSystem->Which(gSystem->Getenv("PATH"), "xrootd", kExecutePermission);
      if (!xrootd) {
         Printf("getProof: xrootd not found: please check the environment!");
         return p;
      }

      // Cleanup the working area
      cmd = Form("rm -fr %s/xpdtut %s %s %s %s", tutdir.Data(), workarea.Data(),
                                                 xpdcf.Data(), xpdpid.Data(), proofsessions.Data());
      gSystem->Exec(cmd);

      // Try to start something locally; create the xrootd config file
      FILE *fcf = fopen(xpdcf.Data(), "w");
      if (!fcf) {
         Printf("getProof: could not create config file for XPD (%s)", xpdcf.Data());
         return p;
      }
      fprintf(fcf,"### Use admin path at %s/admin to avoid interferences with other users\n", tutdir.Data());
      fprintf(fcf,"xrd.adminpath %s/admin\n", tutdir.Data());
#if defined(R__MACOSX)
      fprintf(fcf,"### Use dedicated socket path under /tmp to avoid length problems\n");
      fprintf(fcf,"xpd.sockpathdir /tmp/xpd-sock\n");
#endif
      fprintf(fcf,"### Run data serving on port %d\n", lportp+1);
      fprintf(fcf,"xrd.port %d\n", lportp+1);
      fprintf(fcf,"### Load the XrdProofd protocol on port %d\n", lportp);
      fprintf(fcf,"xrd.protocol xproofd libXrdProofd.so\n");
      fprintf(fcf,"xpd.port %d\n", lportp);
      if (nwrks > 0) {
         fprintf(fcf,"### Force number of local workers\n");
         fprintf(fcf,"xpd.localwrks %d\n", nwrks);
      }
      fprintf(fcf,"### Root path for working dir\n");
      fprintf(fcf,"xpd.workdir %s\n", workarea.Data());
      fprintf(fcf,"### Allow different users to connect\n");
      fprintf(fcf,"xpd.multiuser 1\n");
      fprintf(fcf,"### Limit the number of query results kept in the master sandbox\n");
      fprintf(fcf,"xpd.putrc ProofServ.UserQuotas: maxquerykept=10\n");
      if (tutords) {
         fprintf(fcf,"### Use dataset directory under the tutorial dir\n");
         fprintf(fcf,"xpd.datasetsrc file url:%s opt:-Cq:Av:As:\n", datasetdir.Data());
      }
      if (dyn) {
         fprintf(fcf,"### Use dynamic, per-job scheduling\n");
         fprintf(fcf,"xpd.putrc Proof.DynamicStartup 1\n");
      }
      fprintf(fcf,"### Local data server for the temporary output files\n");
      fprintf(fcf,"xpd.putenv LOCALDATASERVER=root://%s:%d\n", gSystem->HostName(), lportx);
      fclose(fcf);
      Printf("getProof: xrootd config file at %s", xpdcf.Data());

      // Start xrootd in the background
      Printf("getProof: xrootd log file at %s", xpdlogprt.Data());
      cmd = Form("%s -c %s -b -l %s -n xpdtut -p %d",
               xrootd, xpdcf.Data(), xpdlog.Data(), lportx);
      Printf("(NB: any error line from XrdClientSock::RecvRaw and XrdClientMessage::ReadRaw should be ignored)");
      if ((rc = gSystem->Exec(cmd)) != 0) {
         Printf("getProof: problems starting xrootd (%d)", rc);
         return p;
      }
      delete[] xrootd;

      // Wait a bit
      Printf("getProof: waiting for xrootd to start ...");
      gSystem->Sleep(2000);

      pid = getXrootdPid(lportx);
      Printf("getProof: xrootd pid: %d", pid);

      // Save it in the PID file
      FILE *fpid = fopen(xpdpid.Data(), "w");
      if (!fpid) {
         Printf("getProof: could not create pid file for XPD");
      } else {
         fprintf(fpid,"%d\n", pid);
         fclose(fpid);
      }
   }
   Printf("getProof: start / attach the PROOF session ...");

   // Start / attach the session now
   p = TProof::Open(lurl, vopt.Data());
   if (!p || !(p->IsValid())) {
      Printf("getProof: starting local session failed");
      if (p) delete p;
      p = 0;
      return p;
   }

   // Return the session
   return p;
#endif
}

Int_t getXrootdPid(Int_t port, const char *subdir)
{
#ifdef WIN32
   // No support for Xrootd/Proof on Win32 (yet; the optimized local Proof will work there too)
   Printf("getXrootdPid: Xrootd/Proof not supported on Windows, sorry!");
   return -1;
#else
   // Get the pid of the started xrootd process
   Int_t pid = -1;
#if defined(__sun)
   const char *com = "-eo pid,comm";
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
   const char *com = "ax -w -w";
#else
   const char *com = "-w -w -eo pid,command";
#endif
   TString cmd;
   if (subdir && strlen(subdir) > 0) {
      cmd.Form("ps %s | grep xrootd | grep \"\\-p %d\" | grep %s", com, port, subdir);
   } else {
      cmd.Form("ps %s | grep xrootd | grep \"\\-p %d\"", com, port);
   }
   FILE *fp = gSystem->OpenPipe(cmd.Data(), "r");
   if (fp) {
      char line[2048], rest[2048];
      while (fgets(line, sizeof(line), fp)) {
         sscanf(line,"%d %s", &pid, rest);
         break;
      }
      gSystem->ClosePipe(fp);
   }
   // Done
   return pid;
#endif
}

Int_t checkXrootdAt(Int_t port, const char *host)
{
   // Check if a XrdXrootd service is running on 'port' at 'host'
   // Return
   //        0 if OK
   //       -1 if nothing is listening on the port (connection cannot be open)
   //        1 if something is listening but not XROOTD

   // Open the connection
   TSocket s(host, port);
   if (!(s.IsValid())) {
      if (gDebug > 0)
         Printf("checkXrootdAt: could not open connection to %s:%d", host, port);
      return -1;
   }
   // Send the first bytes
   clnt_HS_t initHS;
   memset(&initHS, 0, sizeof(initHS));
   initHS.fourth = host2net((int)4);
   initHS.fifth  = host2net((int)2012);
   int len = sizeof(initHS);
   s.SendRaw(&initHS, len);
   // Read first server response
   int type;
   len = sizeof(type);
   int readCount = s.RecvRaw(&type, len); // 4(2+2) bytes
   if (readCount != len) {
      if (gDebug > 0)
         Printf("checkXrootdAt: 1st: wrong number of bytes read: %d (expected: %d)",
                                readCount, len);
      return 1;
   }
   // to host byte order
   type = net2host(type);
   // Check if the server is the eXtended proofd
   if (type == 0) {
      srv_HS_t xbody;
      len = sizeof(xbody);
      readCount = s.RecvRaw(&xbody, len); // 12(4+4+4) bytes
      if (readCount != len) {
         if (gDebug > 0)
            Printf("checkXrootdAt: 2nd: wrong number of bytes read: %d (expected: %d)",
                                   readCount, len);
         return 1;
      }

   } else if (type == 8) {
      // Standard proofd
      if (gDebug > 0)
         Printf("checkXrootdAt: server is ROOTD");
      return 1;
   } else {
      // We don't know the server type
      if (gDebug > 0)
         Printf("checkXrootdAt: unknown server type: %d", type);
      return 1;
   }
   // Done
   return 0;
}

Int_t checkXproofdAt(Int_t port, const char *host)
{
   // Check if a XrdProofd service is running on 'port' at 'host'
   // Return
   //        0 if OK
   //       -1 if nothing is listening on the port (connection cannot be open)
   //        1 if something is listening but not XPROOFD

   // Open the connection
   TSocket s(host, port);
   if (!(s.IsValid())) {
      if (gDebug > 0)
         Printf("checkXproofdAt: could not open connection to %s:%d", host, port);
      return -1;
   }
   // Send the first bytes
   clnt_HS_t initHS;
   memset(&initHS, 0, sizeof(initHS));
   initHS.third  = (int)host2net((int)1);
   int len = sizeof(initHS);
   s.SendRaw(&initHS, len);
   // These 8 bytes are need by 'proofd' and discarded by XPD
   int dum[2];
   dum[0] = (int)host2net((int)4);
   dum[1] = (int)host2net((int)2012);
   s.SendRaw(&dum[0], sizeof(dum));
   // Read first server response
   int type;
   len = sizeof(type);
   int readCount = s.RecvRaw(&type, len); // 4(2+2) bytes
   if (readCount != len) {
      if (gDebug > 0)
         Printf("checkXproofdAt: 1st: wrong number of bytes read: %d (expected: %d)",
                                 readCount, len);
      return 1;
   }
   // to host byte order
   type = net2host(type);
   // Check if the server is the eXtended proofd
   if (type == 0) {
      srv_HS_t xbody;
      len = sizeof(xbody);
      readCount = s.RecvRaw(&xbody, len); // 12(4+4+4) bytes
      if (readCount != len) {
         if (gDebug > 0)
            Printf("checkXproofdAt: 2nd: wrong number of bytes read: %d (expected: %d)",
                                    readCount, len);
         return 1;
      }
      xbody.protover = net2host(xbody.protover);
      xbody.msgval = net2host(xbody.msglen);
      xbody.msglen = net2host(xbody.msgval);

   } else if (type == 8) {
      // Standard proofd
      if (gDebug > 0)
         Printf("checkXproofdAt: server is PROOFD");
      return 1;
   } else {
      // We don't know the server type
      if (gDebug > 0)
         Printf("checkXproofdAt: unknown server type: %d", type);
      return 1;
   }
   // Done
   return 0;
}

Int_t startXrootdAt(Int_t port, const char *exportdirs, Bool_t force)
{
   // Start a basic xrootd service on 'port' exporting the dirs in 'exportdirs'
   // (blank separated list)

#ifdef WIN32
   // No support for Xrootd on Win32 (yet; the optimized local Proof will work there too)
   Printf("startXrootdAt: Xrootd not supported on Windows, sorry!");
   return -1;
#else
   Bool_t restart = kTRUE;

   // Already there?
   Int_t rc = 0;
   if ((rc = checkXrootdAt(port)) == 1) {

      Printf("startXrootdAt: some other service running on port %d - cannot proceed ", port);
      return -1;

   } else if (rc == 0) {

      restart = kFALSE;

      if (force) {
         // Always restart
         restart = kTRUE;
      } else {
         Printf("startXrootdAt: xrootd service already available on port %d: ", port);
         char *answer = (char *) Getline("startXrootdAt: would you like to restart it (N,Y)? [N] ");
         if (answer && (answer[0] == 'Y' || answer[0] == 'y')) {
            restart = kTRUE;
         }
      }

      // Cleanup, if required
      if (restart) {
         Printf("startXrootdAt: cleaning existing instance ...");

         // Get the Pid
         Int_t pid = getXrootdPid(port, "xrd-basic");

         // Cleanimg up existing daemon
         TString cmd = Form("kill -9 %d", pid);
         if ((rc = gSystem->Exec(cmd)) != 0)
            Printf("startXrootdAt: problems stopping xrootd process %d (%d)", pid, rc);
      }
   }

   if (restart) {
      if (gSystem->AccessPathName("/tmp/xrd-basic")) {
         gSystem->mkdir("/tmp/xrd-basic");
         if (gSystem->AccessPathName("/tmp/xrd-basic")) {
            Printf("startXrootdAt: could not assert dir for log file");
            return -1;
         }
      }
      TString cmd;
      cmd.Form("xrootd -d -p %d -b -l /tmp/xrd-basic/xrootd.log", port);
      if (exportdirs && strlen(exportdirs) > 0) {
         TString dirs(exportdirs), d;
         Int_t from = 0;
         while (dirs.Tokenize(d, from, " ")) {
            if (!d.IsNull()) {
               cmd += " ";
               cmd += d;
            }
         }
      }
      Printf("cmd: %s", cmd.Data());
      if ((rc = gSystem->Exec(cmd)) != 0) {
         Printf("startXrootdAt: problems executing starting command (%d)", rc);
         return -1;
      }
      // Wait a bit
      Printf("startXrootdAt: waiting for xrootd to start ...");
      gSystem->Sleep(2000);
      // Check the result
      if ((rc = checkXrootdAt(port)) != 0) {
         Printf("startXrootdAt: xrootd service not available at %d (rc = %d) - startup failed",
                                port, rc);
         return -1;
      }
      Printf("startXrootdAt: basic xrootd started!");
   }

   // Done
   return 0;
#endif
}

Int_t killXrootdAt(Int_t port, const char *id)
{
   // Kill running xrootd service on 'port'

#ifdef WIN32
   // No support for Xrootd on Win32 (yet; the optimized local Proof will work there too)
   Printf("killXrootdAt: Xrootd not supported on Windows, sorry!");
   return -1;
#else

   Int_t pid = -1, rc= 0;
   if ((pid = getXrootdPid(port, id)) > 0) {

      // Cleanimg up existing daemon
      TString cmd = Form("kill -9 %d", pid);
      if ((rc = gSystem->Exec(cmd)) != 0)
         Printf("killXrootdAt: problems stopping xrootd process %d (%d)", pid, rc);
   }

   // Done
   return rc;
#endif
}

 getProof.C:1
 getProof.C:2
 getProof.C:3
 getProof.C:4
 getProof.C:5
 getProof.C:6
 getProof.C:7
 getProof.C:8
 getProof.C:9
 getProof.C:10
 getProof.C:11
 getProof.C:12
 getProof.C:13
 getProof.C:14
 getProof.C:15
 getProof.C:16
 getProof.C:17
 getProof.C:18
 getProof.C:19
 getProof.C:20
 getProof.C:21
 getProof.C:22
 getProof.C:23
 getProof.C:24
 getProof.C:25
 getProof.C:26
 getProof.C:27
 getProof.C:28
 getProof.C:29
 getProof.C:30
 getProof.C:31
 getProof.C:32
 getProof.C:33
 getProof.C:34
 getProof.C:35
 getProof.C:36
 getProof.C:37
 getProof.C:38
 getProof.C:39
 getProof.C:40
 getProof.C:41
 getProof.C:42
 getProof.C:43
 getProof.C:44
 getProof.C:45
 getProof.C:46
 getProof.C:47
 getProof.C:48
 getProof.C:49
 getProof.C:50
 getProof.C:51
 getProof.C:52
 getProof.C:53
 getProof.C:54
 getProof.C:55
 getProof.C:56
 getProof.C:57
 getProof.C:58
 getProof.C:59
 getProof.C:60
 getProof.C:61
 getProof.C:62
 getProof.C:63
 getProof.C:64
 getProof.C:65
 getProof.C:66
 getProof.C:67
 getProof.C:68
 getProof.C:69
 getProof.C:70
 getProof.C:71
 getProof.C:72
 getProof.C:73
 getProof.C:74
 getProof.C:75
 getProof.C:76
 getProof.C:77
 getProof.C:78
 getProof.C:79
 getProof.C:80
 getProof.C:81
 getProof.C:82
 getProof.C:83
 getProof.C:84
 getProof.C:85
 getProof.C:86
 getProof.C:87
 getProof.C:88
 getProof.C:89
 getProof.C:90
 getProof.C:91
 getProof.C:92
 getProof.C:93
 getProof.C:94
 getProof.C:95
 getProof.C:96
 getProof.C:97
 getProof.C:98
 getProof.C:99
 getProof.C:100
 getProof.C:101
 getProof.C:102
 getProof.C:103
 getProof.C:104
 getProof.C:105
 getProof.C:106
 getProof.C:107
 getProof.C:108
 getProof.C:109
 getProof.C:110
 getProof.C:111
 getProof.C:112
 getProof.C:113
 getProof.C:114
 getProof.C:115
 getProof.C:116
 getProof.C:117
 getProof.C:118
 getProof.C:119
 getProof.C:120
 getProof.C:121
 getProof.C:122
 getProof.C:123
 getProof.C:124
 getProof.C:125
 getProof.C:126
 getProof.C:127
 getProof.C:128
 getProof.C:129
 getProof.C:130
 getProof.C:131
 getProof.C:132
 getProof.C:133
 getProof.C:134
 getProof.C:135
 getProof.C:136
 getProof.C:137
 getProof.C:138
 getProof.C:139
 getProof.C:140
 getProof.C:141
 getProof.C:142
 getProof.C:143
 getProof.C:144
 getProof.C:145
 getProof.C:146
 getProof.C:147
 getProof.C:148
 getProof.C:149
 getProof.C:150
 getProof.C:151
 getProof.C:152
 getProof.C:153
 getProof.C:154
 getProof.C:155
 getProof.C:156
 getProof.C:157
 getProof.C:158
 getProof.C:159
 getProof.C:160
 getProof.C:161
 getProof.C:162
 getProof.C:163
 getProof.C:164
 getProof.C:165
 getProof.C:166
 getProof.C:167
 getProof.C:168
 getProof.C:169
 getProof.C:170
 getProof.C:171
 getProof.C:172
 getProof.C:173
 getProof.C:174
 getProof.C:175
 getProof.C:176
 getProof.C:177
 getProof.C:178
 getProof.C:179
 getProof.C:180
 getProof.C:181
 getProof.C:182
 getProof.C:183
 getProof.C:184
 getProof.C:185
 getProof.C:186
 getProof.C:187
 getProof.C:188
 getProof.C:189
 getProof.C:190
 getProof.C:191
 getProof.C:192
 getProof.C:193
 getProof.C:194
 getProof.C:195
 getProof.C:196
 getProof.C:197
 getProof.C:198
 getProof.C:199
 getProof.C:200
 getProof.C:201
 getProof.C:202
 getProof.C:203
 getProof.C:204
 getProof.C:205
 getProof.C:206
 getProof.C:207
 getProof.C:208
 getProof.C:209
 getProof.C:210
 getProof.C:211
 getProof.C:212
 getProof.C:213
 getProof.C:214
 getProof.C:215
 getProof.C:216
 getProof.C:217
 getProof.C:218
 getProof.C:219
 getProof.C:220
 getProof.C:221
 getProof.C:222
 getProof.C:223
 getProof.C:224
 getProof.C:225
 getProof.C:226
 getProof.C:227
 getProof.C:228
 getProof.C:229
 getProof.C:230
 getProof.C:231
 getProof.C:232
 getProof.C:233
 getProof.C:234
 getProof.C:235
 getProof.C:236
 getProof.C:237
 getProof.C:238
 getProof.C:239
 getProof.C:240
 getProof.C:241
 getProof.C:242
 getProof.C:243
 getProof.C:244
 getProof.C:245
 getProof.C:246
 getProof.C:247
 getProof.C:248
 getProof.C:249
 getProof.C:250
 getProof.C:251
 getProof.C:252
 getProof.C:253
 getProof.C:254
 getProof.C:255
 getProof.C:256
 getProof.C:257
 getProof.C:258
 getProof.C:259
 getProof.C:260
 getProof.C:261
 getProof.C:262
 getProof.C:263
 getProof.C:264
 getProof.C:265
 getProof.C:266
 getProof.C:267
 getProof.C:268
 getProof.C:269
 getProof.C:270
 getProof.C:271
 getProof.C:272
 getProof.C:273
 getProof.C:274
 getProof.C:275
 getProof.C:276
 getProof.C:277
 getProof.C:278
 getProof.C:279
 getProof.C:280
 getProof.C:281
 getProof.C:282
 getProof.C:283
 getProof.C:284
 getProof.C:285
 getProof.C:286
 getProof.C:287
 getProof.C:288
 getProof.C:289
 getProof.C:290
 getProof.C:291
 getProof.C:292
 getProof.C:293
 getProof.C:294
 getProof.C:295
 getProof.C:296
 getProof.C:297
 getProof.C:298
 getProof.C:299
 getProof.C:300
 getProof.C:301
 getProof.C:302
 getProof.C:303
 getProof.C:304
 getProof.C:305
 getProof.C:306
 getProof.C:307
 getProof.C:308
 getProof.C:309
 getProof.C:310
 getProof.C:311
 getProof.C:312
 getProof.C:313
 getProof.C:314
 getProof.C:315
 getProof.C:316
 getProof.C:317
 getProof.C:318
 getProof.C:319
 getProof.C:320
 getProof.C:321
 getProof.C:322
 getProof.C:323
 getProof.C:324
 getProof.C:325
 getProof.C:326
 getProof.C:327
 getProof.C:328
 getProof.C:329
 getProof.C:330
 getProof.C:331
 getProof.C:332
 getProof.C:333
 getProof.C:334
 getProof.C:335
 getProof.C:336
 getProof.C:337
 getProof.C:338
 getProof.C:339
 getProof.C:340
 getProof.C:341
 getProof.C:342
 getProof.C:343
 getProof.C:344
 getProof.C:345
 getProof.C:346
 getProof.C:347
 getProof.C:348
 getProof.C:349
 getProof.C:350
 getProof.C:351
 getProof.C:352
 getProof.C:353
 getProof.C:354
 getProof.C:355
 getProof.C:356
 getProof.C:357
 getProof.C:358
 getProof.C:359
 getProof.C:360
 getProof.C:361
 getProof.C:362
 getProof.C:363
 getProof.C:364
 getProof.C:365
 getProof.C:366
 getProof.C:367
 getProof.C:368
 getProof.C:369
 getProof.C:370
 getProof.C:371
 getProof.C:372
 getProof.C:373
 getProof.C:374
 getProof.C:375
 getProof.C:376
 getProof.C:377
 getProof.C:378
 getProof.C:379
 getProof.C:380
 getProof.C:381
 getProof.C:382
 getProof.C:383
 getProof.C:384
 getProof.C:385
 getProof.C:386
 getProof.C:387
 getProof.C:388
 getProof.C:389
 getProof.C:390
 getProof.C:391
 getProof.C:392
 getProof.C:393
 getProof.C:394
 getProof.C:395
 getProof.C:396
 getProof.C:397
 getProof.C:398
 getProof.C:399
 getProof.C:400
 getProof.C:401
 getProof.C:402
 getProof.C:403
 getProof.C:404
 getProof.C:405
 getProof.C:406
 getProof.C:407
 getProof.C:408
 getProof.C:409
 getProof.C:410
 getProof.C:411
 getProof.C:412
 getProof.C:413
 getProof.C:414
 getProof.C:415
 getProof.C:416
 getProof.C:417
 getProof.C:418
 getProof.C:419
 getProof.C:420
 getProof.C:421
 getProof.C:422
 getProof.C:423
 getProof.C:424
 getProof.C:425
 getProof.C:426
 getProof.C:427
 getProof.C:428
 getProof.C:429
 getProof.C:430
 getProof.C:431
 getProof.C:432
 getProof.C:433
 getProof.C:434
 getProof.C:435
 getProof.C:436
 getProof.C:437
 getProof.C:438
 getProof.C:439
 getProof.C:440
 getProof.C:441
 getProof.C:442
 getProof.C:443
 getProof.C:444
 getProof.C:445
 getProof.C:446
 getProof.C:447
 getProof.C:448
 getProof.C:449
 getProof.C:450
 getProof.C:451
 getProof.C:452
 getProof.C:453
 getProof.C:454
 getProof.C:455
 getProof.C:456
 getProof.C:457
 getProof.C:458
 getProof.C:459
 getProof.C:460
 getProof.C:461
 getProof.C:462
 getProof.C:463
 getProof.C:464
 getProof.C:465
 getProof.C:466
 getProof.C:467
 getProof.C:468
 getProof.C:469
 getProof.C:470
 getProof.C:471
 getProof.C:472
 getProof.C:473
 getProof.C:474
 getProof.C:475
 getProof.C:476
 getProof.C:477
 getProof.C:478
 getProof.C:479
 getProof.C:480
 getProof.C:481
 getProof.C:482
 getProof.C:483
 getProof.C:484
 getProof.C:485
 getProof.C:486
 getProof.C:487
 getProof.C:488
 getProof.C:489
 getProof.C:490
 getProof.C:491
 getProof.C:492
 getProof.C:493
 getProof.C:494
 getProof.C:495
 getProof.C:496
 getProof.C:497
 getProof.C:498
 getProof.C:499
 getProof.C:500
 getProof.C:501
 getProof.C:502
 getProof.C:503
 getProof.C:504
 getProof.C:505
 getProof.C:506
 getProof.C:507
 getProof.C:508
 getProof.C:509
 getProof.C:510
 getProof.C:511
 getProof.C:512
 getProof.C:513
 getProof.C:514
 getProof.C:515
 getProof.C:516
 getProof.C:517
 getProof.C:518
 getProof.C:519
 getProof.C:520
 getProof.C:521
 getProof.C:522
 getProof.C:523
 getProof.C:524
 getProof.C:525
 getProof.C:526
 getProof.C:527
 getProof.C:528
 getProof.C:529
 getProof.C:530
 getProof.C:531
 getProof.C:532
 getProof.C:533
 getProof.C:534
 getProof.C:535
 getProof.C:536
 getProof.C:537
 getProof.C:538
 getProof.C:539
 getProof.C:540
 getProof.C:541
 getProof.C:542
 getProof.C:543
 getProof.C:544
 getProof.C:545
 getProof.C:546
 getProof.C:547
 getProof.C:548
 getProof.C:549
 getProof.C:550
 getProof.C:551
 getProof.C:552
 getProof.C:553
 getProof.C:554
 getProof.C:555
 getProof.C:556
 getProof.C:557
 getProof.C:558
 getProof.C:559
 getProof.C:560
 getProof.C:561
 getProof.C:562
 getProof.C:563
 getProof.C:564
 getProof.C:565
 getProof.C:566
 getProof.C:567
 getProof.C:568
 getProof.C:569
 getProof.C:570
 getProof.C:571
 getProof.C:572
 getProof.C:573
 getProof.C:574
 getProof.C:575
 getProof.C:576
 getProof.C:577
 getProof.C:578
 getProof.C:579
 getProof.C:580
 getProof.C:581
 getProof.C:582
 getProof.C:583
 getProof.C:584
 getProof.C:585
 getProof.C:586
 getProof.C:587
 getProof.C:588
 getProof.C:589
 getProof.C:590
 getProof.C:591
 getProof.C:592
 getProof.C:593
 getProof.C:594
 getProof.C:595
 getProof.C:596
 getProof.C:597
 getProof.C:598
 getProof.C:599
 getProof.C:600
 getProof.C:601
 getProof.C:602
 getProof.C:603
 getProof.C:604
 getProof.C:605
 getProof.C:606
 getProof.C:607
 getProof.C:608
 getProof.C:609
 getProof.C:610
 getProof.C:611
 getProof.C:612
 getProof.C:613
 getProof.C:614
 getProof.C:615
 getProof.C:616
 getProof.C:617
 getProof.C:618
 getProof.C:619
 getProof.C:620
 getProof.C:621
 getProof.C:622
 getProof.C:623
 getProof.C:624
 getProof.C:625
 getProof.C:626
 getProof.C:627
 getProof.C:628
 getProof.C:629
 getProof.C:630
 getProof.C:631
 getProof.C:632
 getProof.C:633
 getProof.C:634
 getProof.C:635
 getProof.C:636
 getProof.C:637
 getProof.C:638
 getProof.C:639
 getProof.C:640
 getProof.C:641
 getProof.C:642
 getProof.C:643
 getProof.C:644
 getProof.C:645
 getProof.C:646
 getProof.C:647
 getProof.C:648
 getProof.C:649
 getProof.C:650
 getProof.C:651
 getProof.C:652
 getProof.C:653