mirror of
https://github.com/lionsoul2014/ip2region.git
synced 2025-12-08 19:25:22 +00:00
C binding is ready for IPv6
This commit is contained in:
parent
8fbdf82797
commit
dff3084b93
@ -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, ®ion_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, ®ion_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.
@ -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 *);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user