#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 7 /* size of ptr field in hash chain */
#define PTR_MAX 9999999 /* 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
没有合适的资源?快使用搜索试试~ 我知道了~
apue.3e.rar
共818个文件
c:221个
makefile:28个
12:15个
需积分: 5 0 下载量 140 浏览量
2022-10-01
23:22:34
上传
评论
收藏 493KB RAR 举报
温馨提示
apue.3e.rar
资源详情
资源评论
资源推荐
收起资源包目录
apue.3e.rar (818个子文件)
0048e6807b1224a35ae329d5c93642e72371e7 490B
00c4e3e2eaaa7a5366fa79f29f236802696a1c 227B
02dc15ceaedef0f7da8a98c18a6df246546b34 292B
02e52466e4a095186c8d4a0daa8eaf0b1f3df1 206B
036c54836a85bed568b06a8bd2cdb99a826fe0 716B
0441a25a191472134eea6902f68c4458507779 137B
052e437af5a41a51739c97e9526786dce6fa21 645B
05851ef003fab4e09a14f6438475d6f48b1840 685B
099c4eff569abe417b18a9b3b6969b1a8df4ed 404B
09cfbd9a3f56552c5a044a1341c0791d9901fa 354B
0ae4bf70a8f82f9d47bb41ec12d9779b53a569 74B
0d3f55752278bc75b0f53c39c9a0b9535f8218 807B
0d5b7dad72f44fdf0d108fea6d14736db13740 880B
0e4d9a7a49ac3d65a047605702052ac724b8c7 282B
0f0178609e6e23517ab78c0b9446c81c3fc73c 267B
0f77f23e4dbcc0d6fc52d630a3e32116776f82 128B
0fa3893b5dd2637c1d47fec4c8336f6f771aae 1KB
0fe2bc049cbf29d83fcd21e32022379deb267d 103B
figB.1 5KB
fig13.1 2KB
fig8.1 624B
fig14.1 590B
figC.1 420B
fig3.1 149B
fig7.1 58B
fig19.10 2KB
fig17.10 1KB
fig11.10 922B
fig1.10 826B
fig18.10 609B
fig16.10 472B
fig10.10 411B
figC.10 321B
106e3f1634133898f4c9f8b76a8e9c608add48 349B
fig19.11 3KB
fig11.11 2KB
fig5.11 2KB
fig3.11 781B
fig15.11 652B
fig18.11 608B
fig16.11 588B
fig10.11 480B
fig6.11 471B
fig7.11 423B
fig12.11 411B
fig15.12 2KB
fig11.12 2KB
fig19.12 2KB
fig14.12 2KB
fig12.12 980B
figC.12 879B
fig9.12 854B
fig10.12 642B
fig5.12 532B
fig17.12 475B
fig16.12 458B
fig4.12 429B
fig8.12 426B
fig3.12 310B
fig18.12 209B
fig2.13 3KB
fig17.13 1KB
fig12.13 1002B
fig7.13 986B
fig5.13 740B
fig8.13 502B
figC.13 382B
fig18.13 135B
fig11.14 2KB
fig17.14 2KB
fig2.14 2KB
fig10.14 620B
fig7.14 275B
figC.14 266B
fig15.14 240B
fig18.14 216B
1470d47fc90ac7f71131f1fdbc3e17a65e102a 276B
fig18.15 2KB
figC.15 2KB
fig17.15 2KB
fig10.15 950B
fig5.15 876B
fig11.15 633B
fig15.15 450B
fig17.16 3KB
fig11.16 2KB
fig12.16 1KB
fig7.16 1KB
fig2.16 1KB
fig19.16 1KB
fig16.16 1KB
fig8.16 669B
fig18.16 502B
fig4.16 242B
figC.16 209B
16fcbf04bae5d06f5267810cf02d5929137aa4 429B
fig16.17 2KB
fig12.17 2KB
fig18.17 1KB
fig2.17 524B
共 818 条
- 1
- 2
- 3
- 4
- 5
- 6
- 9
Embedded_Sky77
- 粉丝: 10
- 资源: 5
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0