C binding is ready for IPv6

This commit is contained in:
lion 2025-09-18 23:09:19 +08:00
parent 8fbdf82797
commit dff3084b93
5 changed files with 136 additions and 25 deletions

View File

@ -17,23 +17,35 @@ struct searcher_test_entry {
typedef struct searcher_test_entry searcher_test_t;
int init_searcher_test(searcher_test_t *test, char *db_path, char *cache_policy) {
int err;
int err, errcode = 0;
FILE *handle = fopen(db_path, "rb");
if (handle == NULL) {
return -1;
}
// auto detect the version from the xdb header
xdb_header_t *header = xdb_load_header_from_file(db_path);
xdb_header_t *header = xdb_load_header(handle);
if (header == NULL) {
printf("failed to load header from `%s`\n", db_path);
return 1;
errcode = 1;
goto defer;
}
// verify the current xdb
err = xdb_verify_from_header(handle, header);
if (err != 0) {
printf("failed to verify xdb file `%s` with errno=%d\n", db_path, err);
errcode = 2;
goto defer;
}
xdb_version_t *version = xdb_version_from_header(header);
if (version == NULL) {
printf("failed to load version from header\n");
xdb_free_header(header);
return 1;
errcode = 3;
goto defer;
}
xdb_free_header(header);
test->v_index = NULL;
test->c_buffer = NULL;
@ -41,38 +53,53 @@ int init_searcher_test(searcher_test_t *test, char *db_path, char *cache_policy)
err = xdb_new_with_file_only(version, &test->searcher, db_path);
if (err != 0) {
printf("failed to create searcher with errcode=%d\n", err);
return 1;
errcode = 4;
goto defer;
}
} else if (strcmp(cache_policy, "vectorIndex") == 0) {
test->v_index = xdb_load_vector_index_from_file(db_path);
if (test->v_index == NULL) {
printf("failed to load vector index from `%s`\n", db_path);
return 2;
errcode = 4;
goto defer;
}
err = xdb_new_with_vector_index(version, &test->searcher, db_path, test->v_index);
if (err != 0) {
printf("failed to create vector index cached searcher with errcode=%d\n", err);
return 3;
errcode = 5;
goto defer;
}
} else if (strcmp(cache_policy, "content") == 0) {
test->c_buffer = xdb_load_content_from_file(db_path);
if (test->c_buffer == NULL) {
printf("failed to load xdb content from `%s`\n", db_path);
return 4;
errcode = 4;
goto defer;
}
err = xdb_new_with_buffer(version, &test->searcher, test->c_buffer);
if (err != 0) {
printf("failed to create content cached searcher with errcode=%d\n", err);
return 5;
errcode = 5;
goto defer;
}
} else {
printf("invalid cache policy `%s`, options: file/vectorIndex/content\n", cache_policy);
return 6;
errcode = 6;
goto defer;
}
return 0;
defer:
if (header != NULL) {
xdb_free_header(header);
}
if (handle != NULL) {
fclose(handle);
}
return errcode;
}
void destroy_searcher_test(searcher_test_t *test) {
@ -125,6 +152,7 @@ void test_search(int argc, char *argv[]) {
long s_time, c_time;
unsigned int ip;
char line[512] = {'\0'}, region[512] = {'\0'};
char *region_buffer = NULL;
// ip parse
xdb_version_t *version;
@ -208,13 +236,17 @@ void test_search(int argc, char *argv[]) {
}
s_time = xdb_now();
err = xdb_search(&test.searcher, ip_bytes, version->bytes, region, sizeof(region));
err = xdb_search(&test.searcher, ip_bytes, version->bytes, &region_buffer, sizeof(region));
if (err != 0) {
printf("{err: %d, io_count: %d}\n", err, xdb_get_io_count(&test.searcher));
} else {
c_time = xdb_now() - s_time;
printf("{region: %s, io_count: %d, took: %ld μs}\n", region, xdb_get_io_count(&test.searcher), c_time);
printf("{region: %s, io_count: %d, took: %ld μs}\n", region_buffer, xdb_get_io_count(&test.searcher), c_time);
}
// free the region_buffer
xdb_free(region_buffer);
region_buffer = NULL;
}
destroy_searcher_test(&test);
@ -229,7 +261,8 @@ void test_bench(int argc, char *argv[]) {
FILE *handle;
char line[1024] = {'\0'}, sip_str[INET6_ADDRSTRLEN+1] = {'\0'}, eip_str[INET6_ADDRSTRLEN+1] = {'\0'};
char src_region[512] = {'\0'}, region_buffer[512] = {'\0'};
char src_region[512] = {'\0'}, region[512] = {'\0'};
char *region_buffer = region;
int count = 0, took;
long s_time, t_time, c_time = 0;
@ -337,7 +370,7 @@ void test_bench(int argc, char *argv[]) {
ip_list[1] = eip_bytes;
for (i = 0; i < 2; i++) {
t_time = xdb_now();
err = xdb_search(&test.searcher, ip_list[i], s_version->bytes, region_buffer, sizeof(region_buffer));
err = xdb_search(&test.searcher, ip_list[i], s_version->bytes, &region_buffer, sizeof(region));
c_time += xdb_now() - t_time;
if (err != 0) {
xdb_ip_to_string(ip_list[i], s_version->bytes, ip_string, sizeof(ip_string));

Binary file not shown.

View File

@ -106,6 +106,20 @@ XDB_PUBLIC(xdb_content_t *) xdb_load_content_from_file(const char *);
XDB_PUBLIC(void) xdb_free_content(void *);
// --- xdb verify
// Verify if the current Searcher could be used to search the specified xdb file.
// Why do we need this check ?
// The future features of the xdb impl may cause the current searcher not able to work properly.
//
// @Note: You Just need to check this ONCE when the service starts
// Or use another process (eg, A command) to check once Just to confirm the suitability.
XDB_PUBLIC(int) xdb_verify(FILE *);
XDB_PUBLIC(int) xdb_verify_from_header(FILE *handle, xdb_header_t *);
XDB_PUBLIC(int) xdb_verify_from_file(const char *);
// --- End xdb buffer
@ -221,9 +235,9 @@ XDB_PUBLIC(int) xdb_new_with_buffer(xdb_version_t *, xdb_searcher_t *, const xdb
XDB_PUBLIC(void) xdb_close(void *);
// xdb searcher search api define
XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *, const string_ip_t *, char *, size_t);
XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *, const string_ip_t *, char **, size_t);
XDB_PUBLIC(int) xdb_search(xdb_searcher_t *, const bytes_ip_t *, int, char *, size_t);
XDB_PUBLIC(int) xdb_search(xdb_searcher_t *, const bytes_ip_t *, int, char **, size_t);
XDB_PUBLIC(xdb_version_t *) xdb_get_version(xdb_searcher_t *);

View File

@ -59,7 +59,7 @@ XDB_PUBLIC(void) xdb_close(void *ptr) {
// --- xdb searcher search api define
XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *xdb, const string_ip_t *ip_string, char *region_buffer, size_t length) {
XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *xdb, const string_ip_t *ip_string, char **region_buffer, size_t length) {
bytes_ip_t ip_bytes[16] = {'\0'};
xdb_version_t *version = xdb_parse_ip(ip_string, ip_bytes, sizeof(ip_bytes));
if (version == NULL) {
@ -69,7 +69,7 @@ XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *xdb, const string_ip_t *ip_
}
}
XDB_PUBLIC(int) xdb_search(xdb_searcher_t *xdb, const bytes_ip_t *ip_bytes, int ip_len, char *region_buffer, size_t length) {
XDB_PUBLIC(int) xdb_search(xdb_searcher_t *xdb, const bytes_ip_t *ip_bytes, int ip_len, char **region_buffer, size_t length) {
int il0, il1, idx, err, bytes, d_bytes;
register int seg_index_size, l, h, m, p;
unsigned int s_ptr, e_ptr, data_ptr, data_len;
@ -147,12 +147,23 @@ XDB_PUBLIC(int) xdb_search(xdb_searcher_t *xdb, const bytes_ip_t *ip_bytes, int
}
// buffer length checking
if (data_len >= (int) length) {
if (length > 0 && data_len >= (int) length) {
err = 1;
goto done;
}
err = read(xdb, data_ptr, region_buffer, data_len);
// @Note: since 2025/09/18 with IPv6 supporting.
// if the region_buffer is NULL or the length is 0 we will create a buffer
// to hold the region info and the caller should call xdb_free to free the region info after finished use it.
char *r_buffer = *region_buffer;
if (r_buffer == NULL || length == 0) {
r_buffer = (char *) xdb_malloc(data_len + 1);
*region_buffer = r_buffer;
}
// auto append a NULL-end
r_buffer[data_len] = '\0';
err = read(xdb, data_ptr, r_buffer, data_len);
if (err != 0) {
err += 30;
goto done;
@ -165,8 +176,6 @@ done:
segment_buffer = NULL;
}
// auto append a NULL-end
region_buffer[data_len] = '\0';
return err;
}

View File

@ -223,6 +223,61 @@ XDB_PUBLIC(void) xdb_free_content(void *ptr) {
}
}
XDB_PUBLIC(int) xdb_verify_from_header(FILE *handle, xdb_header_t *header) {
int runtime_ptr_bytes = 0; // runtime ptr bytes
if (header->version == xdb_structure_20) {
runtime_ptr_bytes = 4;
} else if (header->version == xdb_structure_30) {
runtime_ptr_bytes = header->runtime_ptr_bytes;
} else {
return 2;
}
// 1, confirm the xdb file size.
// to ensure that the maximum file pointer does not overflow.
int err = fseek(handle, 0L, SEEK_END);
if (err != 0) {
return 3;
}
long int fileBytes = ftell(handle);
long int maxFilePtr = (1L << (runtime_ptr_bytes * 8)) - 1;
// printf("fileBytes: %ld, maxFilePtr: %ld\n", fileBytes, maxFilePtr);
if (fileBytes > maxFilePtr) {
return 4;
}
return 0;
}
XDB_PUBLIC(int) xdb_verify(FILE *handle) {
xdb_header_t *header = xdb_load_header(handle);
if (header == NULL) {
return 1;
}
int errcode = xdb_verify_from_header(handle, header);
if (errcode != 0) {
goto done;
}
// what next ?
done:
xdb_free_header(header);
return errcode;
}
XDB_PUBLIC(int) xdb_verify_from_file(const char *db_path) {
FILE *handle = fopen(db_path, "rb");
if (handle == NULL) {
return -1;
}
int r = xdb_verify(handle);
fclose(handle);
return r;
}
// --- End content buffer