db_cls.cpp
上传用户:czjinwang
上传日期:2007-01-12
资源大小:2484k
文件大小:14k
源码类别:

SNMP编程

开发平台:

Visual C++

  1. /*============================================================================
  2.   Copyright (c) 1996
  3.   Hewlett-Packard Company
  4.   ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  5.   Permission to use, copy, modify, distribute and/or sell this software 
  6.   and/or its documentation is hereby granted without fee. User agrees 
  7.   to display the above copyright notice and this license notice in all 
  8.   copies of the software and any documentation of the software. User 
  9.   agrees to assume all liability for the use of the software; Hewlett-Packard 
  10.   makes no representations about the suitability of this software for any 
  11.   purpose. It is provided "AS-IS without warranty of any kind,either express 
  12.   or implied. User hereby grants a royalty-free license to any and all 
  13.   derivatives based upon this software code base. 
  14.  
  15. =============================================================================*/
  16. //============================================================================
  17. //  D B _ C L S . C P P
  18. //
  19. //  Generic Database Class implementation file
  20. //
  21. //
  22. //  Changes:
  23. //
  24. //============================================================================
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <iostream.h>
  28. #include <io.h>
  29. #include <sys/locking.h>
  30. #include <time.h>
  31. #include <share.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <fcntl.h>
  35. #include "db_cls.h"                 
  36. #define BUFFSIZE 4096
  37. // return current time in seconds
  38. int Db::check_current_time()
  39. {
  40.    time_t long_time;    // time as a long integer
  41.    struct tm *current_time;
  42.    time(&long_time);                      // get time
  43.    current_time = localtime(&long_time);  // convert to local time
  44.    return ( current_time->tm_min * 60 + current_time->tm_sec);    
  45. }     
  46. int Db::frag_check()
  47. {
  48.    int infile;
  49.    ldiv_t ldivstruct;
  50.    long int filesize, structsize;
  51.    if((infile = open(db_name, O_RDONLY|O_BINARY)) == -1)
  52.    {       
  53.             return DB_FILE_NOT_FOUND;
  54.     }
  55.    
  56.    filesize = filelength(infile);
  57.    structsize = rec_size;
  58.    ldivstruct = ldiv((long int) filesize, (long int) structsize);
  59.    if (ldivstruct.rem != 0)
  60.    {
  61.        close(infile);
  62.        return DB_FRAG_ERROR;
  63.        
  64.     }
  65.    else
  66.        close(infile);
  67.    return DB_OK;
  68. }
  69. // Db class semaphore wait
  70. FILE* Db::wait ( const char *mode, int shflag)
  71. {
  72.    FILE * tmp_file;
  73.    int end_time;
  74.    
  75. if (frag_check() == DB_OK)
  76. {
  77.    if ((tmp_file = _fsopen(db_name, mode, shflag)) == NULL)
  78.    {
  79.      end_time = check_current_time() + DB_TIMEOUT;
  80.      do {
  81.           if ( check_current_time() <= end_time)          // check timeout
  82.             cerr << ".";       // waiting sign
  83.           else 
  84.                   return tmp_file;
  85.      } while ((tmp_file = _fsopen(db_name, mode, shflag)) == NULL);
  86.      cerr << endl;
  87.    }
  88.  }
  89.  
  90.    return  tmp_file;
  91. };
  92. int Db::set_attributtes( const char *name, const long record_size)
  93. {
  94.    int infile;
  95.    long int filesize,structsize;
  96.    ldiv_t ldivstruct;
  97.    strcpy(db_name,name);    // set the name
  98.    rec_size = record_size;
  99.    // frag check
  100.    infile = open(db_name, O_RDONLY|O_BINARY);
  101.    
  102.    if (infile==-1)
  103.    {
  104.       current_number_of_records = 0;
  105.       return DB_FILE_NOT_FOUND;    // file does not exist
  106.    }
  107.    
  108.    // get num recs and check for frag
  109.    filesize = filelength(infile);
  110.    structsize = rec_size;
  111.    ldivstruct = ldiv((long int) filesize,(long int) structsize);
  112.    if (ldivstruct.rem !=0)
  113.    {
  114.       close(infile);
  115.       current_number_of_records = 0;
  116.       return DB_FRAG_ERROR;      // file fragmented error
  117.    }
  118.    current_number_of_records = (long int) ldivstruct.quot;
  119.    close(infile);
  120.    return DB_OK;
  121. };
  122. // perform a binary search
  123. int Db::binary_search(FILE * binary_search_file,     // binary search file stream
  124.                       void *data,                    // record  matched
  125.                       long int *location)            // spot where found
  126. {
  127.    long int look;
  128.    int result;
  129.    char *read_rec,*db_rec;
  130.    Key key,mkey;
  131.    int found = FALSE;
  132.    long int   min,max;
  133.    read_rec = new char[(int)rec_size];
  134.    db_rec = new char[(int)rec_size];
  135.    memcpy(db_rec,data,(int)rec_size);
  136.    min = 1;
  137.    max = current_number_of_records;
  138.    // search_file = fopen(db_name,"rb");
  139.    if ( binary_search_file == NULL)
  140.         return DB_OPEN_ERROR;    // open error
  141.    
  142.    while ((max >=min)&&(!found))
  143.    {
  144.       look = min + (long int)((max-min) / 2 + 0.5);
  145.       fseek(binary_search_file,((look-1) * rec_size), SEEK_SET);
  146.       fread(read_rec,(int)rec_size,1,binary_search_file);
  147.       memcpy(key,read_rec,sizeof(Key));
  148.       memcpy(mkey,db_rec,sizeof(Key));
  149.       result = strcmp(mkey,key);
  150.       if (result ==0) // found !!!
  151.       {
  152.          memcpy(db_rec,read_rec,(int)rec_size);
  153.          memcpy(data,db_rec,(int)rec_size);
  154.          *location = look;
  155.          found = TRUE;
  156.       }
  157.       else if (result < 0)
  158.               max = look-1;    // look in bottom half
  159.            else
  160.               min = look+1;    // look in top half
  161.    }
  162.   
  163.    delete read_rec;
  164.    delete db_rec;
  165.    if ( found)
  166.       return DB_OK;
  167.    else
  168.    {                                                                                 
  169.      *location = look;
  170.      return DB_REC_NOT_FOUND;
  171.    }
  172. }
  173. // write a record to a database
  174. int Db::write(const void *data)
  175. {
  176.    FILE *outfile,*tmp_file;
  177.    int result;
  178.    long int spot;
  179.    unsigned char *write_rec, *db_rec;
  180.    Key wkey,ckey;
  181.    size_t status;
  182.    
  183.    write_rec = new unsigned char[(int)rec_size];
  184.    db_rec = new unsigned char[(int)rec_size];
  185.    
  186.    memcpy(db_rec,data,(size_t)rec_size);
  187.    if ( access(db_name,0) != 0)
  188.    {  // file does not exist, create it and write
  189.       outfile = fopen(db_name,"wb+");
  190.       status = fwrite(db_rec,(size_t)rec_size,1,outfile);
  191.       current_number_of_records++;
  192.       fclose(outfile);
  193.    }
  194.    else
  195.    {     
  196.        if ((outfile = wait("rb+", SH_DENYWR)) == NULL)
  197.          return FILE_LOCKED;
  198.           
  199.        result = binary_search( outfile,db_rec, &spot);    // binary search
  200.        if ( result == 0)
  201.        {   // found a match
  202.            fseek( outfile, (spot-1) * rec_size,SEEK_SET);
  203.            status = fwrite( data,(size_t)rec_size,1,outfile);
  204.            fclose( outfile);
  205.        }
  206.        else
  207.        {
  208.           if ( spot > current_number_of_records-1) spot--;
  209.           fseek(outfile, (spot * rec_size) ,SEEK_SET);
  210.           
  211.           memcpy(write_rec,db_rec,(int)rec_size);     // save to write_rec 
  212.           fread(db_rec,(int)rec_size,1,outfile);    // read in spot
  213.           memcpy(wkey,write_rec, sizeof(Key));
  214.           memcpy(ckey,db_rec, sizeof(Key));
  215.           result = strcmp(wkey,ckey);
  216.           while (( result < 0)&& ( spot >=0))
  217.           {
  218.              fseek(outfile,spot * rec_size,SEEK_SET);
  219.              fread(db_rec,(int)rec_size,1,outfile);    // read in spot
  220.              memcpy(ckey,db_rec, sizeof(Key));
  221.              result = strcmp(wkey,ckey);
  222.              if (result < 0) spot--;
  223.           }
  224.           
  225.           tmp_file = fopen("TEMP.$$$","wb");            // open TEMP file
  226.           // write to end of file
  227.           if (( result > 0) && ((spot+1) == current_number_of_records))
  228.           {
  229.              fseek(outfile,0,SEEK_SET);
  230.              append_recs(outfile,
  231.                          tmp_file,
  232.                          0,
  233.                          spot,
  234.                          rec_size);
  235.              fwrite(write_rec,(int)rec_size,1,tmp_file);
  236.            }
  237.           else
  238.           // add to front of database file
  239.           if ((result < 0)&&((spot-1) <= 0))
  240.           {
  241.              fseek(outfile,0,SEEK_SET);
  242.              fwrite(write_rec,(int)rec_size,1,tmp_file);
  243.              append_recs(outfile,
  244.                          tmp_file,
  245.                          0,
  246.                          current_number_of_records-1,
  247.                          rec_size);
  248.           }
  249.           else    // insert in the middle
  250.           {
  251.              fseek(outfile,0,SEEK_SET);                                 
  252.              append_recs(outfile,
  253.                          tmp_file,
  254.                          0,
  255.                          spot,
  256.                          rec_size);
  257.              fwrite(write_rec,(int)rec_size,1,tmp_file);
  258.              append_recs( outfile,
  259.                           tmp_file,
  260.                           spot+1,
  261.                           current_number_of_records-1,
  262.                           rec_size);
  263.              }
  264.           current_number_of_records++;
  265.           fclose(tmp_file);
  266.           fclose(outfile);
  267.           remove(db_name);
  268.           rename("TEMP.$$$",db_name);
  269.         }
  270.   }                               
  271.  
  272.   delete [] write_rec;
  273.   delete [] db_rec;
  274.   return DB_OK;
  275. }
  276. // append records to a file
  277. int Db::append_recs(  FILE *from,       // copy from this file
  278.                       FILE *to,         // to this file
  279.                       long int start,   // from this record #
  280.                       long int stop,    // to this record #
  281.                       long int recsize) // size of record
  282. {
  283.    char *buffer;
  284.    long int num_bytes;
  285.    long int write_size;
  286.    
  287.    if ( start > stop) 
  288.         return DB_OK;
  289.    buffer = new char[BUFFSIZE];
  290.    fseek(from,0,SEEK_SET);
  291.    fseek(from,(long int)(start*recsize),SEEK_SET);
  292.    num_bytes = (stop - start + 1) * recsize;while ( num_bytes > 0)
  293.    {
  294.       if ( num_bytes > BUFFSIZE)
  295.       {
  296.           num_bytes -= BUFFSIZE;
  297.           write_size = BUFFSIZE;
  298.       }
  299.       else
  300.       {
  301.          write_size = num_bytes;
  302.          num_bytes = 0;
  303.       }
  304.       fread(buffer,(int)write_size,1,from);
  305.       fwrite(buffer,(int)write_size,1,to);
  306.    }
  307.    delete buffer;
  308.    return DB_OK;
  309. };
  310. // get a record from the DB @ spot
  311. int Db::retrieve(  const long location,  void *data)
  312. {
  313.    FILE *readfile;
  314.    
  315.    if ( *db_name ==0)
  316.       return DB_NO_NAME;
  317.    
  318.    if ((readfile = wait("rb", SH_DENYWR)) == NULL)
  319.         return FILE_LOCKED;
  320.       
  321.    fseek(readfile,(location * rec_size),SEEK_SET);
  322.    fread(data,(int)rec_size,1,readfile);
  323.    fclose(readfile);
  324.    return DB_OK; 
  325. };
  326. // read a record from the database
  327. int Db::read ( void *data)
  328. {
  329.    long int spot;
  330.    int result;
  331.    FILE * readfile;
  332.    if ( *db_name == 0)
  333.       return DB_NO_NAME;
  334.    // do the binary search
  335.    if ((readfile = wait("rb", SH_DENYWR)) == NULL)
  336.        return FILE_LOCKED;
  337.       
  338.    result = binary_search(readfile, data, &spot);    // binary search 
  339.    fclose (readfile);
  340.    return ( result); 
  341. }
  342. // delete a record from the database
  343. int Db::del( const Key key)
  344. {
  345.    FILE *search_file;
  346.    FILE *tmp_file;
  347.    int found;
  348.    unsigned char *data;    
  349.    long int spot;
  350.    if ( *db_name == 0)
  351.       return DB_NO_NAME;
  352.    if ((search_file = wait("rb+", SH_DENYRW)) == NULL)
  353.       return FILE_LOCKED;
  354.       
  355.    data = new unsigned char[(int)rec_size];
  356.    memcpy(data,key,sizeof(Key));
  357.    found = binary_search(search_file, data, &spot);
  358.    if ( found == 0)        // found a match
  359.    {
  360.       // remove the record
  361.       tmp_file = fopen("TEMP.$$$","wb");
  362.               
  363.       fseek(search_file,0,SEEK_SET);
  364.       // copy everything up to the s1>s2
  365.       append_recs( search_file,
  366.                    tmp_file,
  367.                    0,
  368.                    spot-2,
  369.                    rec_size);
  370.       append_recs( search_file,
  371.                    tmp_file,
  372.                    spot,
  373.                    current_number_of_records-1,
  374.                    rec_size);
  375.       fclose(tmp_file);
  376.       fclose(search_file);
  377.       remove(db_name);
  378.       rename("TEMP.$$$",db_name);
  379.       current_number_of_records--;
  380.    }
  381.    else              // not found
  382.       fclose(search_file);
  383.    
  384.    if ( current_number_of_records ==0)
  385.       remove(db_name);
  386.    delete data;
  387.    
  388.    return (found);
  389. }
  390. // delete the database
  391. int Db::delete_db()
  392. {
  393.    FILE * outfile;
  394.    if ((outfile = wait("wb",  SH_DENYRW)) == NULL)   // deny sharing read & write
  395.      return FILE_LOCKED;
  396.    
  397.    if (*db_name != 0)
  398.       remove(db_name);
  399.    else
  400.       return DB_NO_NAME;
  401.      // delete database file                
  402.    strcpy(db_name,"");
  403.    current_number_of_records = 0;
  404.    fclose(outfile);
  405.       
  406.    return DB_OK;
  407.  }
  408. // compare pattern to some string
  409. int Db::wild_card_compare( const char *pattern,
  410.                            const char *str)
  411. {
  412.     char temp[80];
  413.     char *tmp;
  414.     strcpy(temp,str);
  415.     tmp = temp;
  416.     *(tmp+strlen(pattern)) = 0;
  417.     if ( strcmp(pattern,tmp) == 0)
  418.        return WC_MATCH;
  419.     else
  420.       return WC_NO_MATCH;
  421. };
  422. // generate a list of keys based on some pattern
  423. int Db::pattern(const char *pattern, Key **keys, int *keycount)
  424. {
  425.    long int z;
  426.    FILE *readfile;
  427.    char *data;
  428.    *keys = (Key *) new char[(int)(current_number_of_records * sizeof(Key))];
  429.    *keycount = 0;
  430.    if ( *keys == 0)
  431.       return DB_KEY_NEW;
  432.    
  433.    if ( *db_name == 0)
  434.       return DB_NO_NAME;           // no name
  435.    if ((readfile = wait("rb", SH_DENYWR)) == NULL)   // deny share writing
  436.          return FILE_LOCKED;
  437.    fseek(readfile,0,SEEK_SET);
  438.    data = new char[sizeof(Key)];
  439.    for (z=0; z<=(current_number_of_records-1); z++)
  440.    {
  441.       fseek(readfile,(z*rec_size),SEEK_SET);
  442.       fread(data,sizeof(Key),1,readfile);
  443.       if ( wild_card_compare(pattern,data) == WC_MATCH)
  444.       {
  445.          strcpy((*keys)[*keycount],data);
  446.          (*keycount)++;
  447.       }
  448.    }
  449.    
  450.    fclose(readfile);
  451.    delete data;
  452.    
  453.    return DB_OK;
  454. }