Thread: [srvx-commits] CVS: services/src chanserv.c,1.262,1.263 checkdb.c,1.7,1.8 gline.c,1.27,1.28 helpserv
Brought to you by:
entrope
|
From: Adrian D. <sai...@us...> - 2002-08-05 03:20:27
|
Update of /cvsroot/srvx/services/src
In directory usw-pr-cvs1:/tmp/cvs-serv31618
Modified Files:
chanserv.c checkdb.c gline.c helpserv.c modcmd.c opserv.c
recdb.c
Log Message:
recdb.c: read and write using mmap() if possible (faster)
recdb.c: Parse \<octal> qstrings like most other programs do (no leading 0 for characters > 077)
others: Open db files to be written using write_database() as read+write (required for mmap)
Also, change tabs to spaces in a couple places near other changes
Index: chanserv.c
===================================================================
RCS file: /cvsroot/srvx/services/src/chanserv.c,v
retrieving revision 1.262
retrieving revision 1.263
diff -C2 -r1.262 -r1.263
*** chanserv.c 5 Aug 2002 01:26:05 -0000 1.262
--- chanserv.c 5 Aug 2002 03:20:24 -0000 1.263
***************
*** 6887,6891 ****
chanserv_db_write(void)
{
! FILE *f = fopen(TEMP_DB_NAME, "w");
dict_t db = alloc_database();
--- 6887,6891 ----
chanserv_db_write(void)
{
! FILE *f = fopen(TEMP_DB_NAME, "w+");
dict_t db = alloc_database();
Index: checkdb.c
===================================================================
RCS file: /cvsroot/srvx/services/src/checkdb.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -r1.7 -r1.8
*** checkdb.c 30 Jul 2002 02:15:11 -0000 1.7
--- checkdb.c 5 Aug 2002 03:20:24 -0000 1.8
***************
*** 65,69 ****
f = stdout;
} else {
! if (!(f = fopen(argv[2], "w"))) {
fprintf(stderr, "fopen: %s\n", strerror(errno));
return 4;
--- 65,69 ----
f = stdout;
} else {
! if (!(f = fopen(argv[2], "w+"))) {
fprintf(stderr, "fopen: %s\n", strerror(errno));
return 4;
Index: gline.c
===================================================================
RCS file: /cvsroot/srvx/services/src/gline.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -C2 -r1.27 -r1.28
*** gline.c 30 Jul 2002 02:15:11 -0000 1.27
--- gline.c 5 Aug 2002 03:20:24 -0000 1.28
***************
*** 246,250 ****
dict_t db = alloc_database();
heap_remove_pred(gline_heap, gline_insert_entry, db);
! dbfile = fopen(TEMP_DB_NAME, "w");
write_database(dbfile, db);
fclose(dbfile);
--- 246,250 ----
dict_t db = alloc_database();
heap_remove_pred(gline_heap, gline_insert_entry, db);
! dbfile = fopen(TEMP_DB_NAME, "w+");
write_database(dbfile, db);
fclose(dbfile);
Index: helpserv.c
===================================================================
RCS file: /cvsroot/srvx/services/src/helpserv.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -r1.20 -r1.21
*** helpserv.c 30 Jul 2002 02:15:11 -0000 1.20
--- helpserv.c 5 Aug 2002 03:20:24 -0000 1.21
***************
*** 20,23 ****
--- 20,24 ----
/* TODO List for helpserv.c
+ * - ?clone uses a new way to check for a valid nick name (for multi-protocol support) - need to do that in ?helpserv register
* - cmd_close should optionally take another argument (a reason/comment)
* Wishlist for helpserv.c
***************
*** 2914,2918 ****
/* now write the entire database */
! f = fopen(TEMP_DB_NAME, "w");
write_database(f, db);
fclose(f);
--- 2915,2919 ----
/* now write the entire database */
! f = fopen(TEMP_DB_NAME, "w+");
write_database(f, db);
fclose(f);
Index: modcmd.c
===================================================================
RCS file: /cvsroot/srvx/services/src/modcmd.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -r1.11 -r1.12
*** modcmd.c 5 Aug 2002 01:46:27 -0000 1.11
--- modcmd.c 5 Aug 2002 03:20:24 -0000 1.12
***************
*** 982,986 ****
dict_insert(db2, "services", alloc_record_data_object(db));
! dbfile = fopen(TEMP_DB_NAME, "w");
write_database(dbfile, db2);
fclose(dbfile);
--- 982,986 ----
dict_insert(db2, "services", alloc_record_data_object(db));
! dbfile = fopen(TEMP_DB_NAME, "w+");
write_database(dbfile, db2);
fclose(dbfile);
Index: opserv.c
===================================================================
RCS file: /cvsroot/srvx/services/src/opserv.c,v
retrieving revision 1.258
retrieving revision 1.259
diff -C2 -r1.258 -r1.259
*** opserv.c 4 Aug 2002 21:12:57 -0000 1.258
--- opserv.c 5 Aug 2002 03:20:24 -0000 1.259
***************
*** 3030,3039 ****
dict_insert(db, KEY_MAX_CLIENTS, alloc_record_data_object(subdb));
/* now write the entire database */
! f = fopen(TEMP_DB_NAME, "w");
write_database(f, db);
fclose(f);
free_database(db);
if (rename(TEMP_DB_NAME, OPSERV_DB_NAME) == -1) {
! log(NS_LOG, LOG_ERROR, "unable to rename new db to old: %s\n", strerror(errno));
}
last_db_write = now;
--- 3030,3039 ----
dict_insert(db, KEY_MAX_CLIENTS, alloc_record_data_object(subdb));
/* now write the entire database */
! f = fopen(TEMP_DB_NAME, "w+");
write_database(f, db);
fclose(f);
free_database(db);
if (rename(TEMP_DB_NAME, OPSERV_DB_NAME) == -1) {
! log(NS_LOG, LOG_ERROR, "unable to rename new db to old: %s\n", strerror(errno));
}
last_db_write = now;
Index: recdb.c
===================================================================
RCS file: /cvsroot/srvx/services/src/recdb.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -C2 -r1.40 -r1.41
*** recdb.c 3 Aug 2002 02:26:18 -0000 1.40
--- recdb.c 5 Aug 2002 03:20:24 -0000 1.41
***************
*** 22,25 ****
--- 22,34 ----
#include "log.h"
+ #ifdef HAVE_FCNTL_H
+ #include <fcntl.h>
+ #endif
+ #include <sys/mman.h>
+ #include <sys/stat.h>
+
+ /* 4 MiB on x86 */
+ #define MMAP_MAP_LENGTH (getpagesize()*1024)
+
/* file format (grammar in Backus-Naur Form):
*
***************
*** 42,52 ****
};
typedef struct recdb_file {
const char *source;
! union {
! FILE *f;
! unsigned char *s;
! } s;
! int is_file : 1;
struct recdb_context ctx;
jmp_buf env;
--- 51,67 ----
};
+ enum recdb_filetype {
+ RECDB_FILE,
+ RECDB_STRING,
+ RECDB_MMAP
+ };
+
typedef struct recdb_file {
const char *source;
! FILE *f; /* For RECDB_FILE, RECDB_MMAP */
! unsigned char *s; /* For RECDB_STRING, RECDB_MMAP */
! enum recdb_filetype type;
! size_t length;
! off_t pos;
struct recdb_context ctx;
jmp_buf env;
***************
*** 54,58 ****
typedef struct recdb_outfile {
! FILE *f;
int tablvl;
#ifdef NDEBUG
--- 69,86 ----
typedef struct recdb_outfile {
! FILE *f; /* For RECDB_FILE, RECDB_MMAP */
! unsigned char *s; /* For RECDB_STRING, RECDB_MMAP */
! union {
! struct { /* For RECDB_STRING */
! size_t chunksize;
! size_t alloc_length;
! } s;
! struct { /* For RECDB_MMAP */
! off_t mmap_begin;
! size_t mmap_length;
! } m;
! } state;
! enum recdb_filetype type;
! off_t pos;
int tablvl;
#ifdef NDEBUG
***************
*** 61,64 ****
--- 89,96 ----
} RECDB_OUT;
+ #ifdef HAVE_MMAP
+ static int mmap_error=0;
+ #endif
+
#define EOL '\n'
***************
*** 160,164 ****
new_list->used = slist->used;
for (i=0; i<new_list->used; i++) {
! new_list->list[i] = strdup(slist->list[i]);
}
return new_list;
--- 192,196 ----
new_list->used = slist->used;
for (i=0; i<new_list->used; i++) {
! new_list->list[i] = strdup(slist->list[i]);
}
return new_list;
***************
*** 173,187 ****
for (part=new_path; *new_path; new_path++) {
! if (*new_path != '/') continue;
! *new_path = 0;
! rd = dict_find(db, part, NULL);
! if (!rd || rd->type != RECDB_OBJECT) {
! free(orig_path);
! return NULL;
! }
! db = rd->d.object;
! part = new_path+1;
}
--- 205,219 ----
for (part=new_path; *new_path; new_path++) {
! if (*new_path != '/') continue;
! *new_path = 0;
! rd = dict_find(db, part, NULL);
! if (!rd || rd->type != RECDB_OBJECT) {
! free(orig_path);
! return NULL;
! }
! db = rd->d.object;
! part = new_path+1;
}
***************
*** 229,233 ****
dbeof(RECDB *recdb)
{
! return (recdb->is_file) ? feof(recdb->s.f) : !*recdb->s.s;
}
--- 261,278 ----
dbeof(RECDB *recdb)
{
! switch (recdb->type) {
! case RECDB_FILE:
! return feof(recdb->f);
! break;
! case RECDB_STRING:
! return !*recdb->s;
! break;
! case RECDB_MMAP:
! return ((size_t)recdb->pos >= recdb->length);
! break;
! default:
! return 1;
! break;
! }
}
***************
*** 236,243 ****
{
int res;
! if (recdb->is_file) {
! res = fgetc(recdb->s.f);
! } else {
! res = dbeof(recdb) ? EOF : *recdb->s.s++;
}
if (res == EOL) recdb->ctx.line++, recdb->ctx.col=1;
--- 281,296 ----
{
int res;
! switch (recdb->type) {
! case RECDB_FILE:
! res = fgetc(recdb->f);
! recdb->pos++;
! break;
! case RECDB_STRING:
! case RECDB_MMAP:
! res = dbeof(recdb) ? EOF : recdb->s[recdb->pos++];
! break;
! default:
! res = EOF;
! break;
}
if (res == EOL) recdb->ctx.line++, recdb->ctx.col=1;
***************
*** 249,256 ****
dbungetc(int c, RECDB *recdb)
{
! if (recdb->is_file) {
! ungetc(c, recdb->s.f);
! } else {
! *(--recdb->s.s) = c;
}
if (c == EOL) recdb->ctx.line--, recdb->ctx.col=-1;
--- 302,314 ----
dbungetc(int c, RECDB *recdb)
{
! switch (recdb->type) {
! case RECDB_FILE:
! ungetc(c, recdb->f);
! recdb->pos--;
! break;
! case RECDB_STRING:
! case RECDB_MMAP:
! recdb->s[--recdb->pos] = c;
! break;
}
if (c == EOL) recdb->ctx.line--, recdb->ctx.col=-1;
***************
*** 258,261 ****
--- 316,382 ----
}
+ static void
+ dbputc(int c, RECDB_OUT *file)
+ {
+ switch (file->type) {
+ case RECDB_FILE:
+ putc(c, file->f);
+ break;
+ case RECDB_MMAP:
+ #ifdef HAVE_MMAP
+ if (mmap_error) {
+ return;
+ }
+ if ((size_t)file->pos >= file->state.m.mmap_length) {
+ if (munmap(file->s, file->state.m.mmap_length)) {
+ log(MAIN_LOG, LOG_WARNING, "Unable to munmap output db: %s", strerror(errno));
+ mmap_error++;
+ return;
+ }
+ file->state.m.mmap_begin += file->state.m.mmap_length;
+ if ((file->s = mmap(NULL, file->state.m.mmap_length, PROT_WRITE, MAP_SHARED, fileno(file->f), file->state.m.mmap_begin)) == MAP_FAILED) {
+ log(MAIN_LOG, LOG_WARNING, "Unable to re-mmap output db: %s", strerror(errno));
+ file->s = NULL;
+ mmap_error++;
+ return;
+ }
+ ftruncate(fileno(file->f), file->state.m.mmap_begin+file->state.m.mmap_length);
+ file->pos = 0;
+ }
+ file->s[file->pos++] = (unsigned char)c;
+ #endif
+ break;
+ case RECDB_STRING:
+ if ((size_t)file->pos >= file->state.s.alloc_length) {
+ file->state.s.alloc_length += file->state.s.chunksize;
+ realloc(file->s, file->state.s.alloc_length);
+ }
+ file->s[file->pos++] = (unsigned char)c;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* This could be optimized, but it's only used for 2 to 5 char long strings */
+ static void
+ dbputs(const char *s, RECDB_OUT *file)
+ {
+ size_t i;
+
+ switch (file->type) {
+ case RECDB_FILE:
+ fputs(s, file->f);
+ break;
+ case RECDB_MMAP:
+ case RECDB_STRING:
+ for (i=0; s[i]; i++) {
+ dbputc(((const unsigned char *)s)[i], file);
+ }
+ default:
+ break;
+ }
+ }
+
/* returns first non-whitespace, non-comment character (-1 for EOF found) */
int
***************
*** 264,289 ****
int c, d, in_comment = 0;
while (!dbeof(recdb)) {
! c = dbgetc(recdb);
! if (c == EOF) return EOF;
! if (isspace(c)) continue;
! if (c != '/') return c;
! if ((d = dbgetc(recdb)) == '*') {
! /* C style comment, with slash star comment star slash */
! in_comment = 1;
! do {
! do {
! c = dbgetc(recdb);
! } while (c != '*' && c != EOF);
! if ((c = dbgetc(recdb)) == '/') in_comment = 0;
! } while (in_comment);
! } else if (d == '/') {
! /* C++ style comment, with slash slash comment newline */
! do {
! c = dbgetc(recdb);
! } while (c != EOF && c != EOL);
! } else {
! if (d != EOF) dbungetc(d, recdb);
! return c;
! }
}
return -1;
--- 385,410 ----
int c, d, in_comment = 0;
while (!dbeof(recdb)) {
! c = dbgetc(recdb);
! if (c == EOF) return EOF;
! if (isspace(c)) continue;
! if (c != '/') return c;
! if ((d = dbgetc(recdb)) == '*') {
! /* C style comment, with slash star comment star slash */
! in_comment = 1;
! do {
! do {
! c = dbgetc(recdb);
! } while (c != '*' && c != EOF);
! if ((c = dbgetc(recdb)) == '/') in_comment = 0;
! } while (in_comment);
! } else if (d == '/') {
! /* C++ style comment, with slash slash comment newline */
! do {
! c = dbgetc(recdb);
! } while (c != EOF && c != EOL);
! } else {
! if (d != EOF) dbungetc(d, recdb);
! return c;
! }
}
return -1;
***************
*** 312,321 ****
} else {
switch (c = dbgetc(recdb)) {
! case '0': /* either \0 or \0<octal> */
{
! char digits[4] = { '\0', '\0', '\0', '\0' };
! for (i=0; i < 3; i++) {
! /* \0177 is the highest possible, so \0200 would be invalid */
! if ((i == 3) && (digits[0] != '1')) {
break;
}
--- 433,450 ----
} else {
switch (c = dbgetc(recdb)) {
! case '0': /* \<octal>, 000 through 377 */
! case '1':
! case '2':
! case '3':
! case '4':
! case '5':
! case '6':
! case '7':
{
! char digits[3] = { (char)c, '\0', '\0' };
! for (i=1; i < 3; i++) {
! /* Maximum of \377, so there's a max of 2 digits
! * if digits[0] > '3' (no \400, but \40 is fine) */
! if (i == 2 && digits[0] > '3') {
break;
}
***************
*** 397,405 ****
dict_set_free_keys(obj, free);
while (!dbeof(recdb)) {
! if ((c = parse_skip_ws(recdb)) == '}') break;
! if (c == EOF) break;
dbungetc(c, recdb);
! parse_record_int(recdb, &name, &rd);
! dict_insert(obj, name, rd);
}
return obj;
--- 526,534 ----
dict_set_free_keys(obj, free);
while (!dbeof(recdb)) {
! if ((c = parse_skip_ws(recdb)) == '}') break;
! if (c == EOF) break;
dbungetc(c, recdb);
! parse_record_int(recdb, &name, &rd);
! dict_insert(obj, name, rd);
}
return obj;
***************
*** 415,425 ****
slist = alloc_string_list(4);
while (true) {
! c = parse_skip_ws(recdb);
! if (c == EOF || c == ')') break;
! dbungetc(c, recdb);
! string_list_append(slist, parse_qstring(recdb));
! c = parse_skip_ws(recdb);
! if (c == EOF || c == ')') break;
! if (c != ',') ABORT(recdb, EXPECTED_COMMA, c);
}
return slist;
--- 544,554 ----
slist = alloc_string_list(4);
while (true) {
! c = parse_skip_ws(recdb);
! if (c == EOF || c == ')') break;
! dbungetc(c, recdb);
! string_list_append(slist, parse_qstring(recdb));
! c = parse_skip_ws(recdb);
! if (c == EOF || c == ')') break;
! if (c != ',') ABORT(recdb, EXPECTED_COMMA, c);
}
return slist;
***************
*** 433,439 ****
c = parse_skip_ws(recdb);
if (c == EOF) {
! if (!*pname) return;
! free(*pname);
! ABORT(recdb, EXPECTED_RECORD_DATA, EOF);
}
if (c == '=') c = parse_skip_ws(recdb);
--- 562,568 ----
c = parse_skip_ws(recdb);
if (c == EOF) {
! if (!*pname) return;
! free(*pname);
! ABORT(recdb, EXPECTED_RECORD_DATA, EOF);
}
if (c == '=') c = parse_skip_ws(recdb);
***************
*** 461,465 ****
dict_set_free_keys(db, free);
while (!dbeof(recdb)) {
! parse_record_int(recdb, &name, &rd);
if (name) dict_insert(db, name, rd);
}
--- 590,594 ----
dict_set_free_keys(db, free);
while (!dbeof(recdb)) {
! parse_record_int(recdb, &name, &rd);
if (name) dict_insert(db, name, rd);
}
***************
*** 490,495 ****
{
log(MAIN_LOG, LOG_ERROR, "%s (got '%c') at %s line %d column %d\n",
! failure_reason(code), code & 255,
! recdb->source, recdb->ctx.line, recdb->ctx.col);
}
--- 619,624 ----
{
log(MAIN_LOG, LOG_ERROR, "%s (got '%c') at %s line %d column %d\n",
! failure_reason(code), code & 255,
! recdb->source, recdb->ctx.line, recdb->ctx.col);
}
***************
*** 502,515 ****
*prd = NULL;
recdb.source = "<user-supplied text>";
! recdb.s.s = strdup(text);
! recdb.is_file = 0;
recdb.ctx.line = recdb.ctx.col = 1;
if ((res = setjmp(recdb.env)) == 0) {
! parse_record_int(&recdb, pname, prd);
! return 0;
} else {
! if (*pname) free(*pname);
! if (*prd) free(*prd);
! return failure_reason(res);
}
}
--- 631,647 ----
*prd = NULL;
recdb.source = "<user-supplied text>";
! recdb.f = NULL;
! recdb.s = strdup(text);
! recdb.length = strlen(text);
! recdb.pos = 0;
! recdb.type = RECDB_STRING;
recdb.ctx.line = recdb.ctx.col = 1;
if ((res = setjmp(recdb.env)) == 0) {
! parse_record_int(&recdb, pname, prd);
! return 0;
} else {
! if (*pname) free(*pname);
! if (*prd) free(*prd);
! return failure_reason(res);
}
}
***************
*** 521,539 ****
int res;
dict_t db;
recdb.source = filename;
! recdb.s.f = fopen(filename, "r");
! if (!recdb.s.f) {
! log(MAIN_LOG, LOG_ERROR, "Unable to open database file '%s' for reading\n", filename);
! return NULL;
}
! recdb.is_file = 1;
recdb.ctx.line = recdb.ctx.col = 1;
if ((res = setjmp(recdb.env)) == 0) {
! db = parse_database_int(&recdb);
} else {
! explain_failure(&recdb, res);
_exit(1);
}
! fclose(recdb.s.f);
return db;
}
--- 653,709 ----
int res;
dict_t db;
+ struct stat statinfo;
+
recdb.source = filename;
! if (!(recdb.f = fopen(filename, "r"))) {
! log(MAIN_LOG, LOG_ERROR, "Unable to open database file '%s' for reading: %s\n", filename, strerror(errno));
! return NULL;
! }
!
! if (fstat(fileno(recdb.f), &statinfo)) {
! log(MAIN_LOG, LOG_ERROR, "Unable to fstat database file '%s': %s\n", filename, strerror(errno));
! return NULL;
}
! recdb.length = (size_t)statinfo.st_size;
!
! #ifdef HAVE_MMAP
! /* Try mmap */
! if (!mmap_error && (recdb.s = mmap(NULL, recdb.length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(recdb.f), 0)) != MAP_FAILED) {
! recdb.type = RECDB_MMAP;
! } else {
! /* Fall back to stdio */
! if (!mmap_error) {
! log(MAIN_LOG, LOG_WARNING, "Unable to mmap database file '%s' (falling back to stdio): %s\n", filename, strerror(errno));
! mmap_error = 1;
! }
! #else
! if (1) {
! #endif
! recdb.s = NULL;
! recdb.type = RECDB_FILE;
! }
!
recdb.ctx.line = recdb.ctx.col = 1;
+ recdb.pos = 0;
+
if ((res = setjmp(recdb.env)) == 0) {
! db = parse_database_int(&recdb);
} else {
! explain_failure(&recdb, res);
_exit(1);
}
!
! switch (recdb.type) {
! case RECDB_MMAP:
! #ifdef HAVE_MMAP
! munmap(recdb.s, recdb.length);
! #endif
! case RECDB_FILE:
! fclose(recdb.f);
! break;
! /* Appease gcc */
! default:
! break;
! }
return db;
}
***************
*** 544,565 ****
write_qstring(RECDB_OUT *file, const char *str)
{
! fputc('"', file->f);
while (*str) {
switch (*str) {
! case '\a': fputs("\\a", file->f); break;
! case '\b': fputs("\\b", file->f); break;
! case '\t': fputs("\\t", file->f); break;
! case EOL: fputs("\\n", file->f); break;
! case '\v': fputs("\\v", file->f); break;
! case '\f': fputs("\\f", file->f); break;
! case '\r': fputs("\\r", file->f); break;
! case '\\': fputs("\\\\", file->f); break;
! case '"': fputs("\\\"", file->f); break;
default:
if (!isprint(*str)) {
unsigned int chr = (unsigned char)(*str);
! fprintf(file->f, "\\x%.2x", chr);
} else {
! fputc(*str, file->f);
}
break;
--- 714,737 ----
write_qstring(RECDB_OUT *file, const char *str)
{
! dbputc('"', file);
while (*str) {
switch (*str) {
! case '\a': dbputs("\\a", file); break;
! case '\b': dbputs("\\b", file); break;
! case '\t': dbputs("\\t", file); break;
! case EOL: dbputs("\\n", file); break;
! case '\v': dbputs("\\v", file); break;
! case '\f': dbputs("\\f", file); break;
! case '\r': dbputs("\\r", file); break;
! case '\\': dbputs("\\\\", file); break;
! case '"': dbputs("\\\"", file); break;
default:
if (!isprint(*str)) {
unsigned int chr = (unsigned char)(*str);
! char buf[5];
! sprintf(buf, "\\x%.2x", chr);
! dbputs(buf, file);
} else {
! dbputc(*str, file);
}
break;
***************
*** 567,571 ****
str++;
}
! fputc('"', file->f);
}
--- 739,743 ----
str++;
}
! dbputc('"', file);
}
***************
*** 584,588 ****
int i;
! fputs("{\n", file->f);
#ifdef NDEBUG
file->need_tab = 1;
--- 756,760 ----
int i;
! dbputs("{\n", file);
#ifdef NDEBUG
file->need_tab = 1;
***************
*** 594,603 ****
#ifdef NDEBUG
! fputc('\n', file->f);
#endif
for (i=0; i < file->tablvl; i++) {
! fputc('\t', file->f);
}
! fputc('}', file->f);
}
--- 766,775 ----
#ifdef NDEBUG
! dbputc('\n', file);
#endif
for (i=0; i < file->tablvl; i++) {
! dbputc('\t', file);
}
! dbputc('}', file);
}
***************
*** 606,618 ****
{
unsigned int i;
! fputc('(', file->f);
if (slist->used) {
! write_qstring(file, slist->list[0]);
! for (i=1; i<slist->used; i++) {
! fputs(", ", file->f);
! write_qstring(file, slist->list[i]);
! }
}
! fputc(')', file->f);
}
--- 778,790 ----
{
unsigned int i;
! dbputc('(', file);
if (slist->used) {
! write_qstring(file, slist->list[0]);
! for (i=1; i<slist->used; i++) {
! dbputs(", ", file);
! write_qstring(file, slist->list[i]);
! }
}
! dbputc(')', file);
}
***************
*** 628,631 ****
--- 800,804 ----
}
+ /* It's probably not worth the overhead of making this use mmap */
void
write_record(FILE *file, const char *name, struct record_data *rd)
***************
*** 634,637 ****
--- 807,812 ----
fileinfo.f = file;
+ fileinfo.type = RECDB_FILE;
+ fileinfo.pos = 0;
fileinfo.tablvl = 0;
#ifdef NDEBUG
***************
*** 648,652 ****
#ifdef NDEBUG
if (rd->type == RECDB_OBJECT && !file->need_tab) {
! fputc('\n', file->f);
file->need_tab = 1;
}
--- 823,827 ----
#ifdef NDEBUG
if (rd->type == RECDB_OBJECT && !file->need_tab) {
! dbputc('\n', file);
file->need_tab = 1;
}
***************
*** 655,659 ****
#endif
for (i=0; i < file->tablvl; i++) {
! fputc('\t', file->f);
}
#ifdef NDEBUG
--- 830,834 ----
#endif
for (i=0; i < file->tablvl; i++) {
! dbputc('\t', file);
}
#ifdef NDEBUG
***************
*** 662,677 ****
#endif
write_qstring(file, name);
! fputc(' ', file->f);
write_record_data(file, rd);
! fputc(';', file->f);
#ifdef NDEBUG
if (rd->type == RECDB_OBJECT) {
! fputc('\n', file->f);
file->need_tab = 1;
} else {
! fputc(' ', file->f);
}
#else
! fputc('\n', file->f);
#endif
}
--- 837,852 ----
#endif
write_qstring(file, name);
! dbputc(' ', file);
write_record_data(file, rd);
! dbputc(';', file);
#ifdef NDEBUG
if (rd->type == RECDB_OBJECT) {
! dbputc('\n', file);
file->need_tab = 1;
} else {
! dbputc(' ', file);
}
#else
! dbputc('\n', file);
#endif
}
***************
*** 682,698 ****
RECDB_OUT *file = extra;
write_record2(file, key, data);
! fputc(EOL, file->f);
return 0;
}
void
write_database(FILE *file, dict_t db)
{
RECDB_OUT fileinfo;
fileinfo.f = file;
fileinfo.tablvl = 0;
#ifdef NDEBUG
fileinfo.need_tab = 0;
#endif
dict_foreach(db, write_database_helper, &fileinfo);
}
--- 857,931 ----
RECDB_OUT *file = extra;
write_record2(file, key, data);
! dbputc(EOL, file);
return 0;
}
+ /* Note: this *needs* the file opened as "w+" or else mmap() will fail */
void
write_database(FILE *file, dict_t db)
{
RECDB_OUT fileinfo;
+ off_t original_offset;
+
fileinfo.f = file;
+ fileinfo.pos = original_offset = ftello(file);
fileinfo.tablvl = 0;
#ifdef NDEBUG
fileinfo.need_tab = 0;
#endif
+
+ #ifdef HAVE_MMAP
+ if (mmap_error) {
+ #endif
+ fileinfo.type = RECDB_FILE;
+ dict_foreach(db, write_database_helper, &fileinfo);
+ return;
+ #ifdef HAVE_MMAP
+ }
+
+ fileinfo.type = RECDB_MMAP;
+ fileinfo.state.m.mmap_length = MMAP_MAP_LENGTH;
+ fileinfo.state.m.mmap_begin = fileinfo.pos / fileinfo.state.m.mmap_length;
+ fileinfo.pos %= MMAP_MAP_LENGTH;
+
+ fflush(file);
+
+ if (ftruncate(fileno(fileinfo.f), fileinfo.state.m.mmap_begin+fileinfo.state.m.mmap_length)) {
+ log(MAIN_LOG, LOG_WARNING, "Unable to ftruncate to extend output: %s\n", strerror(errno));
+ mmap_error = 1;
+
+ /* As mmap_error is true, it will now use stdio */
+ write_database(file, db);
+ return;
+ }
+
+ if ((fileinfo.s = mmap(NULL, fileinfo.state.m.mmap_length, PROT_WRITE, MAP_SHARED, fileno(fileinfo.f), fileinfo.state.m.mmap_begin)) == MAP_FAILED) {
+ log(MAIN_LOG, LOG_WARNING, "Unable to mmap output: %s\n", strerror(errno));
+ mmap_error = 1;
+
+ ftruncate(fileno(fileinfo.f), original_offset);
+ fseeko(fileinfo.f, original_offset, SEEK_SET);
+
+ write_database(file, db);
+ return;
+ }
+
dict_foreach(db, write_database_helper, &fileinfo);
+
+ if (mmap_error) {
+ if (fileinfo.s) {
+ munmap(fileinfo.s, fileinfo.state.m.mmap_length);
+ }
+
+ ftruncate(fileno(fileinfo.f), original_offset);
+ fseeko(fileinfo.f, original_offset, SEEK_SET);
+
+ write_database(file, db);
+ return;
+ }
+
+ munmap(fileinfo.s, fileinfo.state.m.mmap_length);
+ ftruncate(fileno(fileinfo.f), fileinfo.state.m.mmap_begin+fileinfo.pos); /* Clean up the extra space */
+ fseeko(fileinfo.f, (off_t)0, SEEK_END);
+ #endif
}
|