X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fdatabase.c;h=07cb66c5f68a937b63a976bdc1fb9bf274024dca;hb=9fc7f0017d4d09eefa3fc601b3b7af3a797f72c1;hp=3a4f8b8bb13a81dd4099bdb78b3b89edd6b9b173;hpb=0e974d4b392023e2f38e8ab8cfe5977b0fb439b4;p=location%2Flibloc.git diff --git a/src/database.c b/src/database.c index 3a4f8b8..07cb66c 100644 --- a/src/database.c +++ b/src/database.c @@ -14,7 +14,7 @@ Lesser General Public License for more details. */ -#include +#include #include #include #include @@ -27,18 +27,16 @@ #include #include +#include +#include #include - -#include "libloc-private.h" -#include "as.h" -#include "database.h" -#include "stringpool.h" +#include +#include struct loc_database { struct loc_ctx* ctx; int refcount; - FILE* file; unsigned int version; time_t created_at; off_t vendor; @@ -51,11 +49,11 @@ struct loc_database { struct loc_stringpool* pool; }; -static int loc_database_read_magic(struct loc_database* db) { +static int loc_database_read_magic(struct loc_database* db, FILE* f) { struct loc_database_magic magic; // Read from file - size_t bytes_read = fread(&magic, 1, sizeof(magic), db->file); + size_t bytes_read = fread(&magic, 1, sizeof(magic), f); // Check if we have been able to read enough data if (bytes_read < sizeof(magic)) { @@ -69,7 +67,7 @@ static int loc_database_read_magic(struct loc_database* db) { DEBUG(db->ctx, "Magic value matches\n"); // Parse version - db->version = ntohs(magic.version); + db->version = be16toh(magic.version); DEBUG(db->ctx, "Database version is %u\n", db->version); return 0; @@ -82,12 +80,12 @@ static int loc_database_read_magic(struct loc_database* db) { } static int loc_database_read_as_section_v0(struct loc_database* db, - off_t as_offset, size_t as_length) { + FILE* f, off_t as_offset, size_t as_length) { DEBUG(db->ctx, "Reading AS section from %jd (%zu bytes)\n", as_offset, as_length); if (as_length > 0) { db->as_v0 = mmap(NULL, as_length, PROT_READ, - MAP_SHARED, fileno(db->file), as_offset); + MAP_SHARED, fileno(f), as_offset); if (db->as_v0 == MAP_FAILED) return -errno; @@ -100,11 +98,11 @@ static int loc_database_read_as_section_v0(struct loc_database* db, return 0; } -static int loc_database_read_header_v0(struct loc_database* db) { +static int loc_database_read_header_v0(struct loc_database* db, FILE* f) { struct loc_database_header_v0 header; // Read from file - size_t size = fread(&header, 1, sizeof(header), db->file); + size_t size = fread(&header, 1, sizeof(header), f); if (size < sizeof(header)) { ERROR(db->ctx, "Could not read enough data for header\n"); @@ -113,33 +111,33 @@ static int loc_database_read_header_v0(struct loc_database* db) { // Copy over data db->created_at = be64toh(header.created_at); - db->vendor = ntohl(header.vendor); - db->description = ntohl(header.description); + db->vendor = be32toh(header.vendor); + db->description = be32toh(header.description); // Open pool - off_t pool_offset = ntohl(header.pool_offset); - size_t pool_length = ntohl(header.pool_length); + off_t pool_offset = be32toh(header.pool_offset); + size_t pool_length = be32toh(header.pool_length); int r = loc_stringpool_open(db->ctx, &db->pool, - db->file, pool_length, pool_offset); + f, pool_length, pool_offset); if (r) return r; // AS section - off_t as_offset = ntohl(header.as_offset); - size_t as_length = ntohl(header.as_length); + off_t as_offset = be32toh(header.as_offset); + size_t as_length = be32toh(header.as_length); - r = loc_database_read_as_section_v0(db, as_offset, as_length); + r = loc_database_read_as_section_v0(db, f, as_offset, as_length); if (r) return r; return 0; } -static int loc_database_read_header(struct loc_database* db) { +static int loc_database_read_header(struct loc_database* db, FILE* f) { switch (db->version) { case 0: - return loc_database_read_header_v0(db); + return loc_database_read_header_v0(db, f); default: ERROR(db->ctx, "Incompatible database version: %u\n", db->version); @@ -147,16 +145,32 @@ static int loc_database_read_header(struct loc_database* db) { } } -static FILE* copy_file_pointer(FILE* f) { - int fd = fileno(f); +static int loc_database_read(struct loc_database* db, FILE* f) { + clock_t start = clock(); + + // Read magic bytes + int r = loc_database_read_magic(db, f); + if (r) + return r; - // Make a copy - fd = dup(fd); + // Read the header + r = loc_database_read_header(db, f); + if (r) + return r; - return fdopen(fd, "r"); + clock_t end = clock(); + + INFO(db->ctx, "Opened database in %.8fs\n", + (double)(end - start) / CLOCKS_PER_SEC); + + return 0; } LOC_EXPORT int loc_database_new(struct loc_ctx* ctx, struct loc_database** database, FILE* f) { + // Fail on invalid file handle + if (!f) + return -EINVAL; + struct loc_database* db = calloc(1, sizeof(*db)); if (!db) return -ENOMEM; @@ -167,30 +181,15 @@ LOC_EXPORT int loc_database_new(struct loc_ctx* ctx, struct loc_database** datab DEBUG(db->ctx, "Database object allocated at %p\n", db); - // Copy the file pointer and work on that so we don't care if - // the calling function closes the file - db->file = copy_file_pointer(f); - if (!db->file) - goto FAIL; - - // Read magic bytes - int r = loc_database_read_magic(db); - if (r) - return r; - - // Read the header - r = loc_database_read_header(db); - if (r) + int r = loc_database_read(db, f); + if (r) { + loc_database_unref(db); return r; + } *database = db; return 0; - -FAIL: - loc_database_unref(db); - - return -errno; } LOC_EXPORT struct loc_database* loc_database_ref(struct loc_database* db) { @@ -211,10 +210,6 @@ static void loc_database_free(struct loc_database* db) { loc_stringpool_unref(db->pool); - // Close file - if (db->file) - fclose(db->file); - loc_unref(db->ctx); free(db); } @@ -272,6 +267,9 @@ LOC_EXPORT int loc_database_get_as(struct loc_database* db, struct loc_as** as, off_t lo = 0; off_t hi = db->as_count - 1; + // Save start time + clock_t start = clock(); + while (lo <= hi) { off_t i = (lo + hi) / 2; @@ -282,8 +280,15 @@ LOC_EXPORT int loc_database_get_as(struct loc_database* db, struct loc_as** as, // Check if this is a match uint32_t as_number = loc_as_get_number(*as); - if (as_number == number) + if (as_number == number) { + clock_t end = clock(); + + // Log how fast this has been + DEBUG(db->ctx, "Found AS%u in %.8fs\n", as_number, + (double)(end - start) / CLOCKS_PER_SEC); + return 0; + } // If it wasn't, we release the AS and // adjust our search pointers @@ -298,5 +303,5 @@ LOC_EXPORT int loc_database_get_as(struct loc_database* db, struct loc_as** as, // Nothing found *as = NULL; - return 0; + return 1; }