📄 db_cls.cpp
字号:
/*============================================================================
Copyright (c) 1996
Hewlett-Packard Company
ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
Permission to use, copy, modify, distribute and/or sell this software
and/or its documentation is hereby granted without fee. User agrees
to display the above copyright notice and this license notice in all
copies of the software and any documentation of the software. User
agrees to assume all liability for the use of the software; Hewlett-Packard
makes no representations about the suitability of this software for any
purpose. It is provided "AS-IS without warranty of any kind,either express
or implied. User hereby grants a royalty-free license to any and all
derivatives based upon this software code base.
=============================================================================*/
//============================================================================
// D B _ C L S . C P P
//
// Generic Database Class implementation file
//
//
// Changes:
//
//============================================================================
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <io.h>
#include <sys/locking.h>
#include <time.h>
#include <share.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "db_cls.h"
#define BUFFSIZE 4096
// return current time in seconds
int Db::check_current_time()
{
time_t long_time; // time as a long integer
struct tm *current_time;
time(&long_time); // get time
current_time = localtime(&long_time); // convert to local time
return ( current_time->tm_min * 60 + current_time->tm_sec);
}
int Db::frag_check()
{
int infile;
ldiv_t ldivstruct;
long int filesize, structsize;
if((infile = open(db_name, O_RDONLY|O_BINARY)) == -1)
{
return DB_FILE_NOT_FOUND;
}
filesize = filelength(infile);
structsize = rec_size;
ldivstruct = ldiv((long int) filesize, (long int) structsize);
if (ldivstruct.rem != 0)
{
close(infile);
return DB_FRAG_ERROR;
}
else
close(infile);
return DB_OK;
}
// Db class semaphore wait
FILE* Db::wait ( const char *mode, int shflag)
{
FILE * tmp_file;
int end_time;
if (frag_check() == DB_OK)
{
if ((tmp_file = _fsopen(db_name, mode, shflag)) == NULL)
{
end_time = check_current_time() + DB_TIMEOUT;
do {
if ( check_current_time() <= end_time) // check timeout
cerr << "."; // waiting sign
else
return tmp_file;
} while ((tmp_file = _fsopen(db_name, mode, shflag)) == NULL);
cerr << endl;
}
}
return tmp_file;
};
int Db::set_attributtes( const char *name, const long record_size)
{
int infile;
long int filesize,structsize;
ldiv_t ldivstruct;
strcpy(db_name,name); // set the name
rec_size = record_size;
// frag check
infile = open(db_name, O_RDONLY|O_BINARY);
if (infile==-1)
{
current_number_of_records = 0;
return DB_FILE_NOT_FOUND; // file does not exist
}
// get num recs and check for frag
filesize = filelength(infile);
structsize = rec_size;
ldivstruct = ldiv((long int) filesize,(long int) structsize);
if (ldivstruct.rem !=0)
{
close(infile);
current_number_of_records = 0;
return DB_FRAG_ERROR; // file fragmented error
}
current_number_of_records = (long int) ldivstruct.quot;
close(infile);
return DB_OK;
};
// perform a binary search
int Db::binary_search(FILE * binary_search_file, // binary search file stream
void *data, // record matched
long int *location) // spot where found
{
long int look;
int result;
char *read_rec,*db_rec;
Key key,mkey;
int found = FALSE;
long int min,max;
read_rec = new char[(int)rec_size];
db_rec = new char[(int)rec_size];
memcpy(db_rec,data,(int)rec_size);
min = 1;
max = current_number_of_records;
// search_file = fopen(db_name,"rb");
if ( binary_search_file == NULL)
return DB_OPEN_ERROR; // open error
while ((max >=min)&&(!found))
{
look = min + (long int)((max-min) / 2 + 0.5);
fseek(binary_search_file,((look-1) * rec_size), SEEK_SET);
fread(read_rec,(int)rec_size,1,binary_search_file);
memcpy(key,read_rec,sizeof(Key));
memcpy(mkey,db_rec,sizeof(Key));
result = strcmp(mkey,key);
if (result ==0) // found !!!
{
memcpy(db_rec,read_rec,(int)rec_size);
memcpy(data,db_rec,(int)rec_size);
*location = look;
found = TRUE;
}
else if (result < 0)
max = look-1; // look in bottom half
else
min = look+1; // look in top half
}
delete read_rec;
delete db_rec;
if ( found)
return DB_OK;
else
{
*location = look;
return DB_REC_NOT_FOUND;
}
}
// write a record to a database
int Db::write(const void *data)
{
FILE *outfile,*tmp_file;
int result;
long int spot;
unsigned char *write_rec, *db_rec;
Key wkey,ckey;
size_t status;
write_rec = new unsigned char[(int)rec_size];
db_rec = new unsigned char[(int)rec_size];
memcpy(db_rec,data,(size_t)rec_size);
if ( access(db_name,0) != 0)
{ // file does not exist, create it and write
outfile = fopen(db_name,"wb+");
status = fwrite(db_rec,(size_t)rec_size,1,outfile);
current_number_of_records++;
fclose(outfile);
}
else
{
if ((outfile = wait("rb+", SH_DENYWR)) == NULL)
return FILE_LOCKED;
result = binary_search( outfile,db_rec, &spot); // binary search
if ( result == 0)
{ // found a match
fseek( outfile, (spot-1) * rec_size,SEEK_SET);
status = fwrite( data,(size_t)rec_size,1,outfile);
fclose( outfile);
}
else
{
if ( spot > current_number_of_records-1) spot--;
fseek(outfile, (spot * rec_size) ,SEEK_SET);
memcpy(write_rec,db_rec,(int)rec_size); // save to write_rec
fread(db_rec,(int)rec_size,1,outfile); // read in spot
memcpy(wkey,write_rec, sizeof(Key));
memcpy(ckey,db_rec, sizeof(Key));
result = strcmp(wkey,ckey);
while (( result < 0)&& ( spot >=0))
{
fseek(outfile,spot * rec_size,SEEK_SET);
fread(db_rec,(int)rec_size,1,outfile); // read in spot
memcpy(ckey,db_rec, sizeof(Key));
result = strcmp(wkey,ckey);
if (result < 0) spot--;
}
tmp_file = fopen("TEMP.$$$","wb"); // open TEMP file
// write to end of file
if (( result > 0) && ((spot+1) == current_number_of_records))
{
fseek(outfile,0,SEEK_SET);
append_recs(outfile,
tmp_file,
0,
spot,
rec_size);
fwrite(write_rec,(int)rec_size,1,tmp_file);
}
else
// add to front of database file
if ((result < 0)&&((spot-1) <= 0))
{
fseek(outfile,0,SEEK_SET);
fwrite(write_rec,(int)rec_size,1,tmp_file);
append_recs(outfile,
tmp_file,
0,
current_number_of_records-1,
rec_size);
}
else // insert in the middle
{
fseek(outfile,0,SEEK_SET);
append_recs(outfile,
tmp_file,
0,
spot,
rec_size);
fwrite(write_rec,(int)rec_size,1,tmp_file);
append_recs( outfile,
tmp_file,
spot+1,
current_number_of_records-1,
rec_size);
}
current_number_of_records++;
fclose(tmp_file);
fclose(outfile);
remove(db_name);
rename("TEMP.$$$",db_name);
}
}
delete [] write_rec;
delete [] db_rec;
return DB_OK;
}
// append records to a file
int Db::append_recs( FILE *from, // copy from this file
FILE *to, // to this file
long int start, // from this record #
long int stop, // to this record #
long int recsize) // size of record
{
char *buffer;
long int num_bytes;
long int write_size;
if ( start > stop)
return DB_OK;
buffer = new char[BUFFSIZE];
fseek(from,0,SEEK_SET);
fseek(from,(long int)(start*recsize),SEEK_SET);
num_bytes = (stop - start + 1) * recsize;while ( num_bytes > 0)
{
if ( num_bytes > BUFFSIZE)
{
num_bytes -= BUFFSIZE;
write_size = BUFFSIZE;
}
else
{
write_size = num_bytes;
num_bytes = 0;
}
fread(buffer,(int)write_size,1,from);
fwrite(buffer,(int)write_size,1,to);
}
delete buffer;
return DB_OK;
};
// get a record from the DB @ spot
int Db::retrieve( const long location, void *data)
{
FILE *readfile;
if ( *db_name ==0)
return DB_NO_NAME;
if ((readfile = wait("rb", SH_DENYWR)) == NULL)
return FILE_LOCKED;
fseek(readfile,(location * rec_size),SEEK_SET);
fread(data,(int)rec_size,1,readfile);
fclose(readfile);
return DB_OK;
};
// read a record from the database
int Db::read ( void *data)
{
long int spot;
int result;
FILE * readfile;
if ( *db_name == 0)
return DB_NO_NAME;
// do the binary search
if ((readfile = wait("rb", SH_DENYWR)) == NULL)
return FILE_LOCKED;
result = binary_search(readfile, data, &spot); // binary search
fclose (readfile);
return ( result);
}
// delete a record from the database
int Db::del( const Key key)
{
FILE *search_file;
FILE *tmp_file;
int found;
unsigned char *data;
long int spot;
if ( *db_name == 0)
return DB_NO_NAME;
if ((search_file = wait("rb+", SH_DENYRW)) == NULL)
return FILE_LOCKED;
data = new unsigned char[(int)rec_size];
memcpy(data,key,sizeof(Key));
found = binary_search(search_file, data, &spot);
if ( found == 0) // found a match
{
// remove the record
tmp_file = fopen("TEMP.$$$","wb");
fseek(search_file,0,SEEK_SET);
// copy everything up to the s1>s2
append_recs( search_file,
tmp_file,
0,
spot-2,
rec_size);
append_recs( search_file,
tmp_file,
spot,
current_number_of_records-1,
rec_size);
fclose(tmp_file);
fclose(search_file);
remove(db_name);
rename("TEMP.$$$",db_name);
current_number_of_records--;
}
else // not found
fclose(search_file);
if ( current_number_of_records ==0)
remove(db_name);
delete data;
return (found);
}
// delete the database
int Db::delete_db()
{
FILE * outfile;
if ((outfile = wait("wb", SH_DENYRW)) == NULL) // deny sharing read & write
return FILE_LOCKED;
if (*db_name != 0)
remove(db_name);
else
return DB_NO_NAME;
// delete database file
strcpy(db_name,"");
current_number_of_records = 0;
fclose(outfile);
return DB_OK;
}
// compare pattern to some string
int Db::wild_card_compare( const char *pattern,
const char *str)
{
char temp[80];
char *tmp;
strcpy(temp,str);
tmp = temp;
*(tmp+strlen(pattern)) = 0;
if ( strcmp(pattern,tmp) == 0)
return WC_MATCH;
else
return WC_NO_MATCH;
};
// generate a list of keys based on some pattern
int Db::pattern(const char *pattern, Key **keys, int *keycount)
{
long int z;
FILE *readfile;
char *data;
*keys = (Key *) new char[(int)(current_number_of_records * sizeof(Key))];
*keycount = 0;
if ( *keys == 0)
return DB_KEY_NEW;
if ( *db_name == 0)
return DB_NO_NAME; // no name
if ((readfile = wait("rb", SH_DENYWR)) == NULL) // deny share writing
return FILE_LOCKED;
fseek(readfile,0,SEEK_SET);
data = new char[sizeof(Key)];
for (z=0; z<=(current_number_of_records-1); z++)
{
fseek(readfile,(z*rec_size),SEEK_SET);
fread(data,sizeof(Key),1,readfile);
if ( wild_card_compare(pattern,data) == WC_MATCH)
{
strcpy((*keys)[*keycount],data);
(*keycount)++;
}
}
fclose(readfile);
delete data;
return DB_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -