#include "apue.h"
#include "apue_db.h"
#include <fcntl.h> /* open & db_open flags */
#include <stdarg.h>
#include <errno.h>
#include <sys/uio.h> /* struct iovec */
/*
* Internal index file constants.
* These are used to construct records in the
* index file and data file.
*/
#define IDXLEN_SZ 4 /* index record length (ASCII chars) */
#define SEP ':' /* separator char in index record */
#define SPACE ' ' /* space character */
#define NEWLINE '\n' /* newline character */
/*
* The following definitions are for hash chains and free
* list chain in the index file.
*/
#define PTR_SZ 6 /* size of ptr field in hash chain */
#define PTR_MAX 999999 /* max file offset = 10**PTR_SZ - 1 */
#define NHASH_DEF 137 /* default hash table size */
#define FREE_OFF 0 /* free list offset in index file */
#define HASH_OFF PTR_SZ /* hash table offset in index file */
typedef unsigned long DBHASH; /* hash values */
typedef unsigned long COUNT; /* unsigned counter */
/*
* Library's private representation of the database.
*/
typedef struct {
int idxfd; /* fd for index file */
int datfd; /* fd for data file */
char *idxbuf; /* malloc'ed buffer for index record */
char *datbuf; /* malloc'ed buffer for data record*/
char *name; /* name db was opened under */
off_t idxoff; /* offset in index file of index record */
/* key is at (idxoff + PTR_SZ + IDXLEN_SZ) */
size_t idxlen; /* length of index record */
/* excludes IDXLEN_SZ bytes at front of record */
/* includes newline at end of index record */
off_t datoff; /* offset in data file of data record */
size_t datlen; /* length of data record */
/* includes newline at end */
off_t ptrval; /* contents of chain ptr in index record */
off_t ptroff; /* chain ptr offset pointing to this idx record */
off_t chainoff; /* offset of hash chain for this index record */
off_t hashoff; /* offset in index file of hash table */
DBHASH nhash; /* current hash table size */
COUNT cnt_delok; /* delete OK */
COUNT cnt_delerr; /* delete error */
COUNT cnt_fetchok; /* fetch OK */
COUNT cnt_fetcherr; /* fetch error */
COUNT cnt_nextrec; /* nextrec */
COUNT cnt_stor1; /* store: DB_INSERT, no empty, appended */
COUNT cnt_stor2; /* store: DB_INSERT, found empty, reused */
COUNT cnt_stor3; /* store: DB_REPLACE, diff len, appended */
COUNT cnt_stor4; /* store: DB_REPLACE, same len, overwrote */
COUNT cnt_storerr; /* store error */
} DB;
/*
* Internal functions.
*/
static DB *_db_alloc(int);
static void _db_dodelete(DB *);
static int _db_find_and_lock(DB *, const char *, int);
static int _db_findfree(DB *, int, int);
static void _db_free(DB *);
static DBHASH _db_hash(DB *, const char *);
static char *_db_readdat(DB *);
static off_t _db_readidx(DB *, off_t);
static off_t _db_readptr(DB *, off_t);
static void _db_writedat(DB *, const char *, off_t, int);
static void _db_writeidx(DB *, const char *, off_t, int, off_t);
static void _db_writeptr(DB *, off_t, off_t);
/*
* Open or create a database. Same arguments as open(2).
*/
DBHANDLE
db_open(const char *pathname, int oflag, ...)
{
DB *db;
int len, mode;
size_t i;
char asciiptr[PTR_SZ + 1],
hash[(NHASH_DEF + 1) * PTR_SZ + 2];
/* +2 for newline and null */
struct stat statbuff;
/*
* Allocate a DB structure, and the buffers it needs.
*/
len = strlen(pathname);
if ((db = _db_alloc(len)) == NULL)
err_dump("db_open: _db_alloc error for DB");
db->nhash = NHASH_DEF;/* hash table size */
db->hashoff = HASH_OFF; /* offset in index file of hash table */
strcpy(db->name, pathname);
strcat(db->name, ".idx");
if (oflag & O_CREAT) {
va_list ap;
va_start(ap, oflag);
mode = va_arg(ap, int);
va_end(ap);
/*
* Open index file and data file.
*/
db->idxfd = open(db->name, oflag, mode);
strcpy(db->name + len, ".dat");
db->datfd = open(db->name, oflag, mode);
} else {
/*
* Open index file and data file.
*/
db->idxfd = open(db->name, oflag);
strcpy(db->name + len, ".dat");
db->datfd = open(db->name, oflag);
}
if (db->idxfd < 0 || db->datfd < 0) {
_db_free(db);
return(NULL);
}
if ((oflag & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) {
/*
* If the database was created, we have to initialize
* it. Write lock the entire file so that we can stat
* it, check its size, and initialize it, atomically.
*/
if (writew_lock(db->idxfd, 0, SEEK_SET, 0) < 0)
err_dump("db_open: writew_lock error");
if (fstat(db->idxfd, &statbuff) < 0)
err_sys("db_open: fstat error");
if (statbuff.st_size == 0) {
/*
* We have to build a list of (NHASH_DEF + 1) chain
* ptrs with a value of 0. The +1 is for the free
* list pointer that precedes the hash table.
*/
sprintf(asciiptr, "%*d", PTR_SZ, 0);
hash[0] = 0;
for (i = 0; i < NHASH_DEF + 1; i++)
strcat(hash, asciiptr);
strcat(hash, "\n");
i = strlen(hash);
if (write(db->idxfd, hash, i) != i)
err_dump("db_open: index file init write error");
}
if (un_lock(db->idxfd, 0, SEEK_SET, 0) < 0)
err_dump("db_open: un_lock error");
}
db_rewind(db);
return(db);
}
/*
* Allocate & initialize a DB structure and its buffers.
*/
static DB *
_db_alloc(int namelen)
{
DB *db;
/*
* Use calloc, to initialize the structure to zero.
*/
if ((db = calloc(1, sizeof(DB))) == NULL)
err_dump("_db_alloc: calloc error for DB");
db->idxfd = db->datfd = -1; /* descriptors */
/*
* Allocate room for the name.
* +5 for ".idx" or ".dat" plus null at end.
*/
if ((db->name = malloc(namelen + 5)) == NULL)
err_dump("_db_alloc: malloc error for name");
/*
* Allocate an index buffer and a data buffer.
* +2 for newline and null at end.
*/
if ((db->idxbuf = malloc(IDXLEN_MAX + 2)) == NULL)
err_dump("_db_alloc: malloc error for index buffer");
if ((db->datbuf = malloc(DATLEN_MAX + 2)) == NULL)
err_dump("_db_alloc: malloc error for data buffer");
return(db);
}
/*
* Relinquish access to the database.
*/
void
db_close(DBHANDLE h)
{
_db_free((DB *)h); /* closes fds, free buffers & struct */
}
/*
* Free up a DB structure, and all the malloc'ed buffers it
* may point to. Also close the file descriptors if still open.
*/
static void
_db_free(DB *db)
{
if (db->idxfd >= 0)
close(db->idxfd);
if (db->datfd >= 0)
close(db->datfd);
if (db->idxbuf != NULL)
free(db->idxbuf);
if (db->datbuf != NULL)
free(db->datbuf);
if (db->name != NULL)
free(db->name);
free(db);
}
/*
* Fetch a record. Return a pointer to the null-terminated data.
*/
char *
db_fetch(DBHANDLE h, const char *key)
{
DB *db = h;
char *ptr;
if (_db_find_and_lock(db, key, 0) < 0) {
ptr = NULL; /* error, record not found */
db->cnt_fetcherr++;
} else {
ptr = _db_readdat(db); /* return pointer to data */
db->cnt_fetchok++;
}
/*
* Unlock the hash chain that _db_find_and_lock locked.
*/
if (un_lock(db->idxfd, db->chainoff, SEEK_SET, 1) < 0)
err_dump("db_fetch: un_lock error");
return(ptr);
}
/*
* Find the specified record. Called by db_delete, db_fetch,
* and db_store. Returns with the hash chain locked.
*/
static int
_db_find_and_lock(DB *db, const char *key, int writelock)
{
off_t offset, nextoffset;
/*
* Calculate the hash value for this key, then calculate the
* byte offset of corresponding chain ptr in hash table.
* This is where our search starts. First we calculate the
* offset in the hash table for this key.
*/
db->chainoff = (_db_hash(db, key) * PTR_SZ) + db->hashoff;
db->ptroff = db->chainoff;
/*
* We lock the hash chain here. The caller must unlock it
* when done. Note we lock and unlock only the first byte.
*/
if (writelock) {
if (writew_lock(db->idxfd, db->chainoff, SEEK_SET, 1) < 0)
err_dump("_db_find_and_lock: writew_lock error");
} else {
if (readw_lock(db->idxfd, db->chai
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
相信很多初学《UNIX环境高级编程》的朋友都会遇到一个问题,运行里面的实例时就出现问题,提示 "错误:apue.h:没有那个文件或目录". apue.h是作者自定义的一个头文件,包括程序所需的常用头文件及出错处理函数。所以因该将它放入系统头文件中(Linux下是 /usr/include),这样gcc编译器就可以找到它了。 1. 超级用户权限登入 #cd /usr/include 2. 将apue.h和error.c两个文件copy到该目录下。(apue.h位于 your_apue_path/inlcude ; error.c位于your_apue_path/lib ) 以我的了路径为例: #cp /home/ucfree/apue.2e/inlcude/apue.h . #cp /home/ucfree/apue.2e/lib/error.c . (实现apue.h中的出错处理函数) 3. 编辑apue.h #vi apue.h 在最后一行 #endif /* _APUE_H */ 前面添加一行 #include "error.c" :wq 保存,退出. 这样你就可以运行下载的apue程序了.
资源推荐
资源详情
资源评论
收起资源包目录
apue.h 《UNIX环境高级编程》 头文件 (588个子文件)
figB.1 5KB
fig13.1 2KB
fig8.1 606B
fig14.1 590B
figC.1 420B
fig3.1 149B
fig7.1 58B
fig19.10 2KB
fig17.10 882B
fig11.10 880B
fig1.10 826B
fig3.10 783B
fig18.10 609B
fig16.10 486B
fig10.10 411B
fig11.11 2KB
fig19.11 2KB
fig5.11 1KB
fig9.11 869B
figC.11 866B
fig15.11 652B
fig18.11 608B
fig17.11 488B
fig10.11 480B
fig7.11 423B
fig12.11 365B
fig3.11 310B
fig19.12 3KB
fig2.12 3KB
fig15.12 2KB
fig11.12 2KB
fig14.12 2KB
fig12.12 979B
fig10.12 625B
fig5.12 532B
fig4.12 429B
fig8.12 426B
figC.12 370B
fig17.12 354B
fig18.12 209B
fig11.13 2KB
fig19.13 2KB
fig2.13 2KB
fig7.13 986B
fig12.13 956B
fig8.13 502B
figC.13 266B
fig17.13 250B
fig5.13 234B
fig18.13 135B
figC.14 2KB
fig16.14 1KB
fig11.14 631B
fig10.14 570B
fig17.14 455B
fig7.14 302B
fig15.14 240B
fig18.14 216B
fig18.15 2KB
fig16.15 2KB
fig2.15 982B
fig10.15 948B
fig17.15 912B
fig15.15 450B
figC.15 209B
fig16.16 2KB
fig17.16 2KB
fig12.16 1KB
fig7.16 1KB
fig8.16 669B
fig2.16 546B
fig18.16 499B
fig4.16 242B
figC.16 177B
fig14.16 107B
fig16.17 2KB
fig17.17 1KB
fig12.17 1KB
fig18.17 1KB
fig19.17 1KB
fig15.17 466B
figC.17 368B
fig14.17 351B
fig8.17 308B
fig16.18 1KB
fig15.18 1KB
fig14.18 1005B
fig10.18 466B
figC.18 394B
fig18.18 328B
fig14.19 628B
fig17.19 475B
fig15.19 343B
fig10.19 315B
fig11.2 539B
fig10.2 509B
fig3.2 478B
fig6.2 340B
fig18.20 3KB
fig10.20 1022B
共 588 条
- 1
- 2
- 3
- 4
- 5
- 6
资源评论
- zhouruohua2014-10-27好东西,就是不会用
- 为了维护世界和平_2015-07-23下载了 可是在电脑里用不起来
- _Gatsby2015-10-17亲测可用,很好。
- ErwinDarg2014-08-16很好,非常不错
- 编程牛2016-06-01不错的东西
三月软件----王耀峰
- 粉丝: 22
- 资源: 22
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功