home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / sql / dblib / c / nmpsdmp / nmpsdmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-03  |  19.8 KB  |  741 lines

  1. // NMPSDMP.C
  2. //
  3. // DBLIB program for using named pipe dump devices for backup and restore data
  4. // from SQL Server 95.This program is an example and shows the usage of named pipe
  5. // dump devices on the client side.
  6. //
  7. //
  8. // The program needs the following arguments (it asks from the user interactively) :
  9. //    Operation    : DUMP/LOAD
  10. //    Servername    : Name of the server to dump from/load into
  11. //    Databasename: Name of the database to be dumped/loaded
  12. //    Stripenum    : How many pipes are to be used for dump/load
  13. //    Dumpname    : Prefix of the files to write/read the dumped/load data (DMP postfix)
  14.  
  15. #define DBNTWIN32
  16. #include <windows.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <process.h>
  20. #include <sqlfront.h>
  21. #include <sqldb.h>
  22.  
  23. // definitions
  24. #define MAX_DEVICES            32                // maximum number of stripe devices
  25. #define PIPE_WAIT_TIME        500                // wait time in milliseconds
  26. #define    DBPAGESIZE            2048            // size of physical page dumped
  27.  
  28. // status values for dump/load threads
  29. #define STAT_SUCCESS        0x0                // default status
  30. #define STAT_ERROR            0x1                  // error in the current thread
  31. #define STAT_ENDTHREAD        0x2                // the current thread has terminated
  32.  
  33. // opcode values
  34. #define DUMP_MODE            0x1                // dump mode of operation
  35. #define LOAD_MODE            0x2                // load mode of operation
  36.  
  37. // this structure is maintained on a global basis among all threads that
  38. // are doing reads/writes from pipe
  39. typedef struct ginfo
  40. {
  41.     char     servername[30];    // server name
  42.     char     dbname[30];        // database name            
  43.     char     dumpname[80];    // dump file prefix
  44.     char    password[30];    // dblogin password of SA
  45.     long    status;            // global status flag for error recovery
  46.     short    opcode;            // operation code
  47.     short    stripenum;        // number of pipe devices to be used
  48. } GINFO;
  49.  
  50. // this structure contains pipe specific info to be run by different threads
  51. // that read/write data during the stripe dump/load
  52. typedef struct pipeinfo
  53. {
  54.     char    pipename[80];    // Physical name of pipe used for client
  55.     char    spipename[80];    // Physical name of pipe sent to SQL Server
  56.     char    dumpname[80];    // Physical name of the dump file
  57.     short    slot;            // which device slot
  58.     GINFO    *curinfo;        // pointer to global info buffer
  59.     long    status;            // thread local status        
  60. } PIPEINFO;
  61.  
  62. // Macros
  63. # define NEWARG(i)       (*(argv[i]) == '-' || *(argv[i]) == '/')
  64. # define BUFALIGN(a)    ( (BYTE *) ( ((long)a + 64) & 0xffffffc0) )
  65.  
  66.  
  67. // function prototypes
  68. void parse_parms(int argc, char *argv[], GINFO *curinfo);
  69. void argvalue(int i, int argc, char* argv[], char* out);
  70. int set_up_pipes(GINFO *curinfo, PIPEINFO **pipes);
  71. void close_up_pipes(GINFO *curinfo, PIPEINFO **pipes);
  72. void dump_proc(PIPEINFO    *curpipe);
  73. void load_proc(PIPEINFO    *curpipe);
  74. INT msg_handler(PDBPROCESS,DBINT,INT,INT,LPCSTR,LPCSTR,LPCSTR,DBUSMALLINT);
  75. INT err_handler(PDBPROCESS,INT,INT,INT,LPCSTR,LPCSTR);
  76.  
  77. // start of the progam
  78. main(int argc, char *argv[])
  79. {
  80.  
  81.     RETCODE        retcode;                // DBLIB return code
  82.     LOGINREC     *loginrec = NULL;        // DBLIB LOGINREC pointer
  83.     DBPROCESS     *dbproc = NULL;            // DBLIB DBPROC pointer
  84.     GINFO        info;                    // to store global info & status
  85.     PIPEINFO    *pipes[MAX_DEVICES];    // array of PIPEINFO pointers
  86.     char        cmd[1024];                // SQL command buffer
  87.  
  88.        // scratch variables
  89.       char        scratch[80];
  90.     int            i;
  91.  
  92.       // Initialize
  93.     for (i=0; i<MAX_DEVICES; i++)
  94.         pipes[i] = NULL;
  95.  
  96.     info.servername[0] = 0;
  97.     info.dbname[0] = 0;
  98.     info.dumpname[0] = 0;
  99.     info.password[0] = 0;
  100.     info.stripenum = 1;
  101.     info.opcode = DUMP_MODE;
  102.     info.status = STAT_SUCCESS;
  103.  
  104.     // read the user input
  105.     parse_parms(argc, argv, &info);
  106.  
  107.     // Install the DBLIB handlers
  108.     dberrhandle(err_handler);
  109.     dbmsghandle(msg_handler);
  110.  
  111.     printf("Logging on to server...\n");
  112.  
  113.     loginrec = dblogin();
  114.     DBSETLUSER(loginrec, "sa");
  115.     DBSETLPWD(loginrec,"");
  116.  
  117.     if ((dbproc = dbopen(loginrec, info.servername)) == (DBPROCESS *)NULL)
  118.     {
  119.       printf("dbopen() failed");
  120.       info.status |= STAT_ERROR;
  121.       goto clean_up;
  122.     };
  123.  
  124.     // Set up the thread(s) for reading/writing the pipe device
  125.     if (!set_up_pipes(&info, pipes))
  126.     {
  127.         info.status |= STAT_ERROR;
  128.         goto clean_up;
  129.     }
  130.  
  131.     // prepare the command now
  132.     if (info.opcode == DUMP_MODE)
  133.         strcpy(cmd, "dump database ");
  134.     else
  135.         strcpy(cmd, "load database ");
  136.     strcat(cmd, info.dbname);
  137.     if (info.opcode == DUMP_MODE)
  138.         strcat(cmd, " to ");
  139.     else
  140.         strcat(cmd, " from ");
  141.     for (i=0; i < info.stripenum; i++)
  142.     {
  143.         sprintf(scratch, "pipe = '%s'", &pipes[i]->spipename);
  144.         strcat(cmd, scratch);
  145.         if ((i+1) < info.stripenum)
  146.             strcat(cmd, ", ");
  147.     }
  148.     printf("Command : <%s>\n", cmd);
  149.  
  150.     // this thread will be blocked till the dump/load command is not
  151.     // completed; for changing the behavior to non blocking, use
  152.     // dbsqlsend(), dbdataready() and dbsqlok() instead of dbsqlexec()
  153.     retcode = dbcmd(dbproc, cmd);
  154.     retcode = dbsqlexec(dbproc);
  155.  
  156.        if (retcode != SUCCEED)
  157.     {
  158.         printf("dbsqlexec failed\n");
  159.         info.status |= STAT_ERROR;
  160.         goto clean_up;
  161.     }
  162.  
  163.        // discard results ; we do not need it
  164.        while (dbresults(dbproc) == SUCCEED)
  165.         while (dbnextrow(dbproc) != NO_MORE_ROWS)
  166.             ;
  167.  
  168.     // We are done with all the work ; clean up the resources and exit
  169.     // strictly speaking, cleanup is not necessary for this since we
  170.     // will exit the program (but for implementing this as a procedures
  171.     // would involve cleanup)
  172. clean_up:
  173.  
  174.     if (dbproc)
  175.            dbclose(dbproc);
  176.     if (loginrec)
  177.         dbfreelogin(loginrec);
  178.  
  179.     close_up_pipes(&info, pipes);
  180.     exit(1);
  181.     return(0);
  182. }
  183.  
  184. // procedure to get all the parameters
  185. void  parse_parms(int argc, char *argv[], GINFO *curinfo)
  186. {
  187.     int     i;
  188.     char    argval[30];
  189.  
  190.     for (i = 0 ; i < argc; i++)
  191.     {
  192.         if (NEWARG(i))
  193.         {
  194.             switch(*(argv[i] + 1))
  195.             {
  196.                 case 'S' : // Servername
  197.                     argvalue(i,argc,argv,curinfo->servername);
  198.                     break;
  199.  
  200.                 case 'D' : // Databasename
  201.                     argvalue(i,argc,argv,curinfo->dbname);
  202.                     break;
  203.  
  204.                 case 'P' : // SA password
  205.                     argvalue(i,argc,argv,curinfo->password);
  206.                     break;
  207.  
  208.                 case 'N' : // Stripe Number
  209.                     argvalue(i,argc,argv,argval);
  210.                     if ((curinfo->stripenum = (short)atoi(argval)) < 1)
  211.                     {
  212.                         printf("Invalid value %d for stripe device. Setting to 1\n");
  213.                         curinfo->stripenum = 1;
  214.                     }
  215.                     else if (curinfo->stripenum > MAX_DEVICES)
  216.                     {
  217.                         printf("Invalid value %d for stripe device. Setting to %d\n",
  218.                                 MAX_DEVICES);
  219.                         curinfo->stripenum = MAX_DEVICES;
  220.                     }
  221.                     break;
  222.  
  223.                 case 'F' : // Dump file prefix
  224.                     argvalue(i,argc,argv,curinfo->dumpname);
  225.                     break;
  226.  
  227.                 case 'O' : // Mode of operation
  228.                     argvalue(i,argc,argv,argval);
  229.                     if ( (!strcmp(argval, "DUMP")) || (!strcmp(argval, "dump")) )
  230.                         curinfo->opcode = DUMP_MODE;
  231.                     else if ( (!strcmp(argval, "LOAD")) || (!strcmp(argval, "load")) )
  232.                         curinfo->opcode = LOAD_MODE;
  233.                     else
  234.                     {
  235.                         printf("Invalid mode %s specified\n", argval);
  236.                         exit(1);
  237.                     }
  238.                     break;
  239.  
  240.                 case '?' : // Help message
  241.                     printf("NMPSDMP -Sservername -Ppassword -O{dump | load} -Ddatabasename -Nstripenumber -Fdumpprefix\n");
  242.                     exit(1);
  243.                     break;
  244.  
  245.                 default:
  246.                     printf("Invalid    parameter option : %s\n", *(argv[i] + 1) );
  247.                     printf("NMPSDMP -Sservername -Ppassword -O{dump | load} -Ddatabasename -Nstripenumber -Fdumpprefix\n");
  248.                     exit(1);
  249.             }
  250.         }
  251.     }
  252.     return;
  253. }
  254.  
  255. // argument reading routine for parse_parms()
  256. void argvalue(
  257.     int   i,                           // parameter number
  258.     int   argc,                        // #args
  259.     char* argv[],                      // arglist
  260.     char* out                          // receives parm 'i'
  261. ){
  262.     if( *(argv[i]+2) )
  263.         strcpy(out, argv[i]+2);
  264.     else
  265.     {
  266.         if( i+1<argc && !( NEWARG(i+1) ) )
  267.             strcpy(out, argv[i+1]);
  268.     }
  269. }
  270.  
  271. // procedure to setup all the threads for reading pipes
  272. //
  273. // return : 1 if success
  274. //            0 otherwise
  275. int set_up_pipes(GINFO *curinfo, PIPEINFO **pipes)
  276. {
  277.     
  278.     int        i;
  279.     PIPEINFO    *curpipe;
  280.     char        pipebuf[30];
  281.  
  282.     // for every device
  283.     for (i=0; i < curinfo->stripenum; i++)
  284.     {
  285.         // allocate for the current pipe
  286.         if ((curpipe = malloc(sizeof(PIPEINFO))) == NULL)
  287.             return 0;
  288.         curpipe->slot = i;
  289.         curpipe->curinfo = curinfo;
  290.         curpipe->status = STAT_SUCCESS;
  291.  
  292.         // prepare the pipe name
  293.         strcpy(curpipe->pipename, "\\\\");
  294.         strcpy(curpipe->spipename, "\\\\");
  295.         if (curinfo->servername[0])
  296.             strcat(curpipe->pipename, curinfo->servername);
  297.         else
  298.             strcat(curpipe->pipename, ".");
  299.         strcat(curpipe->spipename, ".");
  300.         strcat(curpipe->pipename, "\\pipe\\");
  301.         strcat(curpipe->spipename, "\\pipe\\");
  302.         sprintf(pipebuf, "sqldmpld%d", i);
  303.         strcat(curpipe->pipename, pipebuf);
  304.         strcat(curpipe->spipename, pipebuf);
  305.  
  306.         // prepare the dump file name
  307.         sprintf(curpipe->dumpname, "%s%d.dmp", curinfo->dumpname, i);
  308.  
  309.         // now start the thread for this device
  310.         pipes[i] = curpipe;
  311.         if (curinfo->opcode == DUMP_MODE)
  312.         {
  313.             if (!(_beginthread(dump_proc, 0, (LPVOID)curpipe)))
  314.             {
  315.                 printf("beginthread failed for slot %d\n", i);
  316.                 return 0;
  317.             }
  318.         }
  319.         else
  320.         {
  321.             if (!(_beginthread(load_proc, 0, (LPVOID)curpipe)))
  322.             {
  323.                 printf("beginthread failed for slot %d\n", i);
  324.                 return 0;
  325.             }
  326.         }
  327.     }
  328.  
  329.     // started all the threads
  330.     return 1;
  331. }
  332.  
  333. // procedure to close all the threads for reading/writing pipes
  334. //
  335. // return : nothing
  336. //
  337. void close_up_pipes(GINFO *curinfo, PIPEINFO **pipes)
  338. {
  339.     int            i;
  340.     PIPEINFO    *curpipe;
  341.  
  342.     // check if we need to clean up
  343.     if (!curinfo->stripenum)
  344.         return;
  345.  
  346.     // for every open device
  347.     for (i=0; i < curinfo->stripenum; i++)
  348.     {
  349.         if (!(curpipe = pipes[i]))
  350.             continue;
  351.  
  352.         // wait for the thread to close itself
  353.         while (!(curpipe->status & STAT_ENDTHREAD))
  354.             SleepEx(10, TRUE);            
  355.  
  356.         // free the allocated memory
  357.         free(curpipe);
  358.     }
  359. }
  360.  
  361. // DUMP_PROC
  362. //     This procedure does the opening and reading of dumped data sent
  363. //    by the SQL Server. Each thread invoked with this routine services
  364. //    one named pipe (instance) connection; for simplicity we are creating
  365. //    separate named pipes for each stripe number.
  366. //                
  367. //    For dump process, the thread opens the pipe created by SQL Server
  368. //     and connects to it. Then keeps reading data and writing it
  369. //    out to the dumpfile till the SQL Server is done.
  370.  
  371. void dump_proc(PIPEINFO    *curpipe)
  372. {
  373.     GINFO        *curinfo = curpipe->curinfo;
  374.     HANDLE        hpipe = NULL;
  375.     HANDLE        hfile = NULL;
  376.     BYTE        *buf_start = NULL;
  377.     BYTE        *buf_ptr;
  378.     DWORD        bufsize, cbread, cbwritten, mode;
  379.     DWORD        errcode = 0;
  380.     DWORD        offl, offh;
  381.  
  382.     // Open the pipe
  383.     while (1)
  384.     {
  385.  
  386.         // check the global flag
  387.         if (curinfo->status & STAT_ERROR)
  388.             goto dump_proc_cleanup;
  389.  
  390.         hpipe = CreateFile(curpipe->pipename,
  391.                 GENERIC_READ | GENERIC_WRITE, 0, NULL,
  392.                 OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
  393.  
  394.         // break if handle is valid
  395.         if (hpipe != INVALID_HANDLE_VALUE)
  396.             break;
  397.         
  398.         // check the pipe state
  399.         errcode = GetLastError();
  400.         if (errcode == ERROR_FILE_NOT_FOUND)
  401.         {
  402.             // SQL Server has not yet created the pipe; wait
  403.             SleepEx(PIPE_WAIT_TIME, TRUE);
  404.             continue;
  405.         }
  406.         else if (errcode != ERROR_PIPE_BUSY)
  407.         {
  408.             printf("Error in %s : %d\n", "CreateFile", errcode);
  409.             curpipe->status |= STAT_ERROR;
  410.             goto dump_proc_cleanup;
  411.         }
  412.  
  413.         // Wait for sometime if pipe is busy
  414.         if (!WaitNamedPipe(curpipe->pipename, PIPE_WAIT_TIME))
  415.         {
  416.             printf("Error in %s : %d\n", "WaitNamedPipe", GetLastError());
  417.             curpipe->status |= STAT_ERROR;
  418.             goto dump_proc_cleanup;
  419.         }
  420.     }
  421.     
  422.     printf("dump thread : %d : connected to server\n", curpipe->slot);
  423.                                 
  424.     // get the buffer size
  425.     if ((!GetNamedPipeInfo(hpipe, NULL, NULL, &bufsize, NULL)) || (bufsize == 0))
  426.     {
  427.         printf("Error in %s : %d\n", "GetNamedPipeInfo", GetLastError());
  428.         curpipe->status |= STAT_ERROR;
  429.         goto dump_proc_cleanup;
  430.     }
  431.  
  432.     // Align the buffer size to database pagesize if necessary
  433.     if (bufsize % DBPAGESIZE)
  434.         bufsize = ((bufsize / DBPAGESIZE) - 1) * DBPAGESIZE;
  435.     //printf("dump thread : %d : buffer size %d \n", curpipe->slot, bufsize);
  436.  
  437.     // allocate the buffer for reading incoming data and align it
  438.     if ((buf_start = malloc(bufsize + 64)) == NULL)
  439.     {
  440.         printf("malloc failed\n");
  441.         curpipe->status |= STAT_ERROR;
  442.         goto dump_proc_cleanup;
  443.     }
  444.     buf_ptr = BUFALIGN(buf_start);
  445.  
  446.     // Set the pipe mode to message read mode 
  447.     mode = PIPE_READMODE_MESSAGE;
  448.     if (!SetNamedPipeHandleState(hpipe, &mode, NULL, NULL))
  449.     {
  450.         printf("Error in %s : %d\n", "SetNamedPipeHandleState", GetLastError());
  451.         curpipe->status |= STAT_ERROR;
  452.         goto dump_proc_cleanup;
  453.     }
  454.  
  455.     // open the dump file ; if it exists then overwrite it
  456.     // otherwise open a new file
  457.     hfile = CreateFile(curpipe->dumpname,
  458.             GENERIC_READ | GENERIC_WRITE, 0, NULL,
  459.             CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  460.     if (hfile == INVALID_HANDLE_VALUE)
  461.     {
  462.         printf("Error in %s : %d\n", "CreateFile", GetLastError());
  463.         curpipe->status |= STAT_ERROR;
  464.         goto dump_proc_cleanup;
  465.     }
  466.  
  467.     // set the file pointer to start of file
  468.     offh = 0;
  469.     if ((offl = SetFilePointer(hfile, 0, &offh, FILE_BEGIN)) == -1)
  470.     {
  471.         printf("Error in %s : %d\n", "SetFilePointer", GetLastError());
  472.         curpipe->status |= STAT_ERROR;
  473.         goto dump_proc_cleanup;
  474.     }
  475.  
  476.     // now we are all set to read from the pipe; keep reading till the pipe is
  477.     // closed.
  478.     while (1)
  479.     {
  480.         // check the global flag
  481.         if (curinfo->status & STAT_ERROR)
  482.             goto dump_proc_cleanup;
  483.  
  484.         if (!ReadFile(hpipe, buf_ptr, bufsize, &cbread, NULL))
  485.         {
  486.             // Are we done reading
  487.             if ((errcode = GetLastError()) == ERROR_BROKEN_PIPE)
  488.                 break;
  489.             if (errcode != ERROR_MORE_DATA)
  490.             {
  491.                 printf("Error in %s : %d\n", "ReadFile", errcode);
  492.                 curpipe->status |= STAT_ERROR;
  493.                 goto dump_proc_cleanup;
  494.             }
  495.         }
  496.         //printf("dump thread : %d : read %d bytes\n", curpipe->slot, cbread);
  497.         if (!WriteFile(hfile, buf_ptr, cbread, &cbwritten, NULL))
  498.         {
  499.             printf("Error in %s : %d\n", "WriteFile", GetLastError());
  500.             curpipe->status |= STAT_ERROR;
  501.             goto dump_proc_cleanup;
  502.         }
  503.     }
  504.  
  505. dump_proc_cleanup:
  506.  
  507.     // release the resources
  508.     if (buf_start)
  509.         free(buf_start);
  510.     if (hfile)
  511.     {
  512.         FlushFileBuffers(hfile);
  513.         CloseHandle(hfile);
  514.     }
  515.     if (hpipe)
  516.         CloseHandle(hpipe);
  517.  
  518.     // set the status flags
  519.     curpipe->status |= STAT_ENDTHREAD;
  520.     if (curpipe->status & STAT_ERROR)
  521.         curinfo->status |= STAT_ERROR;
  522.  
  523.     return;
  524. }
  525.  
  526. // LOAD_PROC
  527. //     This procedure does the opening and writing of dumped data sent
  528. //    to the SQL Server. Each thread invoked with this routine services
  529. //    one named pipe (instance) connection; we are create
  530. //    separate named pipes for each stripe number.
  531. //                
  532. //    For load process, the thread opens the pipe created by SQL Server
  533. //     and connects to it. Then keeps reading data from the dumpfile till end
  534. //  and writes to the pipe; Finally closes the pipe when done.
  535.  
  536. void load_proc(PIPEINFO    *curpipe)
  537. {
  538.     GINFO        *curinfo = curpipe->curinfo;
  539.     HANDLE        hpipe = NULL;
  540.     HANDLE        hfile = NULL;
  541.     BYTE        *buf_start = NULL;
  542.     BYTE        *buf_ptr;
  543.     DWORD        bufsize, cbread, cbwritten, mode;
  544.     DWORD        errcode = 0;
  545.     DWORD        offl, offh;
  546.  
  547.     // Open the pipe
  548.     while (1)
  549.     {
  550.  
  551.         // check the global flag
  552.         if (curinfo->status & STAT_ERROR)
  553.             goto load_proc_cleanup;
  554.  
  555.         hpipe = CreateFile(curpipe->pipename,
  556.                 GENERIC_READ | GENERIC_WRITE, 0, NULL,
  557.                 OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
  558.  
  559.         // break if handle is valid
  560.         if (hpipe != INVALID_HANDLE_VALUE)
  561.             break;
  562.         
  563.         // check the pipe state
  564.         errcode = GetLastError();
  565.         if (errcode == ERROR_FILE_NOT_FOUND)
  566.         {
  567.             // SQL Server has not yet created the pipe; wait
  568.             SleepEx(PIPE_WAIT_TIME, TRUE);
  569.             continue;
  570.         }
  571.         else if (errcode != ERROR_PIPE_BUSY)
  572.         {
  573.             printf("Error in %s : %d\n", "CreateFile", errcode);
  574.             curpipe->status |= STAT_ERROR;
  575.             goto load_proc_cleanup;
  576.         }
  577.  
  578.         // Wait for sometime if pipe is busy
  579.         if (!WaitNamedPipe(curpipe->pipename, PIPE_WAIT_TIME))
  580.         {
  581.             printf("Error in %s : %d\n", "WaitNamedPipe", GetLastError());
  582.             curpipe->status |= STAT_ERROR;
  583.             goto load_proc_cleanup;
  584.         }
  585.     }
  586.  
  587.     printf("load thread : %d : connected to server\n", curpipe->slot);
  588.                                 
  589.     // get the buffer size
  590.     if ((!GetNamedPipeInfo(hpipe, NULL, NULL, &bufsize, NULL)) || (bufsize == 0))
  591.     {
  592.         printf("Error in %s : %d\n", "GetNamedPipeInfo", GetLastError());
  593.         curpipe->status |= STAT_ERROR;
  594.         goto load_proc_cleanup;
  595.     }
  596.  
  597.     // Align the buffer size to database pagesize if necessary
  598.     if (bufsize % DBPAGESIZE)
  599.         bufsize = ((bufsize / DBPAGESIZE) - 1) * DBPAGESIZE;
  600.     //printf("load thread : %d : buffer size %d \n", curpipe->slot, bufsize);
  601.  
  602.     // allocate the buffer for reading incoming data and align it
  603.     if ((buf_start = malloc(bufsize + 64)) == NULL)
  604.     {
  605.         printf("malloc failed\n");
  606.         curpipe->status |= STAT_ERROR;
  607.         goto load_proc_cleanup;
  608.     }
  609.     buf_ptr = BUFALIGN(buf_start);
  610.  
  611.     // Set the pipe mode to message read mode 
  612.     mode = PIPE_READMODE_MESSAGE;
  613.     if (!SetNamedPipeHandleState(hpipe, &mode, NULL, NULL))
  614.     {
  615.         printf("Error in %s : %d\n", "SetNamedPipeHandleState", GetLastError());
  616.         curpipe->status |= STAT_ERROR;
  617.         goto load_proc_cleanup;
  618.     }
  619.  
  620.     // open the dump file ; it should exist
  621.     hfile = CreateFile(curpipe->dumpname,
  622.             GENERIC_READ | GENERIC_WRITE, 0, NULL,
  623.             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  624.     if (hfile == INVALID_HANDLE_VALUE)
  625.     {
  626.         printf("Error in %s : %d\n", "CreateFile", GetLastError());
  627.         curpipe->status |= STAT_ERROR;
  628.         goto load_proc_cleanup;
  629.     }
  630.  
  631.     // set the file pointer to start of file
  632.     offh = 0;
  633.     if ((offl = SetFilePointer(hfile, 0, &offh, FILE_BEGIN)) == -1)
  634.     {
  635.         printf("Error in %s : %d\n", "SetFilePointer", GetLastError());
  636.         curpipe->status |= STAT_ERROR;
  637.         goto load_proc_cleanup;
  638.     }
  639.  
  640.     //
  641.     // Read the first page and write it to the pipe
  642.     //
  643.     if ((!ReadFile(hfile, buf_ptr, DBPAGESIZE, &cbread, NULL)) || 
  644.             (cbread != DBPAGESIZE))
  645.     {
  646.         printf("Error in %s : %d\n", "ReadFile", GetLastError());
  647.         curpipe->status |= STAT_ERROR;
  648.         goto load_proc_cleanup;
  649.     }
  650.     if (!WriteFile(hpipe, buf_ptr, DBPAGESIZE, &cbwritten, NULL))
  651.     {
  652.         printf("Error in %s : %d\n", "WriteFile", errcode);
  653.         curpipe->status |= STAT_ERROR;
  654.         goto load_proc_cleanup;
  655.     }
  656.     //printf("load thread : %d : wrote %d bytes\n", curpipe->slot, cbwritten);
  657.  
  658.     // now we are all set to read from the dumpfile; keep reading till we reach
  659.     // the end of dumpfile
  660.     while (1)
  661.     {
  662.         // check the global flag
  663.         if (curinfo->status & STAT_ERROR)
  664.             goto load_proc_cleanup;
  665.  
  666.         // read from the dump file
  667.         if (!ReadFile(hfile, buf_ptr, bufsize, &cbread, NULL))
  668.         {
  669.             // check if we are done reading
  670.             if ((errcode = GetLastError()) == ERROR_HANDLE_EOF)
  671.                 break;
  672.  
  673.             printf("Error in %s : %d\n", "ReadFile", GetLastError());
  674.             curpipe->status |= STAT_ERROR;
  675.             goto load_proc_cleanup;
  676.         }
  677.  
  678.         // Done reading the dump file
  679.         if (cbread == 0)
  680.             break;
  681.  
  682.         // write to the pipe
  683.         if (!WriteFile(hpipe, buf_ptr, cbread, &cbwritten, NULL))
  684.         {
  685.             printf("Error in %s : %d\n", "WriteFile", GetLastError());
  686.             curpipe->status |= STAT_ERROR;
  687.             goto load_proc_cleanup;
  688.         }
  689.         //printf("load thread : %d : wrote %d bytes\n", curpipe->slot, cbwritten);
  690.     }
  691.  
  692. load_proc_cleanup:
  693.  
  694.     // release the resources
  695.     if (buf_start)
  696.         free(buf_start);
  697.     if (hfile)
  698.         CloseHandle(hfile);
  699.     if (hpipe)
  700.     {
  701.         FlushFileBuffers(hpipe);
  702.         CloseHandle(hpipe);
  703.     }
  704.  
  705.     // set the status flags
  706.     curpipe->status |= STAT_ENDTHREAD;
  707.     if (curpipe->status & STAT_ERROR)
  708.         curinfo->status |= STAT_ERROR;
  709.  
  710.     return;
  711. }
  712.  
  713.  
  714. INT msg_handler(dbproc,msgno,msgstate, severity, msgtext,server,proc,line)
  715. PDBPROCESS     dbproc;
  716. DBINT         msgno;
  717. INT     msgstate;
  718. INT     severity;
  719. LPCSTR        msgtext;
  720. LPCSTR    server;
  721. LPCSTR    proc;
  722. DBUSMALLINT line;
  723. {
  724.    if (severity)
  725.       printf("\nDB-LIB message: %s \n", msgtext);
  726.    return (0);
  727. };
  728.  
  729. INT err_handler(dbproc,    severity, herrno, oserr, dberrstr, oserrstr)
  730. PDBPROCESS     dbproc;
  731. INT        severity;        
  732. INT         herrno;
  733. INT         oserr;            
  734. LPCSTR     dberrstr;
  735. LPCSTR     oserrstr;
  736. {
  737.     if (severity)
  738.       printf("\nDB-LIBRARY error: %s \n", dberrstr);
  739.     return (INT_CANCEL);
  740. };
  741.