?? flatfileold.c,v
字號:
head 1.3;
access;
symbols;
locks; strict;
comment @ * @;
1.3
date 2000.06.25.02.09.10; author cbbrowne; state Exp;
branches;
next 1.2;
1.2
date 2000.06.19.06.17.58; author cbbrowne; state Exp;
branches;
next 1.1;
1.1
date 2000.06.09.03.41.53; author cbbrowne; state Exp;
branches;
next ;
desc
@@
1.3
log
@*** empty log message ***
@
text
@static int open_db_table(char *name, FILE **file_ptr,
int *count_ptr, int record_size)
{
long file_length;
int file_records;
FILE *file;
/* We want to open for reading and writing, but
create if necessary. Here we open for append
to create if needed, then reopen as we need */
file = fopen(name,"a+");
if(!file)
return DVD_ERR_NO_FILE;
file_length = ftell(file);
file = freopen(name, "r+", file);
file_records = file_length/record_size;
if(file_records * record_size != file_length)
return DVD_ERR_BAD_TABLE;
if(file_records == 0) {
/* We just created the file. As we use id zero as a
sentinel we need to reserve the first entry in the
file, so add a dummy record here */
file_records = 1;
}
*file_ptr = file;
*count_ptr = file_records;
return DVD_SUCCESS;
}
int dvd_open_db()
{
/* Only open the database table once */
if(dvd_db_ok)
return DVD_SUCCESS;
/* if(open_db_table(MEMBER_FILE, &member_file,
&member_count, sizeof(dvd_store_member)))
return DVD_ERR_BAD_MEMBER_TABLE; */
if(open_db_table(TITLE_FILE, &title_file,
&title_count, sizeof(dvd_title)))
return DVD_ERR_BAD_TITLE_TABLE;
if(open_db_table(DISK_FILE, &disk_file,
&disk_count, sizeof(dvd_disk)))
return DVD_ERR_BAD_DISK_TABLE;
if(open_db_table(RENTAL_FILE, &rental_file,
&rental_count, sizeof(dvd_rental)))
return DVD_ERR_BAD_RENTAL_TABLE;
if(open_db_table(RESERVE_FILE, &reserve_file,
&reserve_count, sizeof(dvd_reserve)))
return DVD_ERR_BAD_RESERVE_TABLE;
dvd_db_ok = 1;
return DVD_SUCCESS;
}
int dvd_close_db()
{
/* Close the database tables
Ought to check return result from the fclose
*/
if(member_file)
fclose(member_file);
if(title_file)
fclose(title_file);
if(disk_file)
fclose(disk_file);
dvd_db_ok = 0;
return DVD_SUCCESS;
}
static int file_set(FILE *file, long file_position, int size, void *data)
{
if(fseek(file, file_position, SEEK_SET) != 0)
return DVD_ERR_BAD_SEEK;
if(fwrite(data, size, 1, file) != 1)
return DVD_ERR_BAD_WRITE;
return DVD_SUCCESS;
}
static int file_get(FILE *file, long file_position, int size, void *data)
{
if(fseek(file, file_position, SEEK_SET) != 0)
return DVD_ERR_BAD_SEEK;
if(fread(data, size, 1, file) != 1)
return DVD_ERR_BAD_READ;
return DVD_SUCCESS;
}
@
1.2
log
@*** empty log message ***
@
text
@d40 3
a42 3
if(open_db_table(MEMBER_FILE, &member_file,
&member_count, sizeof(dvd_store_member)))
return DVD_ERR_BAD_MEMBER_TABLE;
@
1.1
log
@Initial revision
@
text
@a0 112
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "dvd.h"
/*
DVD Store Application Reference API Implementation
This file contains definitions of functions conforming
to the DVD Store application database APIs.
It is not intended to form the basis of a real
implementation - that will use a real database.
This implementation can be used to:
- confirm understanding of the API functionality
- allow testing to proceed at an early stage
- allow concurrent development of front and back ends
The implementation herein uses flat files to store
the data tables, one per file. A simplistic approach
is taken to data access. No thought has been given
to optimization, the code just needs to work.
All of the database files are created in the current
directory.
*/
/* Prototypes -- as in dvd.h */
/*int dvd_open_db(void);
int dvd_close_db(void);
int dvd_member_set(dvd_store_member *member_record_to_update);
int dvd_member_get(int member_id, dvd_store_member *member_record_to_complete);
int dvd_member_create(dvd_store_member *member_record_to_add, int *member_id);
int dvd_member_delete(int member_id);
int dvd_member_search(char *lname, int *result_ids[], int *count);
int dvd_member_get_id_from_number(char *member_no, int *member_id);
int dvd_title_set(dvd_title *title_record_to_update);
int dvd_title_get(int title_id, dvd_title *title_record_to_complete);
int dvd_title_create(dvd_title *title_record_to_add, int *title_id);
int dvd_title_delete(int title_id);
int dvd_title_search(char *title, char *name, int *result_ids[], int *count);
int dvd_disk_set(dvd_disk *disk_record_to_update);
int dvd_disk_get(int disk_id, dvd_disk *disk_record_to_complete);
int dvd_disk_create(dvd_disk *disk_record_to_add, int *disk_id);
int dvd_disk_delete(int disk_id);
int dvd_disk_search(int title_id, int *result_ids[], int *count);
int dvd_get_genre_list(char **genre_list[], int *count);
int dvd_get_classification_list(char **class_list[], int *count);
int dvd_err_text(int errno, char **message_to_show);
int dvd_today(char **date);
int dvd_rent_title(int member_id, int title_id, int *disk_id);
int dvd_rented_disk_info(int disk_id, int *member_id, char *date_rented);
int dvd_disk_return(int disk_id, int *member_id, char *date);
int dvd_overdue_disks(char *date1, char *date2, int *disk_ids[], int *count);
int dvd_title_available(int title_id, char *date, int *count);
int dvd_reserve_title(char date[], int title_id, int member_id);
int dvd_reserve_title_cancel(int member_id);
int dvd_reserve_title_query_by_member(int member_id, int *title_id);
int dvd_reserve_title_query_by_titledate(int title_id, char *date, int *member_ids[]);
*/
/* Implementation */
/* Internal data structures for reservations and rentals */
typedef struct _reservation_struct {
int member_id;
int title_id;
char date[9];
} dvd_reserve;
typedef struct _rental_struct {
int disk_id;
int member_id;
char date[9];
} dvd_rental;
static int dvd_rental_set(int disk_id, dvd_rental *rental);
static int dvd_reserve_set(int member_id, dvd_reserve *reserve);
/* Database definitions */
#define MEMBER_FILE "member.dat"
static FILE *member_file = NULL;
static int member_count = 0;
#define TITLE_FILE "title.dat"
static FILE *title_file = NULL;
static int title_count = 0;
#define DISK_FILE "disk.dat"
static FILE *disk_file = NULL;
static int disk_count = 0;
#define RENTAL_FILE "rental.dat"
static FILE *rental_file = NULL;
static int rental_count = 0;
#define RESERVE_FILE "reserve.dat"
static FILE *reserve_file = NULL;
static int reserve_count = 0;
/* Helper functions to open files */
d2 1
a2 1
int *count_ptr, int record_size)
d10 1
a10 2
to create if needed, then reopen as we need
*/
a33 3
/* This is a mandatory API */
static int dvd_db_ok = 0;
d41 1
a41 1
&member_count, sizeof(dvd_store_member)))
d45 1
a45 1
&title_count, sizeof(dvd_title)))
d49 1
a49 1
&disk_count, sizeof(dvd_disk)))
d53 1
a53 1
&rental_count, sizeof(dvd_rental)))
d57 1
a57 1
&reserve_count, sizeof(dvd_reserve)))
a99 740
}
int dvd_member_set(dvd_store_member *member_record_to_update)
{
if(member_record_to_update == NULL)
return DVD_ERR_NULL_POINTER;
return
file_set(member_file,
sizeof(dvd_store_member) * (member_record_to_update -> member_id),
sizeof(dvd_store_member),
(void *) member_record_to_update);
}
int dvd_member_get(int member_id, dvd_store_member *member_record_to_complete)
{
int err = DVD_SUCCESS;
if(member_record_to_complete == NULL)
return DVD_ERR_NULL_POINTER;
err = file_get(member_file,
sizeof(dvd_store_member) * member_id,
sizeof(dvd_store_member),
(void *) member_record_to_complete);
/* If we cannot get the member there may be an error
with the data, or the member may not exist */
if(err != DVD_SUCCESS)
return err;
/* If the retrieved member id is not as expected there
may be an error, or the member may be deleted */
if(member_record_to_complete -> member_id == 0)
return DVD_ERR_NOT_FOUND;
if(member_id != member_record_to_complete -> member_id)
return DVD_ERR_BAD_MEMBER_TABLE;
return DVD_SUCCESS;
}
int dvd_member_create(dvd_store_member *member_record_to_add, int *member_id)
{
int err;
dvd_store_member new_member;
dvd_reserve null_reserve;
/* Make a new member record. The caller does not need to fill-in
the member_id or member_no fields, these will be created before
the member record is added to the database. The new meber_id
is returned in the output parameter member_id. This must be
use to retrieve the new member record to discover or set the
member_no.
*/
/* Take a copy of the passed member, in case it is static */
new_member = *member_record_to_add;
/* The new member_id is the next available id */
new_member.member_id = member_count;
/* The new member_no (in this implementation) is 10000+id */
sprintf(new_member.member_no, "%05d", member_count+10000);
/* Add the new member to the member and reservations file */
err = dvd_member_set(&new_member);
if(err != DVD_SUCCESS)
return err;
memset((void *) &null_reserve, 0, sizeof(dvd_reserve));
null_reserve.member_id = new_member.member_id;
err = dvd_reserve_set(null_reserve.member_id, &null_reserve);
if(err != DVD_SUCCESS)
return err;
/* Update member file state */
*member_id = member_count;
member_count++;
return DVD_SUCCESS;
}
int dvd_member_delete(int member_id)
{
/* Delete a member by setting the member_id to zero */
dvd_store_member null_member;
memset((void *)&null_member, 0, sizeof(null_member));
return file_set(member_file,
member_id * sizeof(null_member),
sizeof(null_member),
&null_member);
}
int dvd_member_get_id_from_number(char *member_no, int *member_id)
{
/* Search for a member by member number.
Note that this is an case insensitive EXACT match
in case we ever want to use alpha member "numbers"
*/
dvd_store_member member;
int id = 1;
int err;
while(err = dvd_member_get(id, &member),
err == DVD_SUCCESS || err == DVD_ERR_NOT_FOUND) {
if(err == DVD_SUCCESS &&
strcasecmp(member_no, member.member_no) == 0) {
*member_id = id;
return DVD_SUCCESS;
}
id++;
}
return DVD_ERR_NOT_FOUND;
}
int dvd_member_search(char *lname, int *result_ids[], int *count)
{
/* Search for member by surname
Note this a case sensitive match as there is
no case insensitive strstr!
*/
dvd_store_member member;
int id = 1;
int matches = 0;
int *results = NULL;
int results_size = 0;
int err;
*count = 0;
while(err = dvd_member_get(id, &member),
err == DVD_SUCCESS || err == DVD_ERR_NOT_FOUND) {
if(err == DVD_SUCCESS &&
strstr(member.lname, lname) != NULL &&
member.member_id != 0) {
/* Add a result to the list */
/* Increase capacity if required */
if(matches >= results_size) {
results_size += 4;
results = (int *)realloc(results, sizeof(int)*results_size);
if(results == NULL)
return DVD_ERR_NO_MEMORY;
}
results[matches] = member.member_id;
matches++;
}
id++;
}
*result_ids = results;
*count = matches;
return DVD_SUCCESS;
}
int dvd_title_set(dvd_title *title_record_to_update)
{
if(title_record_to_update == NULL)
return DVD_ERR_NULL_POINTER;
return
file_set(title_file,
sizeof(dvd_title) * (title_record_to_update -> title_id),
sizeof(dvd_title),
(void *) title_record_to_update);
}
int dvd_title_get(int title_id, dvd_title *title_record_to_complete)
{
int err = DVD_SUCCESS;
if(title_record_to_complete == NULL)
return DVD_ERR_NULL_POINTER;
err = file_get(title_file,
sizeof(dvd_title) * title_id,
sizeof(dvd_title),
(void *) title_record_to_complete);
/* If we cannot get the title there may be an error
with the data, or the title may not exist */
if(err != DVD_SUCCESS)
return err;
/* If the retrieved title id is not as expected there
may be an error, or the title may be deleted */
if(title_record_to_complete -> title_id == 0)
return DVD_ERR_NOT_FOUND;
if(title_id != title_record_to_complete -> title_id)
return DVD_ERR_BAD_MEMBER_TABLE;
return DVD_SUCCESS;
}
int dvd_title_create(dvd_title *title_record_to_add, int *title_id)
{
int err;
/* Make a new title record. See also notes in member_create. */
/* Take a copy of the passed member, in case it is static */
dvd_title new_title = *title_record_to_add;
/* The new title_id is the next available id */
new_title.title_id = title_count;
/* Add the new title to the title file */
err = dvd_title_set(&new_title);
if(err != DVD_SUCCESS)
return err;
/* Update title file state */
*title_id = title_count;
title_count++;
return DVD_SUCCESS;
}
int dvd_title_delete(int title_id)
{
/* Delete a title by setting the title_id to zero */
dvd_title null_title;
memset((void *)&null_title, 0, sizeof(null_title));
return file_set(title_file,
title_id * sizeof(null_title),
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -