Remove cdb support
This commit is contained in:
parent
5699020a6b
commit
0923f6a52e
25 changed files with 6 additions and 1975 deletions
|
@ -21,9 +21,6 @@ if(WITH_BNETD)
|
|||
bnxpcalc.conf bnxplevel.conf channel.conf command_groups.conf
|
||||
realm.conf sql_DB_layout.conf supportfile.conf topics.conf
|
||||
tournament.conf versioncheck.json icons.conf)
|
||||
|
||||
# special treatment for non .in files
|
||||
install(FILES bnetd_default_user.cdb DESTINATION ${SYSCONFDIR})
|
||||
endif(WITH_BNETD)
|
||||
|
||||
if(WITH_D2CS)
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
# Syntax: #
|
||||
# * for plain file driver: #
|
||||
# storage_path = file:mode=plain;dir=<path_to_user_files>;clan=<path_to_clan_files>;default=/path/to/default/account #
|
||||
# * for cdb file driver: #
|
||||
# storage_path = file:mode=cdb;dir=<path_to_cdb_files>;clan=<path_to_clan_files>;default=/path/to/default/account #
|
||||
# * for sql driver: #
|
||||
# storage_path = sql:variable=value;...;default=0 (0 is the default uid) #
|
||||
# #
|
||||
|
@ -52,7 +50,6 @@
|
|||
# #
|
||||
# Examples: #
|
||||
# storage_path = "file:mode=plain;dir=${LOCALSTATEDIR}/users;clan=${LOCALSTATEDIR}/clans;team=${LOCALSTATEDIR}/teams;default=${SYSCONFDIR}/bnetd_default_user.plain"
|
||||
# storage_path = "file:mode=cdb;dir=${LOCALSTATEDIR}/userscdb;clan=${LOCALSTATEDIR}/clans;team=${LOCALSTATEDIR}/teams;default=${SYSCONFDIR}/bnetd_default_user.cdb"
|
||||
# storage_path = "sql:mode=mysql;host=127.0.0.1;name=PVPGN;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_"
|
||||
# storage_path = "sql:mode=pgsql;host=127.0.0.1;name=pvpgn;user=pvpgn;pass=pvpgnrocks;default=0;prefix=pvpgn_"
|
||||
# storage_path = "sql:mode=sqlite3;name=${LOCALSTATEDIR}/users.db;default=0;prefix=pvpgn_"
|
||||
|
|
Binary file not shown.
|
@ -5,8 +5,7 @@ include_directories(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src)
|
|||
# when referenced by short names
|
||||
link_directories(${CMAKE_BINARY_DIR}/src/common
|
||||
${CMAKE_BINARY_DIR}/src/compat
|
||||
${CMAKE_BINARY_DIR}/src/win32
|
||||
${CMAKE_BINARY_DIR}/src/tinycdb)
|
||||
${CMAKE_BINARY_DIR}/src/win32)
|
||||
|
||||
#this is needed to be compatible with existent code
|
||||
add_definitions("-DHAVE_CONFIG_H")
|
||||
|
@ -32,15 +31,12 @@ endif(SQLITE3_FOUND)
|
|||
if(PGSQL_FOUND)
|
||||
add_definitions("-DWITH_SQL_PGSQL")
|
||||
endif(PGSQL_FOUND)
|
||||
if(ODBC_FOUND)
|
||||
add_definitions("-DWITH_SQL_ODBC")
|
||||
endif(ODBC_FOUND)
|
||||
|
||||
if (WITH_WIN32_GUI)
|
||||
add_definitions("-DWIN32_GUI")
|
||||
endif (WITH_WIN32_GUI)
|
||||
|
||||
subdirs(compat common win32 tinycdb bntrackd client bniutils bnpass)
|
||||
subdirs(compat common win32 bntrackd client bniutils bnpass)
|
||||
|
||||
if(WITH_BNETD)
|
||||
add_subdirectory(bnetd)
|
||||
|
|
|
@ -12,8 +12,8 @@ set(BNETD_SOURCES
|
|||
attrlayer.h autoupdate.cpp autoupdate.h channel_conv.cpp channel_conv.h
|
||||
channel.cpp channel.h character.cpp character.h clan.cpp clan.h
|
||||
cmdline.cpp cmdline.h command.cpp command_groups.cpp command_groups.h
|
||||
command.h connection.cpp connection.h file_cdb.cpp file_cdb.h file.cpp
|
||||
file.h file_plain.cpp file_plain.h friends.cpp friends.h game_conv.cpp
|
||||
command.h connection.cpp connection.h file.cpp file.h file_plain.cpp
|
||||
file_plain.h friends.cpp friends.h game_conv.cpp
|
||||
game_conv.h game.cpp game.h handle_anongame.cpp handle_anongame.h
|
||||
handle_apireg.cpp handle_apireg.h handle_bnet.cpp handle_bnet.h
|
||||
handle_bot.cpp handle_bot.h handle_d2cs.cpp handle_d2cs.h
|
||||
|
@ -53,6 +53,6 @@ else(WITH_WIN32_GUI)
|
|||
add_executable(bnetd ${BNETD_SOURCES} ${BNETD_CONSOLE_RESOURCES})
|
||||
endif(WITH_WIN32_GUI)
|
||||
|
||||
target_link_libraries(bnetd common compat win32 tinycdb ${NETWORK_LIBRARIES}
|
||||
target_link_libraries(bnetd common compat win32 ${NETWORK_LIBRARIES}
|
||||
${ZLIB_LIBRARIES} ${MYSQL_LIBRARIES} ${SQLITE3_LIBRARIES} ${PGSQL_LIBRARIES} ${ODBC_LIBRARIES} ${LUA_LIBRARIES})
|
||||
install(TARGETS bnetd DESTINATION ${SBINDIR})
|
||||
|
|
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003,2004 Dizzy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "common/setup_before.h"
|
||||
#include "file_cdb.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "common/eventlog.h"
|
||||
#include "tinycdb/cdb.h"
|
||||
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
namespace bnetd
|
||||
{
|
||||
|
||||
/* cdb file storage API functions */
|
||||
|
||||
static int cdb_read_attrs(const char *filename, t_read_attr_func cb, void *data);
|
||||
static t_attr * cdb_read_attr(const char *filename, const char *key);
|
||||
static int cdb_write_attrs(const char *filename, const t_hlist *attributes);
|
||||
|
||||
/* file_engine struct populated with the functions above */
|
||||
|
||||
t_file_engine file_cdb = {
|
||||
cdb_read_attr,
|
||||
cdb_read_attrs,
|
||||
cdb_write_attrs
|
||||
};
|
||||
|
||||
/* start of actual cdb file storage code */
|
||||
|
||||
//#define CDB_ON_DEMAND 1
|
||||
|
||||
static int cdb_write_attrs(const char *filename, const t_hlist *attributes)
|
||||
{
|
||||
std::FILE *cdbfile;
|
||||
t_hlist *curr;
|
||||
t_attr *attr;
|
||||
struct cdb_make cdbm;
|
||||
|
||||
if ((cdbfile = std::fopen(filename, "w+b")) == NULL) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "unable to open file \"{}\" for writing ", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cdb_make_start(&cdbm, cdbfile);
|
||||
|
||||
hlist_for_each(curr, attributes) {
|
||||
attr = hlist_entry(curr, t_attr, link);
|
||||
|
||||
if (attr_get_key(attr) && attr_get_val(attr)) {
|
||||
if (std::strncmp("BNET\\CharacterDefault\\", attr_get_key(attr), 20) == 0) {
|
||||
eventlog(eventlog_level_debug, __FUNCTION__, "skipping attribute key=\"{}\"", attr_get_key(attr));
|
||||
}
|
||||
else {
|
||||
eventlog(eventlog_level_debug, __FUNCTION__, "saving attribute key=\"{}\" val=\"{}\"", attr_get_key(attr), attr_get_val(attr));
|
||||
if (cdb_make_add(&cdbm, attr_get_key(attr), std::strlen(attr_get_key(attr)), attr_get_val(attr), std::strlen(attr_get_val(attr))) < 0)
|
||||
{
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "got error on cdb_make_add ('{}' = '{}')", attr_get_key(attr), attr_get_val(attr));
|
||||
cdb_make_finish(&cdbm); /* try to bail out nicely */
|
||||
std::fclose(cdbfile);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else eventlog(eventlog_level_error, __FUNCTION__, "could not save attribute key=\"{}\"", attr_get_key(attr));
|
||||
|
||||
attr_clear_dirty(attr);
|
||||
}
|
||||
|
||||
if (cdb_make_finish(&cdbm) < 0) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "got error on cdb_make_finish");
|
||||
std::fclose(cdbfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (std::fclose(cdbfile) < 0) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "got error on std::fclose()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CDB_ON_DEMAND
|
||||
/* code adapted from tinycdb-0.73/cdb.c */
|
||||
|
||||
static int fget(std::FILE * fd, unsigned char *b, cdbi_t len, cdbi_t *posp, cdbi_t limit)
|
||||
{
|
||||
if (posp && limit - *posp < len) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "invalid cdb database format");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (std::fread(b, 1, len, fd) != len) {
|
||||
if (std::ferror(fd)) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "got error reading from db file");
|
||||
return -1;
|
||||
}
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "unable to read from cdb file, incomplete file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (posp) *posp += len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * fcpy(std::FILE *fd, cdbi_t len, cdbi_t *posp, cdbi_t limit, unsigned char * buf)
|
||||
{
|
||||
static char *str;
|
||||
static unsigned strl;
|
||||
unsigned int res = 0, no = 0;
|
||||
|
||||
if (strl < len + 1) {
|
||||
char *tmp;
|
||||
|
||||
tmp = (char*)xmalloc(len + 1);
|
||||
if (str) xfree((void*)str);
|
||||
str = tmp;
|
||||
strl = len + 1;
|
||||
}
|
||||
|
||||
while (len - res > 0) {
|
||||
if (len > 2048) no = 2048;
|
||||
else no = len;
|
||||
|
||||
if (fget(fd, buf, no, posp, limit)) return NULL;
|
||||
std::memmove(str + res, buf, no);
|
||||
res += no;
|
||||
}
|
||||
|
||||
if (res > strl - 1) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "BUG, this should not happen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str[res] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
static int cdb_read_attrs(const char *filename, t_read_attr_func cb, void *data)
|
||||
{
|
||||
cdbi_t eod, klen, vlen;
|
||||
cdbi_t pos = 0;
|
||||
const char *key;
|
||||
const char *val;
|
||||
unsigned char buf[2048];
|
||||
std::FILE *f;
|
||||
|
||||
if ((f = std::fopen(filename, "rb")) == NULL) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "got error opening file '{}'", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fget(f, buf, 2048, &pos, 2048)) goto err_fd;
|
||||
eod = cdb_unpack(buf);
|
||||
while (pos < eod) {
|
||||
if (fget(f, buf, 8, &pos, eod)) goto err_fd;
|
||||
klen = cdb_unpack(buf);
|
||||
vlen = cdb_unpack(buf + 4);
|
||||
if ((key = fcpy(f, klen, &pos, eod, buf)) == NULL) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "error reading attribute key");
|
||||
goto err_fd;
|
||||
}
|
||||
|
||||
key = xstrdup(key);
|
||||
|
||||
if ((val = fcpy(f, vlen, &pos, eod, buf)) == NULL) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "error reading attribute val");
|
||||
goto err_key;
|
||||
}
|
||||
|
||||
// eventlog(eventlog_level_trace, __FUNCTION__, "read atribute : '%s' -> '%s'", key, val);
|
||||
if (cb(key, val, data))
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "got error from callback on account file '{}'", filename);
|
||||
xfree((void *)key);
|
||||
}
|
||||
|
||||
std::fclose(f);
|
||||
return 0;
|
||||
|
||||
err_key:
|
||||
xfree((void *)key);
|
||||
|
||||
err_fd:
|
||||
std::fclose(f);
|
||||
return -1;
|
||||
}
|
||||
#else /* CDB_ON_DEMAND */
|
||||
static int cdb_read_attrs(const char *filename, t_read_attr_func cb, void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static t_attr * cdb_read_attr(const char *filename, const char *key)
|
||||
{
|
||||
#ifdef CDB_ON_DEMAND
|
||||
std::FILE *cdbfile;
|
||||
t_attr *attr;
|
||||
char *val;
|
||||
unsigned vlen = 1;
|
||||
|
||||
// eventlog(eventlog_level_trace, __FUNCTION__, "reading key '{}'", key);
|
||||
if ((cdbfile = std::fopen(filename, "rb")) == NULL) {
|
||||
// eventlog(eventlog_level_debug, __FUNCTION__, "unable to open file \"{}\" for reading ",filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cdb_seek(cdbfile, key, std::strlen(key), &vlen) <= 0) {
|
||||
// eventlog(eventlog_level_debug, __FUNCTION__, "could not find key '{}'", key);
|
||||
std:; std::fclose(cdbfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* FIXME: use attr_* API */
|
||||
attr = xmalloc(sizeof(t_attr));
|
||||
attr->key = xstrdup(key);
|
||||
val = xmalloc(vlen + 1);
|
||||
|
||||
cdb_bread(cdbfile, val, vlen);
|
||||
std::fclose(cdbfile);
|
||||
|
||||
val[vlen] = '\0';
|
||||
|
||||
attr->val = val;
|
||||
attr->dirty = 0;
|
||||
// eventlog(eventlog_level_trace, __FUNCTION__, "read key '{}' value '{}'", attr->key, attr->val);
|
||||
return attr;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef JUST_NEED_TYPES
|
||||
#ifndef INClUDED_FILE_CDB_PROTOS
|
||||
#define INClUDED_FILE_CDB_PROTOS
|
||||
|
||||
#include "storage_file.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
namespace bnetd
|
||||
{
|
||||
|
||||
extern t_file_engine file_cdb;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* INClUDED_FILE_CDB_PROTOS */
|
||||
#endif /* JUST_NEED_TYPES */
|
|
@ -44,7 +44,6 @@
|
|||
#include "team.h"
|
||||
#include "account.h"
|
||||
#include "file_plain.h"
|
||||
#include "file_cdb.h"
|
||||
#include "prefs.h"
|
||||
#include "clan.h"
|
||||
#undef CLAN_INTERNAL_ACCESS
|
||||
|
@ -168,11 +167,9 @@ namespace pvpgn
|
|||
|
||||
if (!strcasecmp(driver, "plain"))
|
||||
file = &file_plain;
|
||||
else if (!strcasecmp(driver, "cdb"))
|
||||
file = &file_cdb;
|
||||
else
|
||||
{
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "unknown mode '{}' must be either plain or cdb", driver);
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "unknown mode '{}', mode must be plain", driver);
|
||||
xfree((void *)copy);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2005 Dizzy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CDBHASH_H_INCLUDED__
|
||||
#define __CDBHASH_H_INCLUDED__
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
typedef unsigned int t_cdbhash;
|
||||
|
||||
static inline t_cdbhash cdb_hash(const void* data, std::size_t len)
|
||||
{
|
||||
t_cdbhash h;
|
||||
const char* p = (const char*)data;
|
||||
|
||||
for (h = 5381; len > 0; --len, ++p) {
|
||||
h += h << 5;
|
||||
h ^= *p;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* __CDBHASH_H_INCLUDED__ */
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
add_library(tinycdb
|
||||
cdb_find.cpp cdb_findnext.cpp cdb.h cdb_hash.cpp cdb_init.cpp cdb_int.h
|
||||
cdb_make_add.cpp cdb_make.cpp cdb_make_find.cpp cdb_make_put.cpp
|
||||
cdb_seek.cpp cdb_seq.cpp cdb_unpack.cpp)
|
||||
add_executable(bncdb cdb.cpp)
|
||||
target_link_libraries(bncdb tinycdb common compat )
|
||||
|
||||
install(TARGETS bncdb DESTINATION ${BINDIR})
|
|
@ -1,144 +0,0 @@
|
|||
2003-11-04 Michael Tokarev <mjt@corpit.ru>
|
||||
|
||||
* added cdb_get() routine: tinycdb officially uses mmap.
|
||||
|
||||
* added cdb_{get,read}{data,key}() macros to read and get
|
||||
current data and key.
|
||||
|
||||
* fixed bug in cdb_seek() - incorrect wrap, sometimes
|
||||
cdb_seek()+cdb_bread() may return EIO instead of finding
|
||||
correct record.
|
||||
|
||||
* added some tweaks to Makefile to build position-independent
|
||||
libcdb_pic.a and shared libcdb.so libraries. Note that
|
||||
using libcdb as shared library is probably not a good idea,
|
||||
due to tiny size of the library.
|
||||
|
||||
* added initial nss_cdb module. Still not well-tested.
|
||||
Probably will not build on non-GNU system.
|
||||
|
||||
* adjusted tests.{ok,sh} for latest cdb utility modifications
|
||||
(-a mode in query by default)
|
||||
|
||||
* Victor Porton (porton at ex-code.com) provided a patch
|
||||
to allow tinycdb to be built on win32 platform (cdb_init.c).
|
||||
Completely untested.
|
||||
|
||||
2003-08-13 Michael Tokarev <mjt@corpit.ru>
|
||||
|
||||
* s/cdbi_t/unsigned/g. No need to keep this type.
|
||||
|
||||
* changed usage of cdb_findnext(): one need to pass
|
||||
pointer to cdb structure to cdb_findnext() now,
|
||||
and should use cdb_datapos(struct cdb_find *)
|
||||
instead of cdb_datapos(struct cdb *)
|
||||
|
||||
* added cdb_seqinit() and cdb_seqnext() routines for sequential
|
||||
record enumeration
|
||||
|
||||
* addded cdb_dend to the cdb structure: end of data
|
||||
position. Use that in cdb_seq*().
|
||||
|
||||
* more strict checking: ensure data is within data section,
|
||||
and hash tables are within hash section of a file.
|
||||
|
||||
* cdb_make.c (cdb_make_start): zerofill cdb_make structure
|
||||
to shut valgrind up (writing uninitialized data to file)
|
||||
|
||||
* cdb.c (cmode): always open file in RDWR mode to allow
|
||||
duplicate key detection
|
||||
|
||||
2002-12-08 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.73
|
||||
* de-Debianization. Oh well... ;)
|
||||
* no code changes, just like in 0.72
|
||||
|
||||
2002-10-13 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.72
|
||||
|
||||
* cleaned up debian packaging and made it actually work
|
||||
|
||||
* no code changes
|
||||
|
||||
2002-07-22 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.71
|
||||
|
||||
* rearranged object files to not depend on ranlib on
|
||||
systems that requires it (i.e. OpenBSD)
|
||||
|
||||
* use ranlib but mark it's possible error as non-fatal
|
||||
|
||||
2001-12-10 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.7a
|
||||
|
||||
* converted to CVS, added two missing #include <stdlib.h> for
|
||||
malloc declaration and spec target to the Makefile
|
||||
|
||||
2001-10-14 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.7
|
||||
|
||||
* added cdb_seek() and cdb_bread() routines as found
|
||||
in freecdb/cdb-0.64
|
||||
|
||||
2001-07-26 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.6
|
||||
|
||||
* added another option, CDB_PUT_WARN, to cdb_make_put's flags
|
||||
(to allow adding unconditionally but still warn about dups),
|
||||
now cdb_make_put seems to be logically complete.
|
||||
|
||||
* added and documented -r and -u options for cdb(1) command,
|
||||
and made them consistent with -w and -e also.
|
||||
|
||||
* reorganized cdb(1) manpage and added changes made to cdb
|
||||
command.
|
||||
|
||||
* added version references to manpages (and make them autogenerated
|
||||
to simplify maintenance).
|
||||
|
||||
* added cdb(5) manpage describing CDB file format.
|
||||
|
||||
2001-07-25 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.5
|
||||
|
||||
* added missing #include <sys/types.h> in cdb_init.c, thanks to
|
||||
ppetru@ppetru.net (Petru Paler)
|
||||
|
||||
* removed usage of pread() in cdb_make_find() and friends,
|
||||
suggested by Liviu Daia <Liviu.Daia@imar.ro>
|
||||
|
||||
* autogenerate tinycdb.spec file from template and debian/changelog
|
||||
|
||||
* autogenerate cdb.h from cdb.h.in (substituting version)
|
||||
|
||||
2001-06-29 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.4
|
||||
|
||||
* added cdb_make_put() routine to conditionnaly add a record
|
||||
|
||||
* split cdb library to more files (finer granularity)
|
||||
|
||||
* added cdb_findinit() and cdb_findnext() routines
|
||||
|
||||
* renamed cdbtool to cdb
|
||||
|
||||
* simplified cdb utility (dropped various format spec, changed
|
||||
options parsing) and a manpage
|
||||
|
||||
* added small note and copyright to every file in package
|
||||
|
||||
* added some testsuite (make test)
|
||||
|
||||
2001-05-27 Michael Tokarev <mjt+cdb@corpit.ru>
|
||||
|
||||
* version 0.3
|
||||
|
||||
* Initial Release.
|
|
@ -1,479 +0,0 @@
|
|||
/*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
#include "compat/pgetopt.h"
|
||||
#include "common/xalloc.h"
|
||||
#include "cdb.h"
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "common/setup_after.h"
|
||||
|
||||
using namespace pvpgn;
|
||||
|
||||
#ifndef EPROTO
|
||||
# define EPROTO EINVAL
|
||||
#endif
|
||||
|
||||
static char *progname;
|
||||
|
||||
#define F_DUPMASK 0x000f
|
||||
#define F_WARNDUP 0x0100
|
||||
#define F_ERRDUP 0x0200
|
||||
#define F_MAP 0x1000 /* map format (or else CDB native format) */
|
||||
|
||||
static char *buf;
|
||||
static unsigned blen;
|
||||
|
||||
static void
|
||||
#ifdef __GNUC__
|
||||
__attribute__((noreturn,format(printf,2,3)))
|
||||
#endif
|
||||
error(int errnum, const char *fmt, ...)
|
||||
{
|
||||
if (fmt) {
|
||||
std::va_list ap;
|
||||
std::fprintf(stderr, "%s: ", progname);
|
||||
va_start(ap, fmt);
|
||||
std::vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
if (errnum)
|
||||
std::fprintf(stderr, ": %s\n", std::strerror(errnum));
|
||||
else {
|
||||
if (fmt) std::putc('\n', stderr);
|
||||
std::fprintf(stderr, "%s: try `%s -h' for help\n", progname, progname);
|
||||
}
|
||||
std::fflush(stderr);
|
||||
std::exit(errnum ? 111 : 2);
|
||||
}
|
||||
|
||||
static void allocbuf(unsigned len) {
|
||||
if (blen < len) {
|
||||
if (buf) buf = (char*)xrealloc(buf, len);
|
||||
else buf = (char*)xmalloc(len);
|
||||
if (!buf) error(ENOMEM, "unable to allocate %u bytes", len);
|
||||
blen = len;
|
||||
}
|
||||
}
|
||||
|
||||
static int qmode(char *dbname, char *key, int num, int flags)
|
||||
{
|
||||
struct cdb c;
|
||||
struct cdb_find cf;
|
||||
std::FILE *fd;
|
||||
int r;
|
||||
int n, found;
|
||||
|
||||
fd = std::fopen(dbname, "rb");
|
||||
if (fd == NULL || cdb_init(&c, fd) != 0)
|
||||
error(errno, "unable to open database `%s'", dbname);
|
||||
|
||||
r = cdb_findinit(&cf, &c, key, std::strlen(key));
|
||||
if (!r)
|
||||
return 100;
|
||||
else if (r < 0)
|
||||
error(errno, "%s", key);
|
||||
n = 0; found = 0;
|
||||
while((r = cdb_findnext(&cf)) > 0) {
|
||||
++n;
|
||||
if (num && num != n) continue;
|
||||
++found;
|
||||
allocbuf(cdb_datalen(&c));
|
||||
if (cdb_read(&c, buf, cdb_datalen(&c), cdb_datapos(&c)) != 0)
|
||||
error(errno, "unable to read value");
|
||||
std::fwrite(buf, 1, cdb_datalen(&c), stdout);
|
||||
if (flags & F_MAP) std::putchar('\n');
|
||||
if (num)
|
||||
break;
|
||||
}
|
||||
if (r < 0)
|
||||
error(0, "%s", key);
|
||||
return found ? 0 : 100;
|
||||
}
|
||||
|
||||
static void
|
||||
fget(std::FILE *f, unsigned char *b, unsigned len, unsigned *posp, unsigned limit)
|
||||
{
|
||||
if (posp && limit - *posp < len)
|
||||
error(EPROTO, "invalid database format");
|
||||
if (std::fread(b, 1, len, f) != len) {
|
||||
if (std::ferror(f)) error(errno, "unable to read");
|
||||
std::fprintf(stderr, "%s: unable to read: short file\n", progname);
|
||||
std::exit(2);
|
||||
}
|
||||
if (posp) *posp += len;
|
||||
}
|
||||
|
||||
static int
|
||||
fcpy(std::FILE *fi, std::FILE *fo, unsigned len, unsigned *posp, unsigned limit)
|
||||
{
|
||||
while(len > blen) {
|
||||
fget(fi, (unsigned char*)buf, blen, posp, limit);
|
||||
if (fo && std::fwrite(buf, 1, blen, fo) != blen) return -1;
|
||||
len -= blen;
|
||||
}
|
||||
if (len) {
|
||||
fget(fi, (unsigned char*)buf, len, posp, limit);
|
||||
if (fo && std::fwrite(buf, 1, len, fo) != len) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dmode(const char *dbname, char mode, int flags)
|
||||
{
|
||||
unsigned eod, klen, vlen;
|
||||
unsigned pos = 0;
|
||||
std::FILE *f;
|
||||
if (std::strcmp(dbname, "-") == 0)
|
||||
f = stdin;
|
||||
else if ((f = std::fopen(dbname, "rb")) == NULL)
|
||||
error(errno, "open %s", dbname);
|
||||
allocbuf(2048);
|
||||
fget(f, (unsigned char*)buf, 2048, &pos, 2048);
|
||||
eod = cdb_unpack((unsigned char*)buf);
|
||||
while(pos < eod) {
|
||||
fget(f, (unsigned char*)buf, 8, &pos, eod);
|
||||
klen = cdb_unpack((unsigned char*)buf);
|
||||
vlen = cdb_unpack((unsigned char*)(buf + 4));
|
||||
if (!(flags & F_MAP))
|
||||
if (std::printf(mode == 'd' ? "+%u,%u:" : "+%u:", klen, vlen) < 0) return -1;
|
||||
if (fcpy(f, stdout, klen, &pos, eod) != 0) return -1;
|
||||
if (mode == 'd')
|
||||
if (std::fputs(flags & F_MAP ? " " : "->", stdout) < 0)
|
||||
return -1;
|
||||
if (fcpy(f, mode == 'd' ? stdout : NULL, vlen, &pos, eod) != 0)
|
||||
return -1;
|
||||
if (std::putc('\n', stdout) < 0)
|
||||
return -1;
|
||||
}
|
||||
if (pos != eod)
|
||||
error(EPROTO, "invalid cdb file format");
|
||||
if (!(flags & F_MAP))
|
||||
if (std::putc('\n', stdout) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smode(const char *dbname) {
|
||||
std::FILE *f;
|
||||
unsigned pos, eod;
|
||||
unsigned cnt = 0;
|
||||
unsigned kmin = 0, kmax = 0, ktot = 0;
|
||||
unsigned vmin = 0, vmax = 0, vtot = 0;
|
||||
unsigned hmin = 0, hmax = 0, htot = 0, hcnt = 0;
|
||||
#define NDIST 11
|
||||
unsigned dist[NDIST];
|
||||
unsigned char toc[2048];
|
||||
unsigned k;
|
||||
|
||||
if (std::strcmp(dbname, "-") == 0)
|
||||
f = stdin;
|
||||
else if ((f = std::fopen(dbname, "rb")) == NULL)
|
||||
error(errno, "open %s", dbname);
|
||||
|
||||
pos = 0;
|
||||
fget(f, toc, 2048, &pos, 2048);
|
||||
|
||||
allocbuf(2048);
|
||||
|
||||
eod = cdb_unpack(toc);
|
||||
while(pos < eod) {
|
||||
unsigned klen, vlen;
|
||||
fget(f, (unsigned char*)buf, 8, &pos, eod);
|
||||
klen = cdb_unpack((unsigned char*)buf);
|
||||
vlen = cdb_unpack((unsigned char*)(buf + 4));
|
||||
fcpy(f, NULL, klen, &pos, eod);
|
||||
fcpy(f, NULL, vlen, &pos, eod);
|
||||
++cnt;
|
||||
ktot += klen;
|
||||
if (!kmin || kmin > klen) kmin = klen;
|
||||
if (kmax < klen) kmax = klen;
|
||||
vtot += vlen;
|
||||
if (!vmin || vmin > vlen) vmin = vlen;
|
||||
if (vmax < vlen) vmax = vlen;
|
||||
vlen += klen;
|
||||
}
|
||||
if (pos != eod) error(EPROTO, "invalid cdb file format");
|
||||
|
||||
for (k = 0; k < NDIST; ++k)
|
||||
dist[k] = 0;
|
||||
for (k = 0; k < 256; ++k) {
|
||||
unsigned i = cdb_unpack(toc + (k << 3));
|
||||
unsigned hlen = cdb_unpack(toc + (k << 3) + 4);
|
||||
if (i != pos) error(EPROTO, "invalid cdb hash table");
|
||||
if (!hlen) continue;
|
||||
for (i = 0; i < hlen; ++i) {
|
||||
unsigned h;
|
||||
fget(f, (unsigned char*)buf, 8, &pos, 0xffffffff);
|
||||
if (!cdb_unpack((unsigned char*)(buf + 4))) continue;
|
||||
h = (cdb_unpack((unsigned char*)buf) >> 8) % hlen;
|
||||
if (h == i) h = 0;
|
||||
else {
|
||||
if (h < i) h = i - h;
|
||||
else h = hlen - h + i;
|
||||
if (h >= NDIST) h = NDIST - 1;
|
||||
}
|
||||
++dist[h];
|
||||
}
|
||||
if (!hmin || hmin > hlen) hmin = hlen;
|
||||
if (hmax < hlen) hmax = hlen;
|
||||
htot += hlen;
|
||||
++hcnt;
|
||||
}
|
||||
std::printf("number of records: %u\n", cnt);
|
||||
std::printf("key min/avg/max length: %u/%u/%u\n",
|
||||
kmin, cnt ? (ktot + cnt / 2) / cnt : 0, kmax);
|
||||
std::printf("val min/avg/max length: %u/%u/%u\n",
|
||||
vmin, cnt ? (vtot + cnt / 2) / cnt : 0, vmax);
|
||||
std::printf("hash tables/entries/collisions: %u/%u/%u\n",
|
||||
hcnt, htot, cnt - dist[0]);
|
||||
std::printf("hash table min/avg/max length: %u/%u/%u\n",
|
||||
hmin, hcnt ? (htot + hcnt / 2) / hcnt : 0, hmax);
|
||||
std::printf("hash table distances:\n");
|
||||
for(k = 0; k < NDIST; ++k)
|
||||
std::printf(" %c%u: %6u %2u%%\n",
|
||||
k == NDIST - 1 ? '>' : 'd', k == NDIST - 1 ? k - 1 : k,
|
||||
dist[k], cnt ? dist[k] * 100 / cnt : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void badinput(const char *fn) {
|
||||
std::fprintf(stderr, "%s: %s: bad format\n", progname, fn);
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
static int getnum(std::FILE *f, unsigned *np, const char *fn) {
|
||||
unsigned n;
|
||||
int c = std::getc(f);
|
||||
if (c < '0' || c > '9') badinput(fn);
|
||||
n = c - '0';
|
||||
while((c = std::getc(f)) >= '0' && c <= '9') {
|
||||
c -= '0';
|
||||
if (0xffffffff / 10 - c < n) badinput(fn);
|
||||
n = n * 10 + c;
|
||||
}
|
||||
*np = n;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
addrec(struct cdb_make *cdbmp,
|
||||
char *key, unsigned klen,
|
||||
char *val, unsigned vlen,
|
||||
int flags)
|
||||
{
|
||||
int r = cdb_make_put(cdbmp, key, klen, val, vlen, flags & F_DUPMASK);
|
||||
if (r < 0)
|
||||
error(errno, "cdb_make_put");
|
||||
else if (r && (flags & F_WARNDUP)) {
|
||||
std::fprintf(stderr, "%s: key `", progname);
|
||||
std::fwrite(key, 1, klen, stderr);
|
||||
std::fputs("' duplicated\n", stderr);
|
||||
if (flags & F_ERRDUP)
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dofile_cdb(struct cdb_make *cdbmp, std::FILE *f, const char *fn, int flags)
|
||||
{
|
||||
unsigned klen, vlen;
|
||||
int c;
|
||||
while((c = std::getc(f)) == '+') {
|
||||
if ((c = getnum(f, &klen, fn)) != ',' ||
|
||||
(c = getnum(f, &vlen, fn)) != ':' ||
|
||||
0xffffffff - klen < vlen)
|
||||
badinput(fn);
|
||||
allocbuf(klen + vlen);
|
||||
fget(f, (unsigned char*)buf, klen, NULL, 0);
|
||||
if (std::getc(f) != '-' || std::getc(f) != '>') badinput(fn);
|
||||
fget(f, (unsigned char*)(buf + klen), vlen, NULL, 0);
|
||||
switch (std::getc(f))
|
||||
{
|
||||
case '\n': break;
|
||||
case '\r': if (std::getc(f)=='\n') break;
|
||||
default: badinput(fn);
|
||||
}
|
||||
addrec(cdbmp, buf, klen, buf + klen, vlen, flags);
|
||||
}
|
||||
switch (c)
|
||||
{
|
||||
case '\n': break;
|
||||
case '\r': if (std::getc(f)=='\n') break;
|
||||
default: badinput(fn);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dofile_ln(struct cdb_make *cdbmp, std::FILE *f, const char *fn, int flags)
|
||||
{
|
||||
char *k, *v;
|
||||
while(std::fgets(buf, blen, f) != NULL) {
|
||||
unsigned l = 0;
|
||||
for (;;) {
|
||||
l += std::strlen(buf + l);
|
||||
v = buf + l;
|
||||
if (v > buf && v[-1] == '\n') {
|
||||
v[-1] = '\0';
|
||||
break;
|
||||
}
|
||||
if (l < blen)
|
||||
allocbuf(l + 512);
|
||||
if (!std::fgets(buf + l, blen - l, f))
|
||||
break;
|
||||
}
|
||||
k = buf;
|
||||
while(*k == ' ' || *k == '\t') ++k;
|
||||
if (!*k || *k == '#')
|
||||
continue;
|
||||
v = k;
|
||||
while(*v && *v != ' ' && *v != '\t') ++v;
|
||||
if (*v) *v++ = '\0';
|
||||
while(*v == ' ' || *v == '\t') ++v;
|
||||
addrec(cdbmp, k, std::strlen(k), v, std::strlen(v), flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dofile(struct cdb_make *cdbmp, std::FILE *f, const char *fn, int flags)
|
||||
{
|
||||
if (flags & F_MAP)
|
||||
dofile_ln(cdbmp, f, fn, flags);
|
||||
else
|
||||
dofile_cdb(cdbmp, f, fn, flags);
|
||||
if (std::ferror(f))
|
||||
error(errno, "read error");
|
||||
}
|
||||
|
||||
static int
|
||||
cmode(char *dbname, char *tmpname, int argc, char **argv, int flags)
|
||||
{
|
||||
struct cdb_make cdb;
|
||||
std::FILE *fd;
|
||||
if (!tmpname) {
|
||||
tmpname = (char*)xmalloc(std::strlen(dbname) + 5);
|
||||
if (!tmpname)
|
||||
error(ENOMEM, "unable to allocate memory");
|
||||
std::strcat(std::strcpy(tmpname, dbname), ".tmp");
|
||||
}
|
||||
fd = std::fopen(tmpname, "w+b");
|
||||
if (fd == 0)
|
||||
error(errno, "unable to create %s", tmpname);
|
||||
cdb_make_start(&cdb, fd);
|
||||
allocbuf(4096);
|
||||
if (argc) {
|
||||
int i;
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (std::strcmp(argv[i], "-") == 0)
|
||||
dofile(&cdb, stdin, "(stdin)", flags);
|
||||
else {
|
||||
std::FILE *f = std::fopen(argv[i], "rb");
|
||||
if (!f)
|
||||
error(errno, "%s", argv[i]);
|
||||
dofile(&cdb, f, argv[i], flags);
|
||||
std::fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
dofile(&cdb, stdin, "(stdin)", flags);
|
||||
if (cdb_make_finish(&cdb) != 0)
|
||||
error(errno, "cdb_make_finish");
|
||||
std::fclose(fd);
|
||||
if (std::rename(tmpname, dbname) != 0)
|
||||
error(errno, "std::rename %s->%s", tmpname, dbname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
char mode = 0;
|
||||
char *tmpname = NULL;
|
||||
int flags = 0;
|
||||
int num = 0;
|
||||
int r;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
if ((progname = std::strrchr(argv[0], '/')) != NULL)
|
||||
argv[0] = ++progname;
|
||||
else
|
||||
progname = argv[0];
|
||||
|
||||
if (argc == 1)
|
||||
error(0, "no arguments given");
|
||||
|
||||
while((c = getopt(argc, argv, "qdlcsht:n:mwrue")) != EOF)
|
||||
switch(c) {
|
||||
case 'q': case 'd': case 'l': case 'c': case 's':
|
||||
if (mode && mode != c)
|
||||
error(0, "different modes of operation requested");
|
||||
mode = c;
|
||||
break;
|
||||
case 't': tmpname = optarg; break;
|
||||
case 'w': flags |= F_WARNDUP; break;
|
||||
case 'e': flags |= F_WARNDUP | F_ERRDUP; break;
|
||||
case 'r': flags = (flags & ~F_DUPMASK) | CDB_PUT_REPLACE; break;
|
||||
case 'u': flags = (flags & ~F_DUPMASK) | CDB_PUT_INSERT; break;
|
||||
case 'm': flags |= F_MAP; break;
|
||||
case 'n':
|
||||
if ((num = std::atoi(optarg)) <= 0)
|
||||
error(0, "invalid record number `%s'", optarg);
|
||||
break;
|
||||
case 'h':
|
||||
std::printf("\
|
||||
%s: Constant DataBase (CDB) tool. Usage is:\n\
|
||||
query: %s -q [-m] [-n recno|-a] cdbfile key\n\
|
||||
dump: %s -d [-m] [cdbfile|-]\n\
|
||||
list: %s -l [-m] [cdbfile|-]\n\
|
||||
create: %s -c [-m] [-wrue] [-t tempfile] cdbfile [infile...]\n\
|
||||
stats: %s -s [cdbfile|-]\n\
|
||||
help: %s -h\n\
|
||||
", progname, progname, progname, progname, progname, progname, progname);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
error(0, NULL);
|
||||
}
|
||||
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
switch(mode) {
|
||||
case 'q':
|
||||
if (argc < 2) error(0, "no database or key to query specified");
|
||||
if (argc > 2) error(0, "extra arguments in command line");
|
||||
r = qmode(argv[0], argv[1], num, flags);
|
||||
break;
|
||||
case 'c':
|
||||
if (!argc) error(0, "no database name specified");
|
||||
if ((flags & F_WARNDUP) && !(flags & F_DUPMASK))
|
||||
flags |= CDB_PUT_WARN;
|
||||
r = cmode(argv[0], tmpname, argc - 1, argv + 1, flags);
|
||||
break;
|
||||
case 'd':
|
||||
case 'l':
|
||||
if (argc > 1) error(0, "extra arguments for dump/list");
|
||||
r = dmode(argc ? argv[0] : "-", mode, flags);
|
||||
break;
|
||||
case 's':
|
||||
if (argc > 1) error(0, "extra argument(s) for stats");
|
||||
r = smode(argc ? argv[0] : "-");
|
||||
break;
|
||||
default:
|
||||
error(0, "no -q, -c, -d, -l or -s option specified");
|
||||
}
|
||||
if (r < 0 || std::fflush(stdout) < 0)
|
||||
error(errno, "unable to write: %d", c);
|
||||
return r;
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/* public cdb include file
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
#include <cstdio>
|
||||
|
||||
#ifndef TINYCDB_VERSION
|
||||
#define TINYCDB_VERSION 0.74
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
typedef unsigned int cdbi_t; /* compatibility */
|
||||
|
||||
/* common routines */
|
||||
unsigned cdb_hash(const void *buf, unsigned len);
|
||||
unsigned cdb_unpack(const unsigned char buf[4]);
|
||||
void cdb_pack(unsigned num, unsigned char buf[4]);
|
||||
|
||||
struct cdb {
|
||||
std::FILE *cdb_fd; /* file descriptor */
|
||||
/* private members */
|
||||
unsigned cdb_fsize; /* datafile size */
|
||||
unsigned cdb_dend; /* end of data ptr */
|
||||
const unsigned char *cdb_mem; /* mmap'ed file memory */
|
||||
unsigned cdb_vpos, cdb_vlen; /* found data */
|
||||
unsigned cdb_kpos, cdb_klen; /* found key */
|
||||
};
|
||||
|
||||
#define CDB_STATIC_INIT {0,0,0,0,0,0,0,0}
|
||||
|
||||
#define cdb_datapos(c) ((c)->cdb_vpos)
|
||||
#define cdb_datalen(c) ((c)->cdb_vlen)
|
||||
#define cdb_keypos(c) ((c)->cdb_kpos)
|
||||
#define cdb_keylen(c) ((c)->cdb_klen)
|
||||
#define cdb_fileno(c) ((c)->cdb_fd)
|
||||
|
||||
int cdb_init(struct cdb *cdbp, std::FILE *fd);
|
||||
void cdb_free(struct cdb *cdbp);
|
||||
|
||||
int cdb_read(const struct cdb *cdbp,
|
||||
void *buf, unsigned len, unsigned pos);
|
||||
#define cdb_readdata(cdbp, buf) \
|
||||
cdb_read((cdbp), (buf), cdb_datalen(cdbp), cdb_datapos(cdbp))
|
||||
#define cdb_readkey(cdbp, buf) \
|
||||
cdb_read((cdbp), (buf), cdb_keylen(cdbp), cdb_keypos(cdbp))
|
||||
|
||||
const void *cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos);
|
||||
#define cdb_getdata(cdbp) \
|
||||
cdb_get((cdbp), cdb_datalen(cdbp), cdb_datapos(cdbp))
|
||||
#define cdb_getkey(cdbp) \
|
||||
cdb_get((cdbp), cdb_keylen(cdbp), cdb_keypos(cdbp))
|
||||
|
||||
int cdb_find(struct cdb *cdbp, const void *key, unsigned klen);
|
||||
|
||||
struct cdb_find {
|
||||
struct cdb *cdb_cdbp;
|
||||
unsigned cdb_hval;
|
||||
const unsigned char *cdb_htp, *cdb_htab, *cdb_htend;
|
||||
unsigned cdb_httodo;
|
||||
const void *cdb_key;
|
||||
unsigned cdb_klen;
|
||||
};
|
||||
|
||||
int cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
|
||||
const void *key, unsigned klen);
|
||||
int cdb_findnext(struct cdb_find *cdbfp);
|
||||
|
||||
#define cdb_seqinit(cptr, cdbp) ((*(cptr))=2048)
|
||||
int cdb_seqnext(unsigned *cptr, struct cdb *cdbp);
|
||||
|
||||
/* old simple interface */
|
||||
/* open file using standard routine, then: */
|
||||
int cdb_seek(std::FILE *fd, const void *key, unsigned klen, unsigned *dlenp);
|
||||
int cdb_bread(std::FILE *fd, void *buf, int len);
|
||||
|
||||
/* cdb_make */
|
||||
|
||||
struct cdb_make {
|
||||
std::FILE *cdb_fd; /* file descriptor */
|
||||
/* private */
|
||||
unsigned cdb_dpos; /* data position so far */
|
||||
unsigned cdb_rcnt; /* record count so far */
|
||||
char cdb_buf[4096]; /* write buffer */
|
||||
char *cdb_bpos; /* current buf position */
|
||||
struct cdb_rl *cdb_rec[256]; /* list of arrays of record infos */
|
||||
};
|
||||
|
||||
int cdb_make_start(struct cdb_make *cdbmp, std::FILE *fd);
|
||||
int cdb_make_add(struct cdb_make *cdbmp,
|
||||
const void *key, unsigned klen,
|
||||
const void *val, unsigned vlen);
|
||||
int cdb_make_exists(struct cdb_make *cdbmp,
|
||||
const void *key, unsigned klen);
|
||||
int cdb_make_put(struct cdb_make *cdbmp,
|
||||
const void *key, unsigned klen,
|
||||
const void *val, unsigned vlen,
|
||||
int flag);
|
||||
#define CDB_PUT_ADD 0 /* add unconditionnaly, like cdb_make_add() */
|
||||
#define CDB_PUT_REPLACE 1 /* replace: do not place to index OLD record */
|
||||
#define CDB_PUT_INSERT 2 /* add only if not already exists */
|
||||
#define CDB_PUT_WARN 3 /* add unconditionally but ret. 1 if exists */
|
||||
int cdb_make_finish(struct cdb_make *cdbmp);
|
||||
|
||||
}
|
||||
|
||||
#endif /* include guard */
|
|
@ -1,85 +0,0 @@
|
|||
/* cdb_find routine
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
int
|
||||
cdb_find(struct cdb *cdbp, const void *key, unsigned klen)
|
||||
{
|
||||
const unsigned char *htp; /* hash table pointer */
|
||||
const unsigned char *htab; /* hash table */
|
||||
const unsigned char *htend; /* end of hash table */
|
||||
unsigned httodo; /* ht bytes left to look */
|
||||
unsigned pos, n;
|
||||
|
||||
unsigned hval;
|
||||
|
||||
if (klen >= cdbp->cdb_dend) /* if key size is too large */
|
||||
return 0;
|
||||
|
||||
hval = cdb_hash(key, klen);
|
||||
|
||||
/* find (pos,n) hash table to use */
|
||||
/* first 2048 bytes (toc) are always available */
|
||||
/* (hval % 256) * 8 */
|
||||
htp = cdbp->cdb_mem + ((hval << 3) & 2047); /* index in toc (256x8) */
|
||||
n = cdb_unpack(htp + 4); /* table size */
|
||||
if (!n) /* empty table */
|
||||
return 0; /* not found */
|
||||
httodo = n << 3; /* bytes of htab to lookup */
|
||||
pos = cdb_unpack(htp); /* htab position */
|
||||
if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */
|
||||
|| pos < cdbp->cdb_dend /* is htab inside data section ? */
|
||||
|| pos > cdbp->cdb_fsize /* htab start within file ? */
|
||||
|| httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */
|
||||
return errno = EPROTO, -1;
|
||||
|
||||
htab = cdbp->cdb_mem + pos; /* htab pointer */
|
||||
htend = htab + httodo; /* after end of htab */
|
||||
/* htab starting position: rest of hval modulo htsize, 8bytes per elt */
|
||||
htp = htab + (((hval >> 8) % n) << 3);
|
||||
|
||||
for(;;) {
|
||||
pos = cdb_unpack(htp + 4); /* record position */
|
||||
if (!pos)
|
||||
return 0;
|
||||
if (cdb_unpack(htp) == hval) {
|
||||
if (pos > cdbp->cdb_dend - 8) /* key+val lengths */
|
||||
return errno = EPROTO, -1;
|
||||
if (cdb_unpack(cdbp->cdb_mem + pos) == klen) {
|
||||
if (cdbp->cdb_dend - klen < pos + 8)
|
||||
return errno = EPROTO, -1;
|
||||
if (std::memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) {
|
||||
n = cdb_unpack(cdbp->cdb_mem + pos + 4);
|
||||
pos += 8;
|
||||
if (cdbp->cdb_dend < n || cdbp->cdb_dend - n < pos + klen)
|
||||
return errno = EPROTO, -1;
|
||||
cdbp->cdb_kpos = pos;
|
||||
cdbp->cdb_klen = klen;
|
||||
cdbp->cdb_vpos = pos + klen;
|
||||
cdbp->cdb_vlen = n;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
httodo -= 8;
|
||||
if (!httodo)
|
||||
return 0;
|
||||
if ((htp += 8) >= htend)
|
||||
htp = htab;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
/* sequential cdb_find routines
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
/* see cdb_find.c for comments */
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
int
|
||||
cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
|
||||
const void *key, unsigned klen)
|
||||
{
|
||||
unsigned n, pos;
|
||||
|
||||
cdbfp->cdb_cdbp = cdbp;
|
||||
cdbfp->cdb_key = key;
|
||||
cdbfp->cdb_klen = klen;
|
||||
cdbfp->cdb_hval = cdb_hash(key, klen);
|
||||
|
||||
cdbfp->cdb_htp = cdbp->cdb_mem + ((cdbfp->cdb_hval << 3) & 2047);
|
||||
n = cdb_unpack(cdbfp->cdb_htp + 4);
|
||||
cdbfp->cdb_httodo = n << 3;
|
||||
if (!n)
|
||||
return 0;
|
||||
pos = cdb_unpack(cdbfp->cdb_htp);
|
||||
if (n > (cdbp->cdb_fsize >> 3)
|
||||
|| pos < cdbp->cdb_dend
|
||||
|| pos > cdbp->cdb_fsize
|
||||
|| cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
|
||||
return errno = EPROTO, -1;
|
||||
|
||||
cdbfp->cdb_htab = cdbp->cdb_mem + pos;
|
||||
cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
|
||||
cdbfp->cdb_htp = cdbfp->cdb_htab + (((cdbfp->cdb_hval >> 8) % n) << 3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cdb_findnext(struct cdb_find *cdbfp) {
|
||||
struct cdb *cdbp = cdbfp->cdb_cdbp;
|
||||
unsigned pos, n;
|
||||
unsigned klen = cdbfp->cdb_klen;
|
||||
|
||||
while(cdbfp->cdb_httodo) {
|
||||
pos = cdb_unpack(cdbfp->cdb_htp + 4);
|
||||
if (!pos)
|
||||
return 0;
|
||||
n = cdb_unpack(cdbfp->cdb_htp) == cdbfp->cdb_hval;
|
||||
if ((cdbfp->cdb_htp += 8) >= cdbfp->cdb_htend)
|
||||
cdbfp->cdb_htp = cdbfp->cdb_htab;
|
||||
cdbfp->cdb_httodo -= 8;
|
||||
if (n) {
|
||||
if (pos > cdbp->cdb_fsize - 8)
|
||||
return errno = EPROTO, -1;
|
||||
if (cdb_unpack(cdbp->cdb_mem + pos) == klen) {
|
||||
if (cdbp->cdb_fsize - klen < pos + 8)
|
||||
return errno = EPROTO, -1;
|
||||
if (std::memcmp(cdbfp->cdb_key,
|
||||
cdbp->cdb_mem + pos + 8, klen) == 0) {
|
||||
n = cdb_unpack(cdbp->cdb_mem + pos + 4);
|
||||
pos += 8;
|
||||
if (cdbp->cdb_fsize < n ||
|
||||
cdbp->cdb_fsize - n < pos + klen)
|
||||
return errno = EPROTO, -1;
|
||||
cdbp->cdb_kpos = pos;
|
||||
cdbp->cdb_klen = klen;
|
||||
cdbp->cdb_vpos = pos + klen;
|
||||
cdbp->cdb_vlen = n;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/* cdb hashing routine
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include "cdb.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
unsigned
|
||||
cdb_hash(const void *buf, unsigned len)
|
||||
{
|
||||
register const unsigned char *p = (const unsigned char *)buf;
|
||||
register const unsigned char *end = p + len;
|
||||
register unsigned hash = 5381; /* start value */
|
||||
while (p < end)
|
||||
hash = (hash + (hash << 5)) ^ *p++;
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/* cdb_init, cdb_free and cdb_read routines
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
#include "compat/mmap.h"
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
int
|
||||
cdb_init(struct cdb *cdbp, std::FILE *fd)
|
||||
{
|
||||
unsigned char *mem;
|
||||
unsigned fsize, dend;
|
||||
|
||||
/* get file size */
|
||||
if (std::fseek(fd, 0, SEEK_END))
|
||||
return -1;
|
||||
fsize = (unsigned)(std::ftell(fd));
|
||||
std::rewind(fd);
|
||||
/* trivial sanity check: at least toc should be here */
|
||||
if (fsize < 2048)
|
||||
return errno = EPROTO, -1;
|
||||
|
||||
/* memory-map file */
|
||||
if ((mem = (unsigned char*)pmmap(NULL, fsize, PROT_READ, MAP_SHARED, fileno(fd), 0)) ==
|
||||
(unsigned char *)-1)
|
||||
return -1;
|
||||
|
||||
cdbp->cdb_fd = fd;
|
||||
cdbp->cdb_fsize = fsize;
|
||||
cdbp->cdb_mem = mem;
|
||||
|
||||
#if 0
|
||||
/* XXX don't know well about madvise syscall -- is it legal
|
||||
to set different options for parts of one mmap() region?
|
||||
There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
|
||||
*/
|
||||
#ifdef MADV_RANDOM
|
||||
/* set madvise() parameters. Ignore errors for now if system
|
||||
doesn't support it */
|
||||
madvise(mem, 2048, MADV_WILLNEED);
|
||||
madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
|
||||
cdbp->cdb_kpos = cdbp->cdb_klen = 0;
|
||||
dend = cdb_unpack(mem);
|
||||
if (dend < 2048) dend = 2048;
|
||||
else if (dend >= fsize) dend = fsize;
|
||||
cdbp->cdb_dend = dend;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cdb_free(struct cdb *cdbp)
|
||||
{
|
||||
if (cdbp->cdb_mem) {
|
||||
pmunmap((void*)cdbp->cdb_mem, cdbp->cdb_fsize);
|
||||
cdbp->cdb_mem = NULL;
|
||||
}
|
||||
cdbp->cdb_fsize = 0;
|
||||
}
|
||||
|
||||
const void *
|
||||
cdb_get(const struct cdb *cdbp, unsigned len, unsigned pos)
|
||||
{
|
||||
if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
|
||||
errno = EPROTO;
|
||||
return NULL;
|
||||
}
|
||||
return cdbp->cdb_mem + pos;
|
||||
}
|
||||
|
||||
int
|
||||
cdb_read(const struct cdb *cdbp, void *buf, unsigned len, unsigned pos)
|
||||
{
|
||||
const void *data = cdb_get(cdbp, len, pos);
|
||||
if (!data) return -1;
|
||||
std::memcpy(buf, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/* internal cdb library declarations
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "cdb.h"
|
||||
|
||||
#ifndef EPROTO
|
||||
# define EPROTO EINVAL
|
||||
#endif
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
struct cdb_rec {
|
||||
cdbi_t hval;
|
||||
cdbi_t rpos;
|
||||
};
|
||||
|
||||
struct cdb_rl {
|
||||
struct cdb_rl *next;
|
||||
cdbi_t cnt;
|
||||
struct cdb_rec rec[254];
|
||||
};
|
||||
|
||||
int _cdb_make_find(struct cdb_make *cdbmp,
|
||||
const void *key, cdbi_t klen, cdbi_t hval,
|
||||
struct cdb_rl **rlp);
|
||||
int _cdb_make_write(struct cdb_make *cdbmp,
|
||||
const char *ptr, cdbi_t len);
|
||||
|
||||
}
|
|
@ -1,180 +0,0 @@
|
|||
/* basic cdb creation routines
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
#include "common/xalloc.h"
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
void
|
||||
cdb_pack(unsigned num, unsigned char buf[4])
|
||||
{
|
||||
buf[0] = num & 255; num >>= 8;
|
||||
buf[1] = num & 255; num >>= 8;
|
||||
buf[2] = num & 255;
|
||||
buf[3] = num >> 8;
|
||||
}
|
||||
|
||||
int
|
||||
cdb_make_start(struct cdb_make *cdbmp, std::FILE *fd)
|
||||
{
|
||||
std::memset(cdbmp, 0, sizeof(*cdbmp));
|
||||
cdbmp->cdb_fd = fd;
|
||||
cdbmp->cdb_dpos = 2048;
|
||||
cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ewrite(std::FILE *fd, const char *buf, int len)
|
||||
{
|
||||
while(len) {
|
||||
int l = std::fwrite(buf, 1, len, fd);
|
||||
if (l < 0 && errno != EINTR)
|
||||
return -1;
|
||||
len -= l;
|
||||
buf += l;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_cdb_make_write(struct cdb_make *cdbmp, const char *ptr, unsigned len)
|
||||
{
|
||||
unsigned l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf);
|
||||
cdbmp->cdb_dpos += len;
|
||||
if (len > l) {
|
||||
std::memcpy(cdbmp->cdb_bpos, ptr, l);
|
||||
if (ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, sizeof(cdbmp->cdb_buf)) < 0)
|
||||
return -1;
|
||||
ptr += l; len -= l;
|
||||
l = len / sizeof(cdbmp->cdb_buf);
|
||||
if (l) {
|
||||
l *= sizeof(cdbmp->cdb_buf);
|
||||
if (ewrite(cdbmp->cdb_fd, ptr, l) < 0)
|
||||
return -1;
|
||||
ptr += l; len -= l;
|
||||
}
|
||||
cdbmp->cdb_bpos = cdbmp->cdb_buf;
|
||||
}
|
||||
if (len) {
|
||||
std::memcpy(cdbmp->cdb_bpos, ptr, len);
|
||||
cdbmp->cdb_bpos += len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cdb_make_finish_internal(struct cdb_make *cdbmp)
|
||||
{
|
||||
unsigned hcnt[256]; /* hash table counts */
|
||||
unsigned hpos[256]; /* hash table positions */
|
||||
struct cdb_rec *htab;
|
||||
unsigned char *p;
|
||||
struct cdb_rl *rl;
|
||||
unsigned hsize;
|
||||
unsigned t, i;
|
||||
|
||||
if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt)
|
||||
return errno = ENOMEM, -1;
|
||||
|
||||
/* count htab sizes and reorder reclists */
|
||||
hsize = 0;
|
||||
for (t = 0; t < 256; ++t) {
|
||||
struct cdb_rl *rlt = NULL;
|
||||
i = 0;
|
||||
rl = cdbmp->cdb_rec[t];
|
||||
while(rl) {
|
||||
struct cdb_rl *rln = rl->next;
|
||||
rl->next = rlt;
|
||||
rlt = rl;
|
||||
i += rl->cnt;
|
||||
rl = rln;
|
||||
}
|
||||
cdbmp->cdb_rec[t] = rlt;
|
||||
if (hsize < (hcnt[t] = i << 1))
|
||||
hsize = hcnt[t];
|
||||
}
|
||||
|
||||
/* allocate memory to hold max htable */
|
||||
htab = (struct cdb_rec*)xmalloc((hsize + 2) * sizeof(struct cdb_rec));
|
||||
if (!htab)
|
||||
return errno = ENOENT, -1;
|
||||
p = (unsigned char *)htab;
|
||||
htab += 2;
|
||||
|
||||
/* build hash tables */
|
||||
for (t = 0; t < 256; ++t) {
|
||||
unsigned len, hi;
|
||||
hpos[t] = cdbmp->cdb_dpos;
|
||||
if ((len = hcnt[t]) == 0)
|
||||
continue;
|
||||
for (i = 0; i < len; ++i)
|
||||
htab[i].hval = htab[i].rpos = 0;
|
||||
for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next)
|
||||
for (i = 0; i < rl->cnt; ++i) {
|
||||
hi = (rl->rec[i].hval >> 8) % len;
|
||||
while(htab[hi].rpos)
|
||||
if (++hi == len)
|
||||
hi = 0;
|
||||
htab[hi] = rl->rec[i];
|
||||
}
|
||||
for (i = 0; i < len; ++i) {
|
||||
cdb_pack(htab[i].hval, p + (i << 3));
|
||||
cdb_pack(htab[i].rpos, p + (i << 3) + 4);
|
||||
}
|
||||
if (_cdb_make_write(cdbmp, (char*)p, len << 3) < 0) {
|
||||
xfree(p);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
xfree(p);
|
||||
if (cdbmp->cdb_bpos != cdbmp->cdb_buf &&
|
||||
ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf,
|
||||
cdbmp->cdb_bpos - cdbmp->cdb_buf) != 0)
|
||||
return -1;
|
||||
p = (unsigned char*)cdbmp->cdb_buf;
|
||||
for (t = 0; t < 256; ++t) {
|
||||
cdb_pack(hpos[t], p + (t << 3));
|
||||
cdb_pack(hcnt[t], p + (t << 3) + 4);
|
||||
}
|
||||
std::rewind(cdbmp->cdb_fd);
|
||||
if (ewrite(cdbmp->cdb_fd, (char*)p, 2048) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cdb_make_free(struct cdb_make *cdbmp)
|
||||
{
|
||||
unsigned t;
|
||||
for(t = 0; t < 256; ++t) {
|
||||
struct cdb_rl *rl = cdbmp->cdb_rec[t];
|
||||
while(rl) {
|
||||
struct cdb_rl *tm = rl;
|
||||
rl = rl->next;
|
||||
xfree(tm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cdb_make_finish(struct cdb_make *cdbmp)
|
||||
{
|
||||
int r = cdb_make_finish_internal(cdbmp);
|
||||
cdb_make_free(cdbmp);
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/* basic cdb_make_add routine
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cerrno>
|
||||
|
||||
#include "common/xalloc.h"
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
int
|
||||
cdb_make_add(struct cdb_make *cdbmp,
|
||||
const void *key, unsigned klen,
|
||||
const void *val, unsigned vlen)
|
||||
{
|
||||
unsigned char rlen[8];
|
||||
unsigned hval;
|
||||
struct cdb_rl *rl;
|
||||
if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
|
||||
vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8))
|
||||
return errno = ENOMEM, -1;
|
||||
hval = cdb_hash(key, klen);
|
||||
rl = cdbmp->cdb_rec[hval&255];
|
||||
if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
|
||||
rl = (struct cdb_rl*)xmalloc(sizeof(struct cdb_rl));
|
||||
if (!rl)
|
||||
return errno = ENOMEM, -1;
|
||||
rl->cnt = 0;
|
||||
rl->next = cdbmp->cdb_rec[hval&255];
|
||||
cdbmp->cdb_rec[hval&255] = rl;
|
||||
}
|
||||
rl->rec[rl->cnt].hval = hval;
|
||||
rl->rec[rl->cnt].rpos = cdbmp->cdb_dpos;
|
||||
++rl->cnt;
|
||||
++cdbmp->cdb_rcnt;
|
||||
cdb_pack(klen, rlen);
|
||||
cdb_pack(vlen, rlen + 4);
|
||||
if (_cdb_make_write(cdbmp, (char*)rlen, 8) < 0 ||
|
||||
_cdb_make_write(cdbmp, (char*)key, klen) < 0 ||
|
||||
_cdb_make_write(cdbmp, (char*)val, vlen) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/* routines to search in in-progress cdb file
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
static int
|
||||
match(std::FILE *fd, unsigned pos, const char *key, unsigned klen)
|
||||
{
|
||||
unsigned char buf[64]; /*XXX cdb_buf may be used here instead */
|
||||
if (std::fseek(fd, pos, SEEK_SET) || std::fread(buf, 1, 8, fd) != 8)
|
||||
return -1;
|
||||
if (cdb_unpack(buf) != klen)
|
||||
return 0;
|
||||
|
||||
while(klen > sizeof(buf)) {
|
||||
if (std::fread(buf, 1, sizeof(buf), fd) != sizeof(buf))
|
||||
return -1;
|
||||
if (std::memcmp(buf, key, sizeof(buf)) != 0)
|
||||
return 0;
|
||||
key += sizeof(buf);
|
||||
klen -= sizeof(buf);
|
||||
}
|
||||
if (klen) {
|
||||
if (std::fread(buf, 1, klen, fd) != klen)
|
||||
return -1;
|
||||
if (std::memcmp(buf, key, klen) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
_cdb_make_find(struct cdb_make *cdbmp,
|
||||
const void *key, unsigned klen, unsigned hval,
|
||||
struct cdb_rl **rlp)
|
||||
{
|
||||
struct cdb_rl *rl = cdbmp->cdb_rec[hval&255];
|
||||
int r, i;
|
||||
int seeked = 0;
|
||||
while(rl) {
|
||||
for(i = rl->cnt - 1; i >= 0; --i) { /* search backward */
|
||||
if (rl->rec[i].hval != hval)
|
||||
continue;
|
||||
/*XXX this explicit flush may be unnecessary having
|
||||
* smarter match() that looks to cdb_buf too, but
|
||||
* most of a time here spent in finding hash values
|
||||
* (above), not keys */
|
||||
if (cdbmp->cdb_bpos != cdbmp->cdb_buf) {
|
||||
if (std::fwrite(cdbmp->cdb_buf, 1,
|
||||
cdbmp->cdb_bpos - cdbmp->cdb_buf, cdbmp->cdb_fd) < 0)
|
||||
return -1;
|
||||
cdbmp->cdb_bpos = cdbmp->cdb_buf;
|
||||
}
|
||||
seeked = 1;
|
||||
r = match(cdbmp->cdb_fd, rl->rec[i].rpos, (char*)key, klen);
|
||||
if (!r)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return -1;
|
||||
if (std::fseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET))
|
||||
return -1;
|
||||
if (rlp)
|
||||
*rlp = rl;
|
||||
return i + 1;
|
||||
}
|
||||
rl = rl->next;
|
||||
}
|
||||
if (seeked && std::fseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cdb_make_exists(struct cdb_make *cdbmp,
|
||||
const void *key, unsigned klen)
|
||||
{
|
||||
return _cdb_make_find(cdbmp, key, klen, cdb_hash(key, klen), NULL);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/* "advanced" cdb_make_put routine
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cerrno>
|
||||
#include "common/xalloc.h"
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
int
|
||||
cdb_make_put(struct cdb_make *cdbmp,
|
||||
const void *key, unsigned klen,
|
||||
const void *val, unsigned vlen,
|
||||
int flags)
|
||||
{
|
||||
unsigned char rlen[8];
|
||||
unsigned hval = cdb_hash(key, klen);
|
||||
struct cdb_rl *rl;
|
||||
int c, r;
|
||||
|
||||
switch(flags) {
|
||||
case CDB_PUT_REPLACE:
|
||||
case CDB_PUT_INSERT:
|
||||
case CDB_PUT_WARN:
|
||||
c = _cdb_make_find(cdbmp, key, klen, hval, &rl);
|
||||
if (c < 0)
|
||||
return -1;
|
||||
if (c) {
|
||||
if (flags == CDB_PUT_INSERT)
|
||||
return errno = EEXIST, 1;
|
||||
else if (flags == CDB_PUT_REPLACE) {
|
||||
--c;
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
r = 1;
|
||||
}
|
||||
/* fall */
|
||||
|
||||
case CDB_PUT_ADD:
|
||||
rl = cdbmp->cdb_rec[hval&255];
|
||||
if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
|
||||
rl = (struct cdb_rl*)xmalloc(sizeof(struct cdb_rl));
|
||||
if (!rl)
|
||||
return errno = ENOMEM, -1;
|
||||
rl->cnt = 0;
|
||||
rl->next = cdbmp->cdb_rec[hval&255];
|
||||
cdbmp->cdb_rec[hval&255] = rl;
|
||||
}
|
||||
c = rl->cnt;
|
||||
r = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return errno = EINVAL, -1;
|
||||
}
|
||||
|
||||
if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
|
||||
vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8))
|
||||
return errno = ENOMEM, -1;
|
||||
rl->rec[c].hval = hval;
|
||||
rl->rec[c].rpos = cdbmp->cdb_dpos;
|
||||
if ((unsigned)c == rl->cnt) {
|
||||
++rl->cnt;
|
||||
++cdbmp->cdb_rcnt;
|
||||
}
|
||||
cdb_pack(klen, rlen);
|
||||
cdb_pack(vlen, rlen + 4);
|
||||
if (_cdb_make_write(cdbmp, (char*)rlen, 8) < 0 ||
|
||||
_cdb_make_write(cdbmp, (char*)key, klen) < 0 ||
|
||||
_cdb_make_write(cdbmp, (char*)val, vlen) < 0)
|
||||
return -1;
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/* old interface for reading cdb file
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cerrno>
|
||||
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
/* read a chunk from file, ignoring interrupts (EINTR) */
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
int
|
||||
cdb_bread(std::FILE *fd, void *buf, int len)
|
||||
{
|
||||
int l;
|
||||
while(len > 0) {
|
||||
do l = std::fread(buf, 1, len, fd);
|
||||
while(l < 0 && errno == EINTR);
|
||||
if (l <= 0) {
|
||||
if (!l)
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
buf = (char*)buf + l;
|
||||
len -= l;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find a given key in cdb file, seek a file pointer to it's value and
|
||||
place data length to *dlenp. */
|
||||
|
||||
int
|
||||
cdb_seek(std::FILE *fd, const void *key, unsigned klen, unsigned *dlenp)
|
||||
{
|
||||
unsigned htstart; /* hash table start position */
|
||||
unsigned htsize; /* number of elements in a hash table */
|
||||
unsigned httodo; /* hash table elements left to look */
|
||||
unsigned hti; /* hash table index */
|
||||
unsigned pos; /* position in a file */
|
||||
unsigned hval; /* key's hash value */
|
||||
unsigned char rbuf[64]; /* read buffer */
|
||||
int needseek = 1; /* if we should seek to a hash slot */
|
||||
|
||||
hval = cdb_hash(key, klen);
|
||||
pos = (hval & 0xff) << 3; /* position in TOC */
|
||||
/* read the hash table parameters */
|
||||
if (std::fseek(fd, pos, SEEK_SET) || cdb_bread(fd, rbuf, 8) < 0)
|
||||
return -1;
|
||||
if ((htsize = cdb_unpack(rbuf + 4)) == 0)
|
||||
return 0;
|
||||
hti = (hval >> 8) % htsize; /* start position in hash table */
|
||||
httodo = htsize;
|
||||
htstart = cdb_unpack(rbuf);
|
||||
|
||||
for(;;) {
|
||||
if (needseek && std::fseek(fd, htstart + (hti << 3), SEEK_SET))
|
||||
return -1;
|
||||
if (cdb_bread(fd, rbuf, 8) < 0)
|
||||
return -1;
|
||||
if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */
|
||||
return 0;
|
||||
|
||||
if (cdb_unpack(rbuf) != hval) /* hash value not matched */
|
||||
needseek = 0;
|
||||
else { /* hash value matched */
|
||||
if (std::fseek(fd, pos, SEEK_SET) || cdb_bread(fd, rbuf, 8) < 0)
|
||||
return -1;
|
||||
if (cdb_unpack(rbuf) == klen) { /* key length matches */
|
||||
/* read the key from file and compare with wanted */
|
||||
unsigned l = klen, c;
|
||||
const char *k = (const char*)key;
|
||||
if (*dlenp)
|
||||
*dlenp = cdb_unpack(rbuf + 4); /* save value length */
|
||||
for(;;) {
|
||||
if (!l) /* the whole key read and matches, return */
|
||||
return 1;
|
||||
c = l > sizeof(rbuf) ? sizeof(rbuf) : l;
|
||||
if (cdb_bread(fd, rbuf, c) < 0)
|
||||
return -1;
|
||||
if (std::memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */
|
||||
break;
|
||||
k += c; l -= c;
|
||||
}
|
||||
}
|
||||
needseek = 1; /* we're looked to other place, should seek back */
|
||||
}
|
||||
if (!--httodo)
|
||||
return 0;
|
||||
if (++hti == htsize) {
|
||||
hti = 0;
|
||||
needseek = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/* sequential record retrieval routines
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include <cerrno>
|
||||
|
||||
#include "cdb_int.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
int
|
||||
cdb_seqnext(unsigned *cptr, struct cdb *cdbp) {
|
||||
unsigned klen, vlen;
|
||||
unsigned pos = *cptr;
|
||||
unsigned dend = cdbp->cdb_dend;
|
||||
const unsigned char *mem = cdbp->cdb_mem;
|
||||
if (pos > dend - 8)
|
||||
return 0;
|
||||
klen = cdb_unpack(mem + pos);
|
||||
vlen = cdb_unpack(mem + pos + 4);
|
||||
pos += 8;
|
||||
if (dend - klen < pos || dend - vlen < pos + klen)
|
||||
return errno = EPROTO, -1;
|
||||
cdbp->cdb_kpos = pos;
|
||||
cdbp->cdb_klen = klen;
|
||||
cdbp->cdb_vpos = pos + klen;
|
||||
cdbp->cdb_vlen = vlen;
|
||||
*cptr = pos + klen + vlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/* unpack 32bit integer
|
||||
*
|
||||
* This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include "common/setup_before.h"
|
||||
#include "cdb.h"
|
||||
#include "common/setup_after.h"
|
||||
|
||||
namespace pvpgn
|
||||
{
|
||||
|
||||
unsigned
|
||||
cdb_unpack(const unsigned char buf[4])
|
||||
{
|
||||
unsigned n = buf[3];
|
||||
n <<= 8; n |= buf[2];
|
||||
n <<= 8; n |= buf[1];
|
||||
n <<= 8; n |= buf[0];
|
||||
return n;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue