ts-ip2region2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/README_CN.md +119 -0
- package/addon.cpp +258 -0
- package/binding.gyp +30 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/ip2region/Makefile +27 -0
- package/ip2region/ReadMe.md +341 -0
- package/ip2region/main.c +428 -0
- package/ip2region/test_util +0 -0
- package/ip2region/test_util.c +213 -0
- package/ip2region/xdb_api.h +272 -0
- package/ip2region/xdb_searcher.c +242 -0
- package/ip2region/xdb_util.c +496 -0
- package/package.json +78 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a Apache2.0-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
// ---
|
|
6
|
+
// @Author Lion <chenxin619315@gmail.com>
|
|
7
|
+
// @Date 2022/06/27
|
|
8
|
+
|
|
9
|
+
#ifndef C_IP2REGION_XDB_H
|
|
10
|
+
#define C_IP2REGION_XDB_H
|
|
11
|
+
|
|
12
|
+
#include <stdio.h>
|
|
13
|
+
#include <stdlib.h>
|
|
14
|
+
#include <string.h>
|
|
15
|
+
|
|
16
|
+
#if ( defined(WIN32) || defined(_WIN32) || defined(__WINDOWS_) || defined(WINNT) )
|
|
17
|
+
# define XDB_PUBLIC(type) extern __declspec(dllexport) type
|
|
18
|
+
# define XDB_PRIVATE(type) static type
|
|
19
|
+
# define XDB_WINDOWS
|
|
20
|
+
#ifndef WIN32_LEAN_AND_MEAN
|
|
21
|
+
#define WIN32_LEAN_AND_MEAN
|
|
22
|
+
#endif
|
|
23
|
+
#include <winsock2.h>
|
|
24
|
+
#include <ws2tcpip.h>
|
|
25
|
+
#include <windows.h>
|
|
26
|
+
#pragma comment(lib, "ws2_32.lib")
|
|
27
|
+
#elif ( defined(linux) || defined(_UNIX) || defined(__APPLE__) )
|
|
28
|
+
# define XDB_PUBLIC(type) extern type
|
|
29
|
+
# define XDB_PRIVATE(type) static inline type
|
|
30
|
+
# define XDB_LINUX
|
|
31
|
+
#include <sys/socket.h>
|
|
32
|
+
#include <netinet/in.h>
|
|
33
|
+
#include <arpa/inet.h>
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#define xdb_calloc( _blocks, _bytes ) calloc( _blocks, _bytes )
|
|
37
|
+
#define xdb_malloc( _bytes ) malloc( _bytes )
|
|
38
|
+
#define xdb_free( _ptr ) free( _ptr )
|
|
39
|
+
|
|
40
|
+
// public constants define
|
|
41
|
+
#define xdb_structure_20 2
|
|
42
|
+
#define xdb_structure_30 3
|
|
43
|
+
#define xdb_header_info_length 256
|
|
44
|
+
#define xdb_vector_index_rows 256
|
|
45
|
+
#define xdb_vector_index_cols 256
|
|
46
|
+
#define xdb_vector_index_size 8
|
|
47
|
+
#define xdb_v4_index_size 14 // 4 + 4 + 2 + 4
|
|
48
|
+
#define xdb_v6_index_size 38 // 16 + 16 + 2 + 4
|
|
49
|
+
|
|
50
|
+
// --- ip version info
|
|
51
|
+
#define xdb_ipv4_id 4
|
|
52
|
+
#define xdb_ipv6_id 6
|
|
53
|
+
#define xdb_ipv4_bytes 4
|
|
54
|
+
#define xdb_ipv6_bytes 16
|
|
55
|
+
// cache of vector_index_row × vector_index_rows × vector_index_size
|
|
56
|
+
#define xdb_vector_index_length 524288
|
|
57
|
+
|
|
58
|
+
// --- xdb buffer functions
|
|
59
|
+
|
|
60
|
+
// use the following buffer struct to wrap the binary buffer data
|
|
61
|
+
// since the buffer data could not be operated with the string API.
|
|
62
|
+
struct xdb_header {
|
|
63
|
+
unsigned short version;
|
|
64
|
+
unsigned short index_policy;
|
|
65
|
+
unsigned int created_at;
|
|
66
|
+
unsigned int start_index_ptr;
|
|
67
|
+
unsigned int end_index_ptr;
|
|
68
|
+
|
|
69
|
+
// since 3.0+ with IPv6 supporting
|
|
70
|
+
unsigned short ip_version;
|
|
71
|
+
unsigned short runtime_ptr_bytes;
|
|
72
|
+
|
|
73
|
+
// the original buffer
|
|
74
|
+
unsigned int length;
|
|
75
|
+
char buffer[xdb_header_info_length];
|
|
76
|
+
};
|
|
77
|
+
typedef struct xdb_header xdb_header_t;
|
|
78
|
+
|
|
79
|
+
XDB_PUBLIC(xdb_header_t *) xdb_load_header(FILE *);
|
|
80
|
+
|
|
81
|
+
XDB_PUBLIC(xdb_header_t *) xdb_load_header_from_file(const char *);
|
|
82
|
+
|
|
83
|
+
XDB_PUBLIC(void) xdb_free_header(void *);
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
// --- vector index buffer
|
|
87
|
+
struct xdb_vector_index {
|
|
88
|
+
unsigned int length;
|
|
89
|
+
char buffer[xdb_vector_index_length];
|
|
90
|
+
};
|
|
91
|
+
typedef struct xdb_vector_index xdb_vector_index_t;
|
|
92
|
+
|
|
93
|
+
XDB_PUBLIC(xdb_vector_index_t *) xdb_load_vector_index(FILE *);
|
|
94
|
+
|
|
95
|
+
XDB_PUBLIC(xdb_vector_index_t *) xdb_load_vector_index_from_file(const char *);
|
|
96
|
+
|
|
97
|
+
XDB_PUBLIC(void) xdb_free_vector_index(void *);
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
// --- content buffer
|
|
101
|
+
struct xdb_content {
|
|
102
|
+
unsigned int length;
|
|
103
|
+
char *buffer;
|
|
104
|
+
};
|
|
105
|
+
typedef struct xdb_content xdb_content_t;
|
|
106
|
+
|
|
107
|
+
XDB_PUBLIC(xdb_content_t *) xdb_load_content(FILE *);
|
|
108
|
+
|
|
109
|
+
XDB_PUBLIC(xdb_content_t *) xdb_load_content_from_file(const char *);
|
|
110
|
+
|
|
111
|
+
XDB_PUBLIC(void) xdb_free_content(void *);
|
|
112
|
+
|
|
113
|
+
// --- xdb verify
|
|
114
|
+
|
|
115
|
+
// Verify if the current Searcher could be used to search the specified xdb file.
|
|
116
|
+
// Why do we need this check ?
|
|
117
|
+
// The future features of the xdb impl may cause the current searcher not able to work properly.
|
|
118
|
+
//
|
|
119
|
+
// @Note: You Just need to check this ONCE when the service starts
|
|
120
|
+
// Or use another process (eg, A command) to check once Just to confirm the suitability.
|
|
121
|
+
XDB_PUBLIC(int) xdb_verify(FILE *);
|
|
122
|
+
|
|
123
|
+
XDB_PUBLIC(int) xdb_verify_from_header(FILE *handle, xdb_header_t *);
|
|
124
|
+
|
|
125
|
+
XDB_PUBLIC(int) xdb_verify_from_file(const char *);
|
|
126
|
+
|
|
127
|
+
// --- End xdb buffer
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
// types type define
|
|
131
|
+
typedef char string_ip_t;
|
|
132
|
+
typedef unsigned char bytes_ip_t;
|
|
133
|
+
|
|
134
|
+
// --- ip version
|
|
135
|
+
#define XDB_IPv4 (xdb_version_v4())
|
|
136
|
+
#define XDB_IPv6 (xdb_version_v6())
|
|
137
|
+
typedef int (* ip_compare_fn_t) (const bytes_ip_t *, int, const char *, int);
|
|
138
|
+
struct xdb_ip_version_entry {
|
|
139
|
+
int id; // version id
|
|
140
|
+
char *name; // version name
|
|
141
|
+
int bytes; // ip bytes number
|
|
142
|
+
int segment_index_size; // segment index size in bytes
|
|
143
|
+
|
|
144
|
+
// function to compare two ips
|
|
145
|
+
ip_compare_fn_t ip_compare;
|
|
146
|
+
};
|
|
147
|
+
typedef struct xdb_ip_version_entry xdb_version_t;
|
|
148
|
+
|
|
149
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_v4();
|
|
150
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_v6();
|
|
151
|
+
|
|
152
|
+
XDB_PUBLIC(int) xdb_version_is_v4(const xdb_version_t *);
|
|
153
|
+
XDB_PUBLIC(int) xdb_version_is_v6(const xdb_version_t *);
|
|
154
|
+
|
|
155
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_from_name(char *);
|
|
156
|
+
XDB_PUBLIC(xdb_version_t *) xdb_version_from_header(xdb_header_t *);
|
|
157
|
+
|
|
158
|
+
// --- END ip version
|
|
159
|
+
|
|
160
|
+
// --- xdb util functions
|
|
161
|
+
|
|
162
|
+
// to compatiable with the windows
|
|
163
|
+
// returns: 0 for ok and -1 for failed
|
|
164
|
+
XDB_PUBLIC(int) xdb_init_winsock();
|
|
165
|
+
XDB_PUBLIC(void) xdb_clean_winsock();
|
|
166
|
+
|
|
167
|
+
// get the current time in microseconds
|
|
168
|
+
XDB_PUBLIC(long) xdb_now();
|
|
169
|
+
|
|
170
|
+
// get unsigned long (4bytes) from a specified buffer start from the specified offset with little-endian
|
|
171
|
+
XDB_PUBLIC(unsigned int) xdb_le_get_uint32(const char *, int);
|
|
172
|
+
|
|
173
|
+
// get unsigned short (2bytes) from a specified buffer start from the specified offset with little-endian
|
|
174
|
+
XDB_PUBLIC(int) xdb_le_get_uint16(const char *, int);
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
// parse the specified IP address to byte array.
|
|
178
|
+
// returns: xdb_version_t for valid ipv4 / ipv6, or NULL for failed
|
|
179
|
+
XDB_PUBLIC(xdb_version_t *) xdb_parse_ip(const string_ip_t *, bytes_ip_t *, size_t);
|
|
180
|
+
|
|
181
|
+
// parse the specified IPv4 address to byte array
|
|
182
|
+
// returns: xdb_version_t for valid ipv4, or NULL for failed
|
|
183
|
+
XDB_PUBLIC(xdb_version_t *) xdb_parse_v4_ip(const string_ip_t *, bytes_ip_t *, size_t);
|
|
184
|
+
|
|
185
|
+
// parse the specified IPv6 address to byte array
|
|
186
|
+
// returns: xdb_version_t for valid ipv6, or NULL for failed
|
|
187
|
+
XDB_PUBLIC(xdb_version_t *) xdb_parse_v6_ip(const string_ip_t *, bytes_ip_t *, size_t);
|
|
188
|
+
|
|
189
|
+
// convert a specified ip bytes to humen-readable string.
|
|
190
|
+
// returns: 0 for success or -1 for failed.
|
|
191
|
+
XDB_PUBLIC(int) xdb_ip_to_string(const bytes_ip_t *, int, char *, size_t);
|
|
192
|
+
|
|
193
|
+
// ipv4 bytes to string
|
|
194
|
+
XDB_PUBLIC(int) xdb_v4_ip_to_string(const bytes_ip_t *, char *, size_t);
|
|
195
|
+
|
|
196
|
+
// ipv6 bytes to string
|
|
197
|
+
XDB_PUBLIC(int) xdb_v6_ip_to_string(const bytes_ip_t *, char *, size_t);
|
|
198
|
+
|
|
199
|
+
// compare the specified ip bytes with another ip bytes in the specified buff from offset.
|
|
200
|
+
// ip args must be the return value from #xdb_parse_ip.
|
|
201
|
+
// returns: -1 if ip1 < ip2, 1 if ip1 > ip2 or 0
|
|
202
|
+
XDB_PUBLIC(int) xdb_ip_sub_compare(const bytes_ip_t *, int, const char *, int);
|
|
203
|
+
|
|
204
|
+
// --- END xdb utils
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
// --- xdb searcher api
|
|
208
|
+
|
|
209
|
+
// xdb region info structure
|
|
210
|
+
#define xdb_region_buffer_wrapper 1
|
|
211
|
+
#define xdb_region_buffer_auto 2
|
|
212
|
+
struct xdb_region_buffer_entry {
|
|
213
|
+
int type; // buffer type
|
|
214
|
+
char *value; // region value
|
|
215
|
+
size_t length; // buffer length
|
|
216
|
+
};
|
|
217
|
+
typedef struct xdb_region_buffer_entry xdb_region_buffer_t;
|
|
218
|
+
|
|
219
|
+
// wrapper the region from a local stack buffer.
|
|
220
|
+
// returns: 0 for succeed or failed
|
|
221
|
+
XDB_PUBLIC(int) xdb_region_buffer_init(xdb_region_buffer_t *, char *, size_t);
|
|
222
|
+
|
|
223
|
+
// do the buffer alloc.
|
|
224
|
+
// returns: 0 for ok or failed
|
|
225
|
+
XDB_PUBLIC(int) xdb_region_buffer_alloc(xdb_region_buffer_t *, int);
|
|
226
|
+
|
|
227
|
+
XDB_PUBLIC(void) xdb_region_buffer_free(xdb_region_buffer_t *);
|
|
228
|
+
|
|
229
|
+
// xdb searcher structure
|
|
230
|
+
struct xdb_searcher_entry {
|
|
231
|
+
// ip version
|
|
232
|
+
xdb_version_t *version;
|
|
233
|
+
|
|
234
|
+
// xdb file handle
|
|
235
|
+
FILE *handle;
|
|
236
|
+
|
|
237
|
+
// header info
|
|
238
|
+
const char *header;
|
|
239
|
+
int io_count;
|
|
240
|
+
|
|
241
|
+
// vector index buffer cache.
|
|
242
|
+
// preload the vector index will reduce the number of IO operations
|
|
243
|
+
// thus speedup the search process.
|
|
244
|
+
const xdb_vector_index_t *v_index;
|
|
245
|
+
|
|
246
|
+
// content buffer.
|
|
247
|
+
// cache the whole xdb content.
|
|
248
|
+
const xdb_content_t *content;
|
|
249
|
+
};
|
|
250
|
+
typedef struct xdb_searcher_entry xdb_searcher_t;
|
|
251
|
+
|
|
252
|
+
// xdb searcher new api define
|
|
253
|
+
XDB_PUBLIC(int) xdb_new_with_file_only(xdb_version_t *, xdb_searcher_t *, const char *);
|
|
254
|
+
|
|
255
|
+
XDB_PUBLIC(int) xdb_new_with_vector_index(xdb_version_t *, xdb_searcher_t *, const char *, const xdb_vector_index_t *);
|
|
256
|
+
|
|
257
|
+
XDB_PUBLIC(int) xdb_new_with_buffer(xdb_version_t *, xdb_searcher_t *, const xdb_content_t *);
|
|
258
|
+
|
|
259
|
+
XDB_PUBLIC(void) xdb_close(void *);
|
|
260
|
+
|
|
261
|
+
// xdb searcher search api define
|
|
262
|
+
XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *, const string_ip_t *, xdb_region_buffer_t *);
|
|
263
|
+
|
|
264
|
+
XDB_PUBLIC(int) xdb_search(xdb_searcher_t *, const bytes_ip_t *, int, xdb_region_buffer_t *);
|
|
265
|
+
|
|
266
|
+
XDB_PUBLIC(xdb_version_t *) xdb_get_version(xdb_searcher_t *);
|
|
267
|
+
|
|
268
|
+
XDB_PUBLIC(int) xdb_get_io_count(xdb_searcher_t *);
|
|
269
|
+
|
|
270
|
+
// --- END xdb searcher api
|
|
271
|
+
|
|
272
|
+
#endif // C_IP2REGION_XDB_H
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a Apache2.0-style
|
|
3
|
+
// license that can be found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
// ---
|
|
6
|
+
// @Author Lion <chenxin619315@gmail.com>
|
|
7
|
+
// @Date 2022/06/27
|
|
8
|
+
|
|
9
|
+
#include "xdb_api.h"
|
|
10
|
+
|
|
11
|
+
// --- region buffer
|
|
12
|
+
XDB_PUBLIC(int) xdb_region_buffer_init(xdb_region_buffer_t *region, char *buffer, size_t length) {
|
|
13
|
+
if (buffer == NULL) {
|
|
14
|
+
region->type = xdb_region_buffer_auto;
|
|
15
|
+
region->length = 0;
|
|
16
|
+
} else if (length <= 0) {
|
|
17
|
+
return 1;
|
|
18
|
+
} else {
|
|
19
|
+
region->type = xdb_region_buffer_wrapper;
|
|
20
|
+
region->length = length;
|
|
21
|
+
memset(buffer, 0x00, length); // zero-fill the buffer
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
region->value = buffer;
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
XDB_PUBLIC(int) xdb_region_buffer_alloc(xdb_region_buffer_t *region, int length) {
|
|
29
|
+
if (length <= 0) {
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// no allocation supports for the buffer wapper
|
|
34
|
+
if (region->type == xdb_region_buffer_wrapper) {
|
|
35
|
+
if (length >= region->length) {
|
|
36
|
+
return 2;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
region->value[length] = '\0';
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ensure that the value were freed
|
|
44
|
+
// by calling #xdb_region_buffer_free
|
|
45
|
+
if (region->value != NULL) {
|
|
46
|
+
return 3;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
char *ptr = (char *) xdb_malloc(length + 1);
|
|
50
|
+
if (ptr == NULL) {
|
|
51
|
+
return 4;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
ptr[length] = '\0'; // NULL-end
|
|
55
|
+
region->value = ptr;
|
|
56
|
+
region->length = length;
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
XDB_PUBLIC(void) xdb_region_buffer_free(xdb_region_buffer_t *region) {
|
|
61
|
+
if (region->type == xdb_region_buffer_auto) {
|
|
62
|
+
xdb_free(region->value);
|
|
63
|
+
region->value = NULL;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// --- END region buffer
|
|
68
|
+
|
|
69
|
+
// internal function prototype define
|
|
70
|
+
XDB_PRIVATE(int) read(xdb_searcher_t *, long offset, char *, size_t length);
|
|
71
|
+
|
|
72
|
+
XDB_PRIVATE(int) xdb_new_base(xdb_version_t *version, xdb_searcher_t *xdb, const char *db_path, const xdb_vector_index_t *v_index, const xdb_content_t *c_buffer) {
|
|
73
|
+
memset(xdb, 0x00, sizeof(xdb_searcher_t));
|
|
74
|
+
|
|
75
|
+
// set the version
|
|
76
|
+
xdb->version = version;
|
|
77
|
+
|
|
78
|
+
// check the content buffer first
|
|
79
|
+
if (c_buffer != NULL) {
|
|
80
|
+
xdb->v_index = NULL;
|
|
81
|
+
xdb->content = c_buffer;
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// open the xdb binary file
|
|
86
|
+
FILE *handle = fopen(db_path, "rb");
|
|
87
|
+
if (handle == NULL) {
|
|
88
|
+
return 1;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
xdb->handle = handle;
|
|
92
|
+
xdb->v_index = v_index;
|
|
93
|
+
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// xdb searcher new api define
|
|
98
|
+
XDB_PUBLIC(int) xdb_new_with_file_only(xdb_version_t *version, xdb_searcher_t *xdb, const char *db_path) {
|
|
99
|
+
return xdb_new_base(version, xdb, db_path, NULL, NULL);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
XDB_PUBLIC(int) xdb_new_with_vector_index(xdb_version_t *version, xdb_searcher_t *xdb, const char *db_path, const xdb_vector_index_t *v_index) {
|
|
103
|
+
return xdb_new_base(version, xdb, db_path, v_index, NULL);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
XDB_PUBLIC(int) xdb_new_with_buffer(xdb_version_t *version, xdb_searcher_t *xdb, const xdb_content_t *c_buffer) {
|
|
107
|
+
return xdb_new_base(version, xdb, NULL, NULL, c_buffer);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
XDB_PUBLIC(void) xdb_close(void *ptr) {
|
|
111
|
+
xdb_searcher_t *xdb = (xdb_searcher_t *) ptr;
|
|
112
|
+
if (xdb->handle != NULL) {
|
|
113
|
+
fclose(xdb->handle);
|
|
114
|
+
xdb->handle = NULL;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// --- xdb searcher search api define
|
|
119
|
+
|
|
120
|
+
XDB_PUBLIC(int) xdb_search_by_string(xdb_searcher_t *xdb, const string_ip_t *ip_string, xdb_region_buffer_t *region) {
|
|
121
|
+
bytes_ip_t ip_bytes[16] = {'\0'};
|
|
122
|
+
xdb_version_t *version = xdb_parse_ip(ip_string, ip_bytes, sizeof(ip_bytes));
|
|
123
|
+
if (version == NULL) {
|
|
124
|
+
return 10;
|
|
125
|
+
} else {
|
|
126
|
+
return xdb_search(xdb, ip_bytes, version->bytes, region);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
XDB_PUBLIC(int) xdb_search(xdb_searcher_t *xdb, const bytes_ip_t *ip_bytes, int ip_len, xdb_region_buffer_t *region) {
|
|
131
|
+
int il0, il1, idx, err, bytes, d_bytes;
|
|
132
|
+
register int seg_index_size, l, h, m, p;
|
|
133
|
+
unsigned int s_ptr, e_ptr, data_ptr, data_len;
|
|
134
|
+
char vector_buffer[xdb_vector_index_size];
|
|
135
|
+
char segment_buffer[xdb_v6_index_size];
|
|
136
|
+
|
|
137
|
+
// ip version check
|
|
138
|
+
if (ip_len != xdb->version->bytes) {
|
|
139
|
+
return -1;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// some resets
|
|
143
|
+
err = 0;
|
|
144
|
+
data_len = 0;
|
|
145
|
+
bytes = xdb->version->bytes;
|
|
146
|
+
d_bytes = xdb->version->bytes << 1;
|
|
147
|
+
xdb->io_count = 0;
|
|
148
|
+
|
|
149
|
+
// locate the segment index block based on the vector index
|
|
150
|
+
il0 = (int) (ip_bytes[0]);
|
|
151
|
+
il1 = (int) (ip_bytes[1]);
|
|
152
|
+
idx = il0 * xdb_vector_index_cols * xdb_vector_index_size + il1 * xdb_vector_index_size;
|
|
153
|
+
if (xdb->v_index != NULL) {
|
|
154
|
+
s_ptr = xdb_le_get_uint32(xdb->v_index->buffer, idx);
|
|
155
|
+
e_ptr = xdb_le_get_uint32(xdb->v_index->buffer, idx + 4);
|
|
156
|
+
} else if (xdb->content != NULL) {
|
|
157
|
+
s_ptr = xdb_le_get_uint32(xdb->content->buffer, xdb_header_info_length + idx);
|
|
158
|
+
e_ptr = xdb_le_get_uint32(xdb->content->buffer, xdb_header_info_length + idx + 4);
|
|
159
|
+
} else {
|
|
160
|
+
err = read(xdb, xdb_header_info_length + idx, vector_buffer, sizeof(vector_buffer));
|
|
161
|
+
if (err != 0) {
|
|
162
|
+
return 10 + err;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
s_ptr = xdb_le_get_uint32(vector_buffer, 0);
|
|
166
|
+
e_ptr = xdb_le_get_uint32(vector_buffer, 4);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// printf("s_ptr=%u, e_ptr=%u\n", s_ptr, e_ptr);
|
|
170
|
+
// binary search to get the final region info
|
|
171
|
+
// segment_buffer = xdb_malloc(seg_index_size);
|
|
172
|
+
seg_index_size = xdb->version->segment_index_size;
|
|
173
|
+
data_len = 0, data_ptr = 0;
|
|
174
|
+
l = 0, h = ((int) (e_ptr - s_ptr)) / seg_index_size;
|
|
175
|
+
while (l <= h) {
|
|
176
|
+
m = (l + h) >> 1;
|
|
177
|
+
p = s_ptr + m * seg_index_size;
|
|
178
|
+
|
|
179
|
+
// read the segment index item
|
|
180
|
+
err = read(xdb, p, segment_buffer, seg_index_size);
|
|
181
|
+
if (err != 0) {
|
|
182
|
+
return 20 + err;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// decode the data fields as needed
|
|
186
|
+
if (xdb->version->ip_compare(ip_bytes, bytes, segment_buffer, 0) < 0) {
|
|
187
|
+
h = m - 1;
|
|
188
|
+
} else if (xdb->version->ip_compare(ip_bytes, bytes, segment_buffer, bytes) > 0) {
|
|
189
|
+
l = m + 1;
|
|
190
|
+
} else {
|
|
191
|
+
data_len = xdb_le_get_uint16(segment_buffer, d_bytes);
|
|
192
|
+
data_ptr = xdb_le_get_uint32(segment_buffer, d_bytes + 2);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// printf("data_len=%u, data_ptr=%u\n", data_len, data_ptr);
|
|
198
|
+
if (data_len == 0) {
|
|
199
|
+
return 100;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// buffer alloc checking
|
|
203
|
+
err = xdb_region_buffer_alloc(region, data_len);
|
|
204
|
+
if (err != 0) {
|
|
205
|
+
return 100 + err;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
err = read(xdb, data_ptr, region->value, data_len);
|
|
209
|
+
if (err != 0) {
|
|
210
|
+
return 30 + err;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return err;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
XDB_PRIVATE(int) read(xdb_searcher_t *xdb, long offset, char *buffer, size_t length) {
|
|
217
|
+
// check the xdb content cache first
|
|
218
|
+
if (xdb->content != NULL) {
|
|
219
|
+
memcpy(buffer, xdb->content->buffer + offset, length);
|
|
220
|
+
return 0;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// seek to the offset
|
|
224
|
+
if (fseek(xdb->handle, offset, SEEK_SET) == -1) {
|
|
225
|
+
return 1;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
xdb->io_count++;
|
|
229
|
+
if (fread(buffer, 1, length, xdb->handle) != length) {
|
|
230
|
+
return 2;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
XDB_PUBLIC(xdb_version_t *) xdb_get_version(xdb_searcher_t *xdb) {
|
|
237
|
+
return xdb->version;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
XDB_PUBLIC(int) xdb_get_io_count(xdb_searcher_t *xdb) {
|
|
241
|
+
return xdb->io_count;
|
|
242
|
+
}
|