diff --git a/binding/c/xdb_searcher.c b/binding/c/xdb_searcher.c index 8a12119..f7de603 100644 --- a/binding/c/xdb_searcher.c +++ b/binding/c/xdb_searcher.c @@ -8,6 +8,9 @@ #include "xdb_searcher.h" +// internal function prototype define +XDB_PRIVATE(int) read(xdb_searcher_t *, long offset, char *, size_t length); + XDB_PRIVATE(int) xdb_new_base(xdb_searcher_t *xdb, const char *dbPath, const char *vIndex, const char *cBuff) { memset(xdb, 0x00, sizeof(xdb_searcher_t)); @@ -49,21 +52,152 @@ XDB_PUBLIC(void) xdb_close(xdb_searcher_t *xdb) { } } -// xdb searcher search api define -XDB_PUBLIC(int) xdb_search(unsigned int ip, char *buffer) { - return 0; -} +// --- xdb searcher search api define -XDB_PUBLIC(int) xdb_search_by_string(const char *str_ip, char *buffer) { +XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *xdb, const char *str_ip, char *region_buffer, size_t length) { unsigned int ip = 0; int errcode = check_ip(str_ip, &ip); if (errcode != 0) { return 10 + errcode; } else { - return xdb_search(ip, buffer); + return xdb_search(xdb, ip, region_buffer, length); } } +XDB_PUBLIC(int) xdb_search(xdb_searcher_t *xdb, unsigned int ip, char *region_buffer, size_t length) { + int il0, il1, idx, err, l, h, m, data_len; + unsigned int s_ptr, e_ptr, p, sip, eip, data_ptr; + char vector_buffer[VectorIndexSize], segment_buffer[SegmentIndexSize]; + + // reset the io counter + xdb->io_count = 0; + + // locate the segment index block based on the vector index + il0 = (ip >> 24) & 0xFF; + il1 = (ip >> 16) & 0xFF; + idx = il0 * VectorIndexCols * VectorIndexSize + il1 * VectorIndexSize; + if (xdb->vector_index != NULL) { + s_ptr = get_unsigned_int(xdb->vector_index, idx); + e_ptr = get_unsigned_int(xdb->vector_index, idx + 4); + } else if (xdb->content_buff != NULL) { + s_ptr = get_unsigned_int(xdb->content_buff, HeaderInfoLength + idx); + e_ptr = get_unsigned_int(xdb->content_buff, HeaderInfoLength + idx + 4); + } else { + err = read(xdb, HeaderInfoLength + idx, vector_buffer, sizeof(vector_buffer)); + if (err != 0) { + return 10 + err; + } + + s_ptr = get_unsigned_int(vector_buffer, 0); + e_ptr = get_unsigned_int(vector_buffer, 4); + } + + printf("s_ptr=%u, e_ptr=%u", s_ptr, e_ptr); + + // binary search to get the final region info + data_len = 0, data_ptr = 0; + l = 0, h = (e_ptr - s_ptr) / SegmentIndexSize; + while (l <= h) { + m = (l + h) >> 1; + p = s_ptr + m * SegmentIndexSize; + + // read the segment index item + err = read(xdb, p, segment_buffer, sizeof(segment_buffer)); + if (err != 0) { + return 20 + err; + } + + // decode the data fields as needed + sip = get_unsigned_int(segment_buffer, 0); + if (ip < sip) { + h = m - 1; + } else { + eip = get_unsigned_int(segment_buffer, 4); + if (ip > eip) { + l = m + 1; + } else { + data_len = get_unsigned_short(segment_buffer, 8); + data_ptr = get_unsigned_short(segment_buffer, 10); + break; + } + } + } + + printf("data_len=%u, data_ptr=%u\n", data_len, data_ptr); + if (data_len == 0) { + region_buffer[0] = '\0'; + return 0; + } + + // buffer length checking + if (data_len >= length) { + return 1; + } + + err = read(xdb, data_ptr, region_buffer, data_len); + if (err != 0) { + return 30 + err; + } + + // auto append a NULL-end + region_buffer[data_len] = '\0'; + return 0; +} + +XDB_PRIVATE(int) read(xdb_searcher_t *xdb, long offset, char *buffer, size_t length) { + // check the xdb content cache first + if (xdb->content_buff != NULL) { + memcpy(buffer, xdb->content_buff, length); + return 0; + } + + // seek to the offset + int errcode = fseek(xdb->handle, offset, SEEK_SET); + if (errcode == -1) { + return 1; + } + + int r_size = fread(buffer, 1, length, xdb->handle); + if (r_size != 1) { + return 2; + } + + return 0; +} + +XDB_PUBLIC(int) xdb_get_io_count(xdb_searcher_t *xdb) { + return xdb->io_count; +} + + +// --- buffer load util functions + +XDB_PUBLIC(int) xdb_load_header(FILE *handle, char *buffer, size_t length) { + return 0; +} + +XDB_PUBLIC(int) xdb_load_header_from_file(char *dbPath, char *buffer, size_t length) { + return 0; +} + +XDB_PUBLIC(int) xdb_load_vector_index(FILE *handle, char *buffer, size_t length) { + return 0; +} + +XDB_PUBLIC(int) xdb_load_vector_index_from_file(char *dbPath, char *buffer, size_t length) { + return 0; +} + +XDB_PUBLIC(int) xdb_load_content(FILE *handle, char *buffer, size_t length) { + return 0; +} + +XDB_PUBLIC(int) xdb_load_content_from_file(char *handle, char *buffer, size_t length) { + return 0; +} + +// --- End + // get unsigned long (4bytes) from a specified buffer start from the specified offset XDB_PUBLIC(unsigned int) get_unsigned_int(const char *buffer, int offset) { return ( diff --git a/binding/c/xdb_searcher.h b/binding/c/xdb_searcher.h index 45abe38..8070e05 100644 --- a/binding/c/xdb_searcher.h +++ b/binding/c/xdb_searcher.h @@ -37,6 +37,15 @@ do { \ #define field_size(type, field) sizeof(((type *)0)->field) #define sf_field_size(type, field) (sizeof(((type *)0)->field) - 1) + +// public constants define +#define HeaderInfoLength 256 +#define VectorIndexRows 256 +#define VectorIndexCols 256 +#define VectorIndexSize 8 +#define SegmentIndexSize 14 + + // xdb searcher structure struct xdb_searcher_entry { FILE *handle; @@ -66,9 +75,28 @@ XDB_PUBLIC(int) xdb_new_with_buffer(xdb_searcher_t *, char *); XDB_PUBLIC(void) xdb_close(xdb_searcher_t *); // xdb searcher search api define -XDB_PUBLIC(int) xdb_search(unsigned int, char *); +XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *, const char *, char *, size_t); -XDB_PUBLIC(int) xdb_search_by_string(const char *, char *); +XDB_PUBLIC(int) xdb_search(xdb_searcher_t *, unsigned int, char *, size_t); + +XDB_PUBLIC(int) xdb_get_io_count(xdb_searcher_t *); + + +// --- buffer load util functions + +XDB_PUBLIC(int) xdb_load_header(FILE *, char *, size_t); + +XDB_PUBLIC(int) xdb_load_header_from_file(char *, char *, size_t); + +XDB_PUBLIC(int) xdb_load_vector_index(FILE *, char *, size_t); + +XDB_PUBLIC(int) xdb_load_vector_index_from_file(char *, char *, size_t); + +XDB_PUBLIC(int) xdb_load_content(FILE *, char *, size_t); + +XDB_PUBLIC(int) xdb_load_content_from_file(char *, char *, size_t); + +// --- End buffer load // get unsigned long (4bytes) from a specified buffer start from the specified offset with little-endian