home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / blt2rx_o.zip / c_src.zip / bd_files.c next >
C/C++ Source or Header  |  1996-10-12  |  16KB  |  499 lines

  1.  
  2. /* bd_files.c -  2-Oct-1996 Cornel Huth
  3.  * This module is called by bd_main.c
  4.  * lots of files open at one time
  5.  *
  6.  * If DOSX32: this requires compiler support in
  7.  * ccdosfn.c, BulletSetHandleCount(), if more than
  8.  * a total of 15 handles are to be used
  9.  *
  10.  */
  11.  
  12. #include "platform.h"
  13.  
  14. // external to this module
  15.  
  16. void PutMsg(CHAR *strg);
  17. void GetMsg(CHAR *strg);
  18.  
  19. extern CHAR *collateTable;
  20.  
  21.  
  22. // public in this module
  23.  
  24. int bd_files(void);
  25.  
  26.  
  27. // GO
  28.  
  29. int bd_files(void) {
  30.  
  31. /* 
  32.  * Extend Bullet 2 file resources to the max by opening as many files as 
  33.  * possible (limited by version level so far as max files/max instances)
  34.  * Filenames generated are based on PID, and so multiple processes can
  35.  * be used without filename conflict.  It's recommended that this test be
  36.  * run in a new directory, for no reason other than that you can easily 
  37.  * delete the files created, all of which are of the form: $pidnnnn.DBF
  38.  * where pid is the process ID number, and nnnn is the sequence number
  39.  * of the file generated (0001, 0002, onward). (See below at "For Win95...").
  40.  *
  41.  * This module can create up to 1024 files in the directory so do not
  42.  * use the root directory since this has a finite number of entries,
  43.  * (less than 512, even less if VFAT).
  44.  *
  45.  * For non-multi-process versions (Bullet/X, Win32s), no provision is made for
  46.  * more than one active process (other starts get a 'access denied' or
  47.  * 'file exists' message).
  48.  *
  49.  * No actual add operations are performed in this test (see a later example),
  50.  * but the create/open/close/delete operations are timed.  
  51.  *
  52.  * The mix of file types is one index file for each data file.  So, if the
  53.  * max files is 100, 50 DBFs and 50 index files are generated; if 250 files
  54.  * then 125/125; for 1024 files, 512 DBFs and 512 index files, though the
  55.  * actual number is determined by the number entered from the keyboard
  56.  * (i.e., the user) and also the DLL capability level -- the shareware 
  57.  * DLL has 100 files max, per process, with up to two processes active.
  58.  *
  59.  * ------------------------------------------------------------------------
  60.  * For Win95, VFAT file system, the limit is much higher than MS-DOS:  I've
  61.  * opened 1024 files without problem.  NTFS or HPFS has no preset limit.
  62.  * NOTE: Win95 returns the same PID for things run in an MS-DOS box.  This
  63.  * means that if you run this module simultaneously with another "files
  64.  * blowout" run, you should do so in separate directories since the filenames
  65.  * generated are based on the PID, and if the PIDs are the same, so are the
  66.  * filenames.
  67.  *
  68.  * The shareware Bullet95.DLL of the  version can open and use up to
  69.  * 100 files at the same time, with up to two concurrent processes (except
  70.  * for Win32s, where only 1 process is available).
  71.  *
  72.  * -----------------------------------------------------------------------
  73.  * 
  74.  * For DOSX32, the file limit is about 250, but is dependent on the FILES=
  75.  * statement in CONFIG.SYS.  This module limits it to 250 (125+125), but
  76.  * you may be able to do 251 if nothing else is open (hanles 0-2 are reserved
  77.  * and handle 255 is not a valid handle, leaving 251 max handles).
  78.  *
  79.  * All files are open simultaneously, i.e., no files are closed until all 
  80.  * have been opened, after which all are closed and deleted.  The creates, 
  81.  * opens, and closes are all timed, individually, as well as the sum of all.
  82.  *
  83.  * Note: Since the process cannot easily know which files belong to it
  84.  *       from any previous run, and since there may be multiple processes
  85.  *       generating these files, this program deletes the files created
  86.  *       at the end of the run, rather than at the beginning as most other
  87.  *       examples do.
  88.  */
  89.  
  90.  
  91.  // See platform.h for already-defined HANDLES_WANTED, as used in INIT_XB
  92.  // in the bd_main.c module.
  93.  
  94. #if PLATFORM == ON_DOSX32
  95.  #define MAX_DATA_FILES 127   // may have less than 255 available, such as 208,
  96.  #define MAX_INDEX_FILES 127  // or whatever is left by extender or DPMI provider or DOS
  97.  
  98. #elif PLATFORM == ON_OS2
  99.  #define MAX_DATA_FILES 512   // your DLL/LIB may not be capable of allowing
  100.  #define MAX_INDEX_FILES 512  // as many as this (see your manual)
  101.  
  102. #elif PLATFORM == ON_WIN32    // if using NTFS or HPFS, can use more
  103.  #define MAX_DATA_FILES 512   // but VFAT (Win95) is limited to 230 or so
  104.  #define MAX_INDEX_FILES 512  // but NTFS or HPFS under NT can do many more
  105.  
  106. #else
  107.  #error No PLATFORM set in platform.h
  108.  #error -----------------------------
  109. #endif
  110.  
  111.  void BuildFieldListFiles(FIELDDESCTYPE fieldList[]);
  112.  
  113. #pragma pack(1)
  114.  
  115.  DOSFILEPACK DFP;
  116.  CREATEDATAPACK CDP;
  117.  CREATEINDEXPACK CIP;
  118.  HANDLEPACK HP;
  119.  OPENPACK OP;
  120.  QUERYSETPACK QSP;
  121.  
  122. #pragma pack()
  123.  
  124.  int crdFiles=0;  // data files created (so to limit what is deleted)
  125.  int crxFiles=0;  // index files created
  126.  int wkdFiles=0;  // data files opened so far (so to limit what is closed)
  127.  int wkxFiles=0;  // index files opened so far
  128.  int err4=0;      // ran out of handles flag
  129.  
  130.  time_t startTime,endTime,endTime2,endTime3,endTime4,endTime5,endTime6,endTime7,endTime8;
  131.  
  132.  LONG rez;                    // return value from Bullet
  133.  LONG i;                      // misc counter
  134.  
  135.  LONG maxFiles;               // max files DLL allows per process
  136.  LONG userFiles;              // number tester wants (up to maxFiles)
  137.  LONG dataFiles;              // computed number of data files (1/3rd)
  138.  LONG indexFiles;             // computed number of index files (2/3rd)
  139.  
  140.  
  141.  // these are used as part of the process-unique filenames generated
  142.  
  143. #if PLATFORM == ON_OS2
  144.  PTIB pptib;                  // for DosGetInfoBlocks
  145.  PPIB pppib;                  // for DosGetInfoBlocks
  146.  CHAR sPID[4];                // this process ID, ASCII format (e.g.,"0015")
  147.  
  148. #elif PLATFORM == ON_WIN32
  149.  DWORD PID;                   // process ID (low word only)
  150.  CHAR sPID[4];                // this process ID, ASCII format (e.g.,"0015")
  151. #endif
  152.  
  153.  CHAR nameData[]=".\\$pid#nnn.dbf";   // data filenames built here
  154.  ULONG dataID[MAX_DATA_FILES]={0};   // handles of data files, max this test uses
  155.  FIELDDESCTYPE fieldList[5];         // 5 fields used in data record (all use same)
  156.  
  157.  CHAR nameIX3[]=".\\$pid#nnn.ix3";    // index filenames built here
  158.  ULONG indexID[MAX_INDEX_FILES]={0}; // handles of indexes, max this test uses
  159.  CHAR keyExpression[128];            // key expression string buffer (all use same)
  160.  
  161.  CHAR tmpStr[128];                   // misc stuff, non-Bullet related
  162.  CHAR putStr[128];
  163.  
  164.  
  165.  setbuf(stdout,NULL);
  166.  
  167.  memset(fieldList,0,sizeof(fieldList));  // init unused bytes to 0 (required)
  168.  BuildFieldListFiles(fieldList);
  169.  
  170. #if PLATFORM == ON_OS2
  171.   // get PID for unique filenames
  172.  
  173.  rez = DosGetInfoBlocks(&pptib,&pppib);
  174.  sprintf(sPID,"%4.4x",(pppib->pib_ulpid & 0xFFFF)); // pre-build filenames
  175.  strncpy(nameData+3,sPID,4);  // account for leading .\$ characters
  176.  strncpy(nameIX3+3,sPID,4);
  177.  
  178. #elif PLATFORM == ON_WIN32
  179.  // get PID for unique filenames
  180.  
  181.  PID = GetCurrentProcessId();
  182.  sprintf(sPID,"%4.4x",(PID & 0xFFFF)); // pre-build filenames (.\$0001nnn.ext)
  183.  strncpy(nameData+3,sPID,4);
  184.  strncpy(nameIX3+3,sPID,4);
  185. #endif
  186.  
  187.  // find out max files your DLL/LIB version has (100, 250, or 1024)
  188.  // you'll already know this, but for this general purpose example...
  189.  
  190.  QSP.func = QUERY_SYSVARS_XB;
  191.  QSP.item = 28;
  192.  rez = BULLET(&QSP);
  193.  if (rez) {
  194.     sprintf(putStr,"Failed QUERY_SYSVARS call.  Err: %d\n",rez);
  195.     PutMsg(putStr);
  196.     goto Abend;
  197.  }
  198.  maxFiles = QSP.itemValue;
  199.  
  200. #if PLATFORM == ON_DOSX32
  201.  if (maxFiles > 250) maxFiles = 250;   // limit to openable handles
  202.  PutMsg("For DOSX32: Max files that can be opened is dependent on FILES= in\n");
  203.  PutMsg("CONFIG.SYS and compiler support in ccdosfn.c:BulletSetHandleCount()\n");
  204.  PutMsg("and the operating system being used (real DOS, a DOS box, etc.)\n\n");
  205. #endif
  206.  
  207.  sprintf(putStr,"Max files to generate (half data+half index)? (max %d): ",maxFiles);
  208.  PutMsg(putStr);
  209.  GetMsg(tmpStr);
  210.  userFiles = atol(tmpStr);
  211.  if (userFiles > maxFiles) userFiles = maxFiles;
  212.  if (userFiles < 2)        userFiles = 2;
  213.  
  214.  dataFiles = userFiles >> 1; // half are data files
  215.  indexFiles = dataFiles;     // and the other half index files
  216.  
  217.  sprintf(putStr,"Using %d data and %d index files for a total of %d files\n\n",
  218.          dataFiles,
  219.          indexFiles,
  220.          (dataFiles+indexFiles));
  221.  PutMsg(putStr);
  222.  
  223.  time(&startTime);
  224.  
  225.  // Create the data file, a standard DBF (ID=3) as defined in fieldList above.
  226.  
  227.  CDP.func = CREATE_DATA_XB;      // these are all invariant
  228.  CDP.filenamePtr = nameData;     // all DBF files will be similar except in name
  229.  CDP.noFields = 5;
  230.  CDP.fieldListPtr = fieldList;
  231.  CDP.fileID = 0x03;
  232.  
  233.  for (i=1;i <= dataFiles;i++) {
  234.  
  235.     sprintf(tmpStr,"%3.3i",i);
  236.     strncpy(nameData+7,tmpStr,3);
  237.  
  238.     rez = BULLET(&CDP);
  239.     if (rez) {
  240.        sprintf(putStr,"Failed data file #%d create.  Err: %d\n",i,rez);
  241.        PutMsg(putStr);
  242.        goto Abend;
  243.     }
  244.     else {
  245.        sprintf(putStr,"Created: %d\r",i);
  246.        PutMsg(putStr);
  247.        crdFiles++;
  248.     }
  249.  }
  250.  
  251.  time(&endTime);
  252.  sprintf(putStr,"Created: %d data files - took %u secs.\n",i-1,(endTime - startTime));
  253.  PutMsg(putStr);
  254.  
  255.  // Open the data files
  256.  
  257.  OP.func = OPEN_DATA_XB;
  258.  OP.filenamePtr = nameData;
  259.  OP.asMode = READWRITE | DENYNONE;
  260.  
  261.  for (i=1;i <= dataFiles;i++) {
  262.  
  263.     sprintf(tmpStr,"%3.3i",i);
  264.     strncpy(nameData+7,tmpStr,3);
  265.  
  266.     rez = BULLET(&OP);
  267.     if (rez) {
  268.        sprintf(putStr,"Failed data file #%d open.    Err: %d\n",i,rez);
  269.        PutMsg(putStr);
  270.        if (rez==4) {
  271.           sprintf(putStr,"\nYou ran out of handles after %d handles.\n\n",wkdFiles);
  272.           PutMsg(putStr);
  273.           err4=1;
  274.        }
  275.        goto Abend;
  276.     }
  277.     else {
  278.        sprintf(putStr," Opened: %d\r",i);
  279.        PutMsg(putStr);
  280.        dataID[i-1]=OP.handle;
  281.        wkdFiles++;
  282.     }
  283.  }
  284.  time(&endTime2);
  285.  sprintf(putStr," Opened: %d data files - took %u secs.\n\n",i-1,(endTime2 - endTime));
  286.  PutMsg(putStr);
  287.  
  288.  // Create an index file for each data file.
  289.  // All index files are the same, except for name, for this example
  290.  
  291.  strcpy(keyExpression,"SSN");
  292.  
  293.  CIP.func = CREATE_INDEX_XB;
  294.  CIP.filenamePtr = nameIX3;
  295.  CIP.keyExpPtr = keyExpression;
  296.  CIP.sortFunction = NLS_SORT | SORT_SET;  // sort by NLS (SORT_SET defined in PLATFORM.H)
  297.  CIP.codePage = CODEPAGE;
  298.  CIP.countryCode = CTRYCODE;
  299.  CIP.collatePtr = collateTable;
  300.  CIP.nodeSize = 512;
  301.  
  302.  for (i=1;i <= indexFiles;i++) {
  303.  
  304.     sprintf(tmpStr,"%3.3i",i);
  305.     strncpy(nameIX3+7,tmpStr,3);
  306.  
  307.     CIP.xbLink = dataID[i-1];    // its cooresponding DBF handle
  308.     rez = BULLET(&CIP);
  309.     if (rez) {
  310.        sprintf(putStr,"Failed index file #%d create.  Err: %d\n",i,rez);
  311.        PutMsg(putStr);
  312.        goto Abend;
  313.     }
  314.     else {
  315.        sprintf(putStr,"Created: %d\r",i);
  316.        PutMsg(putStr);
  317.        crxFiles++;
  318.     }
  319.  }
  320.  
  321.  time(&endTime3);
  322.  sprintf(putStr,"Created: %d index files- took %u secs.\n",i-1,(endTime3 - endTime2));
  323.  PutMsg(putStr);
  324.  
  325.  // Open the index files
  326.  
  327.  OP.func = OPEN_INDEX_XB;
  328.  OP.filenamePtr = nameIX3;
  329.  OP.asMode = READWRITE | DENYNONE;
  330.  
  331.  for (i=1;i <= indexFiles;i++) {
  332.  
  333.     sprintf(tmpStr,"%3.3i",i);
  334.     strncpy(nameIX3+7,tmpStr,3);
  335.  
  336.     OP.xbLink = dataID[i-1];     // its cooresponding DBF handle
  337.     rez = BULLET(&OP);
  338.     if (rez) {
  339.        sprintf(putStr,"Failed index file #%d open.    Err: %d\n",i,rez);
  340.        PutMsg(putStr);
  341.        if (rez==4) {
  342.           sprintf(putStr,"\nYou ran out of handles after %d handles.\n\n",wkdFiles+wkxFiles);
  343.           PutMsg(putStr);
  344.           err4=1;
  345.        }
  346.        goto Abend;
  347.     }
  348.     else {
  349.        sprintf(putStr," Opened: %d\r",i);
  350.        PutMsg(putStr);
  351.        indexID[i-1]=OP.handle;
  352.        wkxFiles++;
  353.     }
  354.  }
  355.  time(&endTime4);
  356.  sprintf(putStr," Opened: %d index files- took %u secs.\n\n",i-1,(endTime4 - endTime3));
  357.  PutMsg(putStr);
  358.  
  359.  // Abnormal endings come here
  360. Abend:
  361.  
  362.  if (rez) time(&endTime4);
  363.  
  364.  // Close the index files than were opened
  365.  
  366.  HP.func = CLOSE_INDEX_XB;
  367.  for (i=1;i <= wkxFiles;i++) {
  368.     if (indexID[i-1]) {
  369.        HP.handle = indexID[i-1];
  370.        rez = BULLET(&HP);
  371.        if (rez) {
  372.           sprintf(putStr,"Failed index file #%d close.   Err: %d\n",i,rez);
  373.           PutMsg(putStr);
  374.        }
  375.        else {
  376.           sprintf(putStr," Closed: %d\r",i);
  377.           PutMsg(putStr);
  378.           indexID[i-1]=0;
  379.        }
  380.     }
  381.  }
  382.  time(&endTime5);
  383.  sprintf(putStr," Closed: %d index files- took %u secs.\n",i-1,(endTime5 - endTime4));
  384.  PutMsg(putStr);
  385.  
  386.  // Close the data files (only closes if handle != 0)
  387.  
  388.  HP.func = CLOSE_DATA_XB;
  389.  for (i=1;i <= wkdFiles;i++) {
  390.     if (dataID[i-1]) {
  391.        HP.handle = dataID[i-1];
  392.        rez = BULLET(&HP);
  393.        if (rez) {
  394.           sprintf(putStr,"Failed data file #%d close.   Err: %d\n",i,rez);
  395.           PutMsg(putStr);
  396.        }
  397.        else {
  398.           sprintf(putStr," Closed: %d\r",i);
  399.           PutMsg(putStr);
  400.           dataID[i-1]=0;
  401.        }
  402.     }
  403.  }
  404.  time(&endTime6);
  405.  sprintf(putStr," Closed: %d data files - took %u secs.\n\n",i-1,(endTime6 - endTime5));
  406.  PutMsg(putStr);
  407.  
  408.  // Delete the index files
  409.  
  410.  DFP.func = DELETE_FILE_DOS;
  411.  DFP.filenamePtr = nameIX3;
  412.  for (i=1;i <= crxFiles;i++) {
  413.  
  414.     sprintf(tmpStr,"%3.3i",i);
  415.     strncpy(nameIX3+7,tmpStr,3);
  416.  
  417.     rez = BULLET(&DFP);
  418.     if (rez) {
  419.        sprintf(putStr,"Failed index file #%d ('%s') delete.  Err: %d\n",i,DFP.filenamePtr,rez);
  420.        PutMsg(putStr);
  421.     }
  422.     else {
  423.        sprintf(putStr,"Deleted: %d index files\r",i);
  424.        PutMsg(putStr);
  425.     }
  426.  }
  427.  time(&endTime7);
  428.  sprintf(putStr,"Deleted: %d index files- took %u secs.\n",i-1,(endTime7 - endTime6));
  429.  PutMsg(putStr);
  430.  
  431.  // Delete the data files
  432.  
  433.  DFP.func = DELETE_FILE_DOS;
  434.  DFP.filenamePtr = nameData;
  435.  for (i=1;i <= crdFiles;i++) {
  436.  
  437.     sprintf(tmpStr,"%3.3i",i);
  438.     strncpy(nameData+7,tmpStr,3);
  439.  
  440.     rez = BULLET(&DFP);
  441.     if (rez) {
  442.        sprintf(putStr,"Failed data file #%d ('%s') delete.  Err: %d\n",i,DFP.filenamePtr,rez);
  443.        PutMsg(putStr);
  444.     }
  445.     else {
  446.        sprintf(putStr,"Deleted: %d data files\r",i);
  447.        PutMsg(putStr);
  448.     }
  449.  }
  450.  time(&endTime8);
  451.  sprintf(putStr,"Deleted: %d data files - took %u secs.\n\n",i-1,(endTime8 - endTime7));
  452.  PutMsg(putStr);
  453.  
  454.  sprintf(putStr,"Total time: %u seconds.\n",(endTime8 - startTime));
  455.  PutMsg(putStr);
  456.  
  457.  // put up this message again, since it probably scrolled off
  458.  
  459.  if (err4) {
  460.     sprintf(putStr,"\nRepeat:  You ran out of handles after %d handles.\n\n",wkdFiles+wkxFiles);
  461.     PutMsg(putStr);
  462.  }
  463.  
  464.  return rez;  // module exit
  465. }
  466.  
  467.  
  468. //------------------------------------
  469. // Init field list items for data file
  470.  
  471. void BuildFieldListFiles(FIELDDESCTYPE fieldList[]) {
  472.  
  473.  strcpy(fieldList[0].fieldName, "SSN");  // field names must be upper-case
  474.  fieldList[0].fieldType = 'C';           // field types must be upper-case
  475.  fieldList[0].fieldLen = 9;
  476.  fieldList[0].fieldDC = 0;
  477.  
  478.  strcpy(fieldList[1].fieldName, "LNAME");
  479.  fieldList[1].fieldType = 'C';
  480.  fieldList[1].fieldLen = 16;
  481.  fieldList[1].fieldDC = 0;
  482.  
  483.  strcpy(fieldList[2].fieldName, "FNAME");
  484.  fieldList[2].fieldType = 'C';
  485.  fieldList[2].fieldLen = 16;
  486.  fieldList[2].fieldDC = 0;
  487.  
  488.  strcpy(fieldList[3].fieldName, "HIRED");
  489.  fieldList[3].fieldType = 'D';
  490.  fieldList[3].fieldLen = 8;      // date field type must be 8.0
  491.  fieldList[3].fieldDC = 0;
  492.  
  493.  strcpy(fieldList[4].fieldName, "DEPT");
  494.  fieldList[4].fieldType = 'C';
  495.  fieldList[4].fieldLen = 6;
  496.  fieldList[4].fieldDC = 0;
  497.  return;
  498. }
  499.