1 /**
2 * Copyright (C) 2008 Happy Fish / YuQing
3 *
4 * FastDFS may be copied only under the terms of the GNU General
5 * Public License V3, which may be found in the FastDFS source kit.
6 * Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
7 **/
8 
9 #include <stdlib.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <netdb.h>
13 #include "fastcommon/logger.h"
14 #include "fastcommon/sockopt.h"
15 #include "fastcommon/shared_func.h"
16 #include "fastcommon/local_ip_func.h"
17 #include "tracker_proto.h"
18 #include "fdfs_global.h"
19 #include "fdfs_shared_func.h"
20 
21 
fdfs_server_contain(TrackerServerInfo * pServerInfo,const char * target_ip,const int target_port)22 bool fdfs_server_contain(TrackerServerInfo *pServerInfo,
23         const char *target_ip, const int target_port)
24 {
25 	ConnectionInfo *conn;
26 	ConnectionInfo *end;
27 
28     if (pServerInfo->count == 1)
29     {
30 		return FC_CONNECTION_SERVER_EQUAL(pServerInfo->connections[0],
31                 target_ip, target_port);
32     }
33     else if (pServerInfo->count == 2)
34     {
35 		return FC_CONNECTION_SERVER_EQUAL(pServerInfo->connections[0],
36                 target_ip, target_port) ||
37             FC_CONNECTION_SERVER_EQUAL(pServerInfo->connections[1],
38                     target_ip, target_port);
39     }
40 
41 	end = pServerInfo->connections + pServerInfo->count;
42 	for (conn=pServerInfo->connections; conn<end; conn++)
43     {
44 		if (FC_CONNECTION_SERVER_EQUAL(*conn, target_ip, target_port))
45         {
46             return true;
47         }
48     }
49 
50     return false;
51 }
52 
fdfs_server_contain_ex(TrackerServerInfo * pServer1,TrackerServerInfo * pServer2)53 bool fdfs_server_contain_ex(TrackerServerInfo *pServer1,
54         TrackerServerInfo *pServer2)
55 {
56 	ConnectionInfo *conn;
57 	ConnectionInfo *end;
58 
59     if (pServer1->count == 1)
60     {
61         return fdfs_server_contain1(pServer2, pServer1->connections + 0);
62     }
63     else if (pServer1->count == 2)
64     {
65         if (fdfs_server_contain1(pServer2, pServer1->connections + 0))
66         {
67             return true;
68         }
69         return fdfs_server_contain1(pServer2, pServer1->connections + 1);
70     }
71 
72 	end = pServer1->connections + pServer1->count;
73 	for (conn=pServer1->connections; conn<end; conn++)
74     {
75 		if (fdfs_server_contain1(pServer2, conn))
76         {
77             return true;
78         }
79     }
80 
81     return false;
82 }
83 
fdfs_server_equal(TrackerServerInfo * pServer1,TrackerServerInfo * pServer2)84 bool fdfs_server_equal(TrackerServerInfo *pServer1,
85         TrackerServerInfo *pServer2)
86 {
87 	ConnectionInfo *conn;
88 	ConnectionInfo *end;
89 
90     if (pServer1->count != pServer2->count)
91     {
92         return false;
93     }
94 
95     if (pServer1->count == 1)
96     {
97         return (pServer1->connections->port == pServer2->connections->port &&
98             strcmp(pServer1->connections->ip_addr, pServer2->connections->ip_addr) == 0);
99     }
100 
101 	end = pServer1->connections + pServer1->count;
102 	for (conn=pServer1->connections; conn<end; conn++)
103     {
104 		if (!fdfs_server_contain1(pServer2, conn))
105         {
106             return false;
107         }
108     }
109 
110     return true;
111 }
112 
fdfs_server_contain_local_service(TrackerServerInfo * pServerInfo,const int target_port)113 bool fdfs_server_contain_local_service(TrackerServerInfo *pServerInfo,
114         const int target_port)
115 {
116     const char *current_ip;
117 
118     current_ip = get_first_local_ip();
119     while (current_ip != NULL)
120     {
121         if (fdfs_server_contain(pServerInfo, current_ip, target_port))
122         {
123             return true;
124         }
125         current_ip = get_next_local_ip(current_ip);
126     }
127 
128     return false;
129 }
130 
fdfs_tracker_group_get_server(TrackerServerGroup * pGroup,const char * target_ip,const int target_port)131 TrackerServerInfo *fdfs_tracker_group_get_server(TrackerServerGroup *pGroup,
132         const char *target_ip, const int target_port)
133 {
134     TrackerServerInfo *pServer;
135     TrackerServerInfo *pEnd;
136 
137     pEnd = pGroup->servers + pGroup->server_count;
138     for (pServer=pGroup->servers; pServer<pEnd; pServer++)
139     {
140         if (fdfs_server_contain(pServer, target_ip, target_port))
141         {
142             return pServer;
143         }
144     }
145 
146     return NULL;
147 }
148 
fdfs_server_sock_reset(TrackerServerInfo * pServerInfo)149 void fdfs_server_sock_reset(TrackerServerInfo *pServerInfo)
150 {
151 	ConnectionInfo *conn;
152 	ConnectionInfo *end;
153 
154     if (pServerInfo->count == 1)
155     {
156 		pServerInfo->connections[0].sock = -1;
157     }
158     else if (pServerInfo->count == 2)
159     {
160 		pServerInfo->connections[0].sock = -1;
161 		pServerInfo->connections[1].sock = -1;
162     }
163     else
164     {
165         end = pServerInfo->connections + pServerInfo->count;
166         for (conn=pServerInfo->connections; conn<end; conn++)
167         {
168             conn->sock = -1;
169         }
170     }
171 }
172 
fdfs_get_tracker_leader_index_ex(TrackerServerGroup * pServerGroup,const char * leaderIp,const int leaderPort)173 int fdfs_get_tracker_leader_index_ex(TrackerServerGroup *pServerGroup,
174 		const char *leaderIp, const int leaderPort)
175 {
176 	TrackerServerInfo *pServer;
177 	TrackerServerInfo *pEnd;
178 
179 	if (pServerGroup->server_count == 0)
180 	{
181 		return -1;
182 	}
183 
184 	pEnd = pServerGroup->servers + pServerGroup->server_count;
185 	for (pServer=pServerGroup->servers; pServer<pEnd; pServer++)
186 	{
187         if (fdfs_server_contain(pServer, leaderIp, leaderPort))
188 		{
189 			return pServer - pServerGroup->servers;
190 		}
191 	}
192 
193 	return -1;
194 }
195 
fdfs_parse_storage_reserved_space(IniContext * pIniContext,FDFSStorageReservedSpace * pStorageReservedSpace)196 int fdfs_parse_storage_reserved_space(IniContext *pIniContext,
197 		FDFSStorageReservedSpace *pStorageReservedSpace)
198 {
199 	int result;
200 	int len;
201 	char *pReservedSpaceStr;
202 	int64_t storage_reserved;
203 
204 	pReservedSpaceStr = iniGetStrValue(NULL, \
205 			"reserved_storage_space", pIniContext);
206 	if (pReservedSpaceStr == NULL)
207 	{
208 		pStorageReservedSpace->flag = \
209 				TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB;
210 		pStorageReservedSpace->rs.mb = FDFS_DEF_STORAGE_RESERVED_MB;
211 		return 0;
212 	}
213 	if (*pReservedSpaceStr == '\0')
214 	{
215 		logError("file: "__FILE__", line: %d, " \
216 			"item \"reserved_storage_space\" is empty!", \
217 			__LINE__);
218 		return EINVAL;
219 	}
220 
221 	len = strlen(pReservedSpaceStr);
222 	if (*(pReservedSpaceStr + len - 1) == '%')
223 	{
224 		char *endptr;
225 		pStorageReservedSpace->flag = \
226 				TRACKER_STORAGE_RESERVED_SPACE_FLAG_RATIO;
227 		endptr = NULL;
228 		*(pReservedSpaceStr + len - 1) = '\0';
229 		pStorageReservedSpace->rs.ratio = \
230 					strtod(pReservedSpaceStr, &endptr);
231 		if (endptr != NULL && *endptr != '\0')
232 		{
233 			logError("file: "__FILE__", line: %d, " \
234 				"item \"reserved_storage_space\": %s%%"\
235 				" is invalid!", __LINE__, \
236 				pReservedSpaceStr);
237 			return EINVAL;
238 		}
239 
240 		if (pStorageReservedSpace->rs.ratio <= 0.00 || \
241 			pStorageReservedSpace->rs.ratio >= 100.00)
242 		{
243 			logError("file: "__FILE__", line: %d, " \
244 				"item \"reserved_storage_space\": %s%%"\
245 				" is invalid!", __LINE__, \
246 				pReservedSpaceStr);
247 			return EINVAL;
248 		}
249 
250 		pStorageReservedSpace->rs.ratio /= 100.00;
251 		return 0;
252 	}
253 
254 	if ((result=parse_bytes(pReservedSpaceStr, 1, &storage_reserved)) != 0)
255 	{
256 		return result;
257 	}
258 
259 	pStorageReservedSpace->flag = TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB;
260 	pStorageReservedSpace->rs.mb = storage_reserved / FDFS_ONE_MB;
261 	return 0;
262 }
263 
fdfs_storage_reserved_space_to_string(FDFSStorageReservedSpace * pStorageReservedSpace,char * buff)264 const char *fdfs_storage_reserved_space_to_string(FDFSStorageReservedSpace \
265 			*pStorageReservedSpace, char *buff)
266 {
267 	if (pStorageReservedSpace->flag == \
268 			TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB)
269 	{
270 		sprintf(buff, "%d MB", pStorageReservedSpace->rs.mb);
271 	}
272 	else
273 	{
274 		sprintf(buff, "%.2f%%", 100.00 * \
275 			pStorageReservedSpace->rs.ratio);
276 	}
277 
278 	return buff;
279 }
280 
fdfs_storage_reserved_space_to_string_ex(const bool flag,const int space_mb,const int total_mb,const double space_ratio,char * buff)281 const char *fdfs_storage_reserved_space_to_string_ex(const bool flag, \
282 	const int space_mb, const int total_mb, const double space_ratio, \
283 	char *buff)
284 {
285 	if (flag == TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB)
286 	{
287 		sprintf(buff, "%d MB", space_mb);
288 	}
289 	else
290 	{
291 		sprintf(buff, "%d MB(%.2f%%)", (int)(total_mb * space_ratio), \
292 			 100.00 * space_ratio);
293 	}
294 
295 	return buff;
296 }
297 
fdfs_get_storage_reserved_space_mb(const int total_mb,FDFSStorageReservedSpace * pStorageReservedSpace)298 int fdfs_get_storage_reserved_space_mb(const int total_mb, \
299 		FDFSStorageReservedSpace *pStorageReservedSpace)
300 {
301 	if (pStorageReservedSpace->flag == \
302 			TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB)
303 	{
304 		return pStorageReservedSpace->rs.mb;
305 	}
306 	else
307 	{
308 		return (int)(total_mb * pStorageReservedSpace->rs.ratio);
309 	}
310 }
311 
fdfs_check_reserved_space(FDFSGroupInfo * pGroup,FDFSStorageReservedSpace * pStorageReservedSpace)312 bool fdfs_check_reserved_space(FDFSGroupInfo *pGroup, \
313 	FDFSStorageReservedSpace *pStorageReservedSpace)
314 {
315 	if (pStorageReservedSpace->flag == \
316 			TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB)
317 	{
318 		return pGroup->free_mb > pStorageReservedSpace->rs.mb;
319 	}
320 	else
321 	{
322 		if (pGroup->total_mb == 0)
323 		{
324 			return false;
325 		}
326 
327 		/*
328 		logInfo("storage=%.4f, rs.ratio=%.4f",
329 			((double)pGroup->free_mb / (double)pGroup->total_mb),
330 			pStorageReservedSpace->rs.ratio);
331 		*/
332 
333 		return ((double)pGroup->free_mb / (double)pGroup->total_mb) > \
334 			pStorageReservedSpace->rs.ratio;
335 	}
336 }
337 
fdfs_check_reserved_space_trunk(FDFSGroupInfo * pGroup,FDFSStorageReservedSpace * pStorageReservedSpace)338 bool fdfs_check_reserved_space_trunk(FDFSGroupInfo *pGroup, \
339 	FDFSStorageReservedSpace *pStorageReservedSpace)
340 {
341 	if (pStorageReservedSpace->flag == \
342 			TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB)
343 	{
344 		return (pGroup->free_mb + pGroup->trunk_free_mb >
345 			pStorageReservedSpace->rs.mb);
346 	}
347 	else
348 	{
349 		if (pGroup->total_mb == 0)
350 		{
351 			return false;
352 		}
353 
354 		/*
355 		logInfo("storage trunk=%.4f, rs.ratio=%.4f",
356 		((double)(pGroup->free_mb + pGroup->trunk_free_mb) / \
357 		(double)pGroup->total_mb), pStorageReservedSpace->rs.ratio);
358 		*/
359 
360 		return ((double)(pGroup->free_mb + pGroup->trunk_free_mb) / \
361 		(double)pGroup->total_mb) > pStorageReservedSpace->rs.ratio;
362 	}
363 }
364 
fdfs_check_reserved_space_path(const int64_t total_mb,const int64_t free_mb,const int avg_mb,FDFSStorageReservedSpace * pStorageReservedSpace)365 bool fdfs_check_reserved_space_path(const int64_t total_mb, \
366 	const int64_t free_mb, const int avg_mb, \
367 	FDFSStorageReservedSpace *pStorageReservedSpace)
368 {
369 	if (pStorageReservedSpace->flag == \
370 			TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB)
371 	{
372 		return free_mb > avg_mb;
373 	}
374 	else
375 	{
376 		if (total_mb == 0)
377 		{
378 			return false;
379 		}
380 
381 		/*
382 		logInfo("storage path, free_mb=%"PRId64 \
383 			", total_mb=%"PRId64", " \
384 			"real ratio=%.4f, rs.ratio=%.4f", \
385 			free_mb, total_mb, ((double)free_mb / total_mb), \
386 			pStorageReservedSpace->rs.ratio);
387 		*/
388 
389 		return ((double)free_mb / (double)total_mb) > \
390 			pStorageReservedSpace->rs.ratio;
391 	}
392 }
393 
fdfs_connection_pool_init(const char * config_filename,IniContext * pItemContext)394 int fdfs_connection_pool_init(const char *config_filename, \
395 		IniContext *pItemContext)
396 {
397 	g_use_connection_pool = iniGetBoolValue(NULL, "use_connection_pool", \
398 				pItemContext, false);
399 	if (!g_use_connection_pool)
400 	{
401 		return 0;
402 	}
403 
404 	g_connection_pool_max_idle_time = iniGetIntValue(NULL, \
405 			"connection_pool_max_idle_time", \
406 			pItemContext, 3600);
407 	if (g_connection_pool_max_idle_time <= 0)
408 	{
409 		logError("file: "__FILE__", line: %d, " \
410 			"connection_pool_max_idle_time: %d of conf " \
411 			"filename: \"%s\" is invalid!", __LINE__, \
412 			g_connection_pool_max_idle_time, config_filename);
413 		return EINVAL;
414 	}
415 
416 	return conn_pool_init(&g_connection_pool, g_fdfs_connect_timeout, \
417         		0, g_connection_pool_max_idle_time);
418 }
419 
fdfs_connection_pool_destroy()420 void fdfs_connection_pool_destroy()
421 {
422 	conn_pool_destroy(&g_connection_pool);
423 }
424 
fdfs_set_log_rotate_size(LogContext * pContext,const int64_t log_rotate_size)425 void fdfs_set_log_rotate_size(LogContext *pContext, const int64_t log_rotate_size)
426 {
427 	if (log_rotate_size > 0)
428 	{
429 		pContext->rotate_size = log_rotate_size;
430 		log_set_rotate_time_format(pContext, "%Y%m%d_%H%M%S");
431 	}
432 	else
433 	{
434 		pContext->rotate_size = 0;
435 		log_set_rotate_time_format(pContext, "%Y%m%d");
436 	}
437 }
438 
fdfs_parse_server_info_ex(char * server_str,const int default_port,TrackerServerInfo * pServer,const bool resolve)439 int fdfs_parse_server_info_ex(char *server_str, const int default_port,
440         TrackerServerInfo *pServer, const bool resolve)
441 {
442 	char *pColon;
443     char *hosts[FDFS_MULTI_IP_MAX_COUNT];
444     ConnectionInfo *conn;
445     int port;
446     int i;
447 
448     memset(pServer, 0, sizeof(TrackerServerInfo));
449     if ((pColon=strrchr(server_str, ':')) == NULL)
450     {
451         logInfo("file: "__FILE__", line: %d, "
452                 "no port part in %s, set port to %d",
453                 __LINE__, server_str, default_port);
454         port = default_port;
455     }
456     else
457     {
458         *pColon = '\0';
459         port = atoi(pColon + 1);
460     }
461 
462     conn = pServer->connections;
463     pServer->count =  splitEx(server_str, ',',
464             hosts, FDFS_MULTI_IP_MAX_COUNT);
465     for (i=0; i<pServer->count; i++)
466     {
467         if (resolve)
468         {
469             if (getIpaddrByName(hosts[i], conn->ip_addr,
470                         sizeof(conn->ip_addr)) == INADDR_NONE)
471             {
472                 logError("file: "__FILE__", line: %d, "
473                         "host \"%s\" is invalid, error info: %s",
474                         __LINE__, hosts[i], hstrerror(h_errno));
475                 return EINVAL;
476             }
477         }
478         else
479         {
480             snprintf(conn->ip_addr, sizeof(conn->ip_addr), "%s", hosts[i]);
481         }
482         conn->port = port;
483         conn->sock = -1;
484         conn++;
485     }
486 
487     return 0;
488 }
489 
fdfs_server_info_to_string_ex(const TrackerServerInfo * pServer,const int port,char * buff,const int buffSize)490 int fdfs_server_info_to_string_ex(const TrackerServerInfo *pServer,
491         const int port, char *buff, const int buffSize)
492 {
493 	const ConnectionInfo *conn;
494 	const ConnectionInfo *end;
495     int len;
496 
497     if (pServer->count <= 0)
498     {
499         *buff = '\0';
500         return 0;
501     }
502     if (pServer->count == 1)
503     {
504         return snprintf(buff, buffSize, "%s:%d",
505                 pServer->connections[0].ip_addr, port);
506     }
507 
508     len = snprintf(buff, buffSize, "%s", pServer->connections[0].ip_addr);
509 	end = pServer->connections + pServer->count;
510 	for (conn=pServer->connections + 1; conn<end; conn++)
511     {
512         len += snprintf(buff + len, buffSize - len, ",%s", conn->ip_addr);
513     }
514     len += snprintf(buff + len, buffSize - len, ":%d", port);
515     return len;
516 }
517 
fdfs_get_ip_type(const char * ip)518 int fdfs_get_ip_type(const char* ip)
519 {
520     if (ip == NULL || (int)strlen(ip) < 8)
521     {
522         return FDFS_IP_TYPE_UNKNOWN;
523     }
524 
525     if (memcmp(ip, "10.", 3) == 0)
526     {
527         return FDFS_IP_TYPE_PRIVATE_10;
528     }
529     if (memcmp(ip, "192.168.", 8) == 0)
530     {
531         return FDFS_IP_TYPE_PRIVATE_192;
532     }
533 
534     if (memcmp(ip, "172.", 4) == 0)
535     {
536         int b;
537         b = atoi(ip + 4);
538         if (b >= 16 && b < 32)
539         {
540             return FDFS_IP_TYPE_PRIVATE_172;
541         }
542     }
543 
544     return FDFS_IP_TYPE_OUTER;
545 }
546 
fdfs_check_server_ips(const TrackerServerInfo * pServer,char * error_info,const int error_size)547 int fdfs_check_server_ips(const TrackerServerInfo *pServer,
548         char *error_info, const int error_size)
549 {
550     int type0;
551     int type1;
552     if (pServer->count == 1)
553     {
554         *error_info = '\0';
555         return 0;
556     }
557 
558     if (pServer->count <= 0)
559     {
560         logError("file: "__FILE__", line: %d, "
561                 "empty server", __LINE__);
562         return EINVAL;
563     }
564 
565     if (pServer->count > FDFS_MULTI_IP_MAX_COUNT)
566     {
567         snprintf(error_info, error_size,
568                 "too many server ip addresses: %d, exceeds %d",
569                 pServer->count, FDFS_MULTI_IP_MAX_COUNT);
570         return EINVAL;
571     }
572 
573     type0 = fdfs_get_ip_type(pServer->connections[0].ip_addr);
574     type1 = fdfs_get_ip_type(pServer->connections[1].ip_addr);
575     if (type0 == type1)
576     {
577         snprintf(error_info, error_size,
578                 "invalid ip addresses %s and %s, "
579                 "one MUST be an inner IP and another is a outer IP, "
580                 "or two different types of inner IP addresses",
581                 pServer->connections[0].ip_addr,
582                 pServer->connections[1].ip_addr);
583         return EINVAL;
584     }
585 
586     *error_info = '\0';
587     return 0;
588 }
589 
fdfs_parse_multi_ips_ex(char * ip_str,FDFSMultiIP * ip_addrs,char * error_info,const int error_size,const bool resolve)590 int fdfs_parse_multi_ips_ex(char *ip_str, FDFSMultiIP *ip_addrs,
591         char *error_info, const int error_size, const bool resolve)
592 {
593     char *hosts[FDFS_MULTI_IP_MAX_COUNT];
594     int i;
595 
596     ip_addrs->index = 0;
597     ip_addrs->count = splitEx(ip_str, ',', hosts, FDFS_MULTI_IP_MAX_COUNT);
598     for (i=0; i<ip_addrs->count; i++)
599     {
600         if (resolve)
601         {
602             if (getIpaddrByName(hosts[i], ip_addrs->ips[i].address,
603                         sizeof(ip_addrs->ips[i].address)) == INADDR_NONE)
604             {
605                 snprintf(error_info, error_size,
606                         "host \"%s\" is invalid, error info: %s",
607                         hosts[i], hstrerror(h_errno));
608                 return EINVAL;
609             }
610         }
611         else
612         {
613             snprintf(ip_addrs->ips[i].address,
614                     sizeof(ip_addrs->ips[i].address), "%s", hosts[i]);
615         }
616 
617         ip_addrs->ips[i].type = fdfs_get_ip_type(ip_addrs->ips[i].address);
618         if (ip_addrs->ips[i].type == FDFS_IP_TYPE_UNKNOWN)
619         {
620             snprintf(error_info, error_size,
621                     "ip address \"%s\" is invalid",
622                     ip_addrs->ips[i].address);
623             return EINVAL;
624         }
625     }
626 
627     *error_info = '\0';
628     return 0;
629 }
630 
fdfs_multi_ips_to_string_ex(const FDFSMultiIP * ip_addrs,const char seperator,char * buff,const int buffSize)631 int fdfs_multi_ips_to_string_ex(const FDFSMultiIP *ip_addrs,
632         const char seperator, char *buff, const int buffSize)
633 {
634     int i;
635     int len;
636 
637     if (ip_addrs->count <= 0)
638     {
639         *buff = '\0';
640         return 0;
641     }
642     if (ip_addrs->count == 1)
643     {
644         return snprintf(buff, buffSize, "%s",
645                 ip_addrs->ips[0].address);
646     }
647 
648     len = snprintf(buff, buffSize, "%s", ip_addrs->ips[0].address);
649 	for (i=1; i<ip_addrs->count; i++)
650     {
651         len += snprintf(buff + len, buffSize - len, "%c%s",
652                 seperator, ip_addrs->ips[i].address);
653     }
654     return len;
655 }
656 
fdfs_get_ipaddr_by_peer_ip(const FDFSMultiIP * ip_addrs,const char * client_ip)657 const char *fdfs_get_ipaddr_by_peer_ip(const FDFSMultiIP *ip_addrs,
658         const char *client_ip)
659 {
660     int ip_type;
661     int index;
662     if (ip_addrs->count == 1)
663     {
664         return ip_addrs->ips[0].address;
665     }
666 
667     if (ip_addrs->count <= 0)
668     {
669         return "";
670     }
671 
672     ip_type = fdfs_get_ip_type(client_ip);
673     index = ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER].type == ip_type ?
674         FDFS_MULTI_IP_INDEX_OUTER : FDFS_MULTI_IP_INDEX_INNER;
675     return ip_addrs->ips[index].address;
676 }
677 
fdfs_check_and_format_ips(FDFSMultiIP * ip_addrs,char * error_info,const int error_size)678 int fdfs_check_and_format_ips(FDFSMultiIP *ip_addrs,
679         char *error_info, const int error_size)
680 {
681     FDFSIPInfo swap_ip;
682     if (ip_addrs->count == 1)
683     {
684         *error_info = '\0';
685         return 0;
686     }
687 
688     if (ip_addrs->count <= 0)
689     {
690         logError("file: "__FILE__", line: %d, "
691                 "empty server", __LINE__);
692         return EINVAL;
693     }
694 
695     if (ip_addrs->count > FDFS_MULTI_IP_MAX_COUNT)
696     {
697         snprintf(error_info, error_size,
698                 "too many server ip addresses: %d, exceeds %d",
699                 ip_addrs->count, FDFS_MULTI_IP_MAX_COUNT);
700         return EINVAL;
701     }
702 
703     if (ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER].type ==
704             ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER].type)
705     {
706         snprintf(error_info, error_size,
707                 "invalid ip addresses %s and %s, "
708                 "one MUST be an inner IP and another is a outer IP, "
709                 "or two different types of inner IP addresses",
710                 ip_addrs->ips[0].address, ip_addrs->ips[1].address);
711         return EINVAL;
712     }
713 
714     if (ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER].type == FDFS_IP_TYPE_OUTER)
715     {
716         swap_ip = ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER];
717         ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER] =
718             ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER];
719         ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER] = swap_ip;
720     }
721 
722     *error_info = '\0';
723     return 0;
724 }
725 
fdfs_set_multi_ip_index(FDFSMultiIP * multi_ip,const char * target_ip)726 void fdfs_set_multi_ip_index(FDFSMultiIP *multi_ip, const char *target_ip)
727 {
728     int i;
729     if (multi_ip->count <= 1)
730     {
731         return;
732     }
733 
734     for (i=0; i<multi_ip->count; i++)
735     {
736         if (strcmp(multi_ip->ips[i].address, target_ip) == 0)
737         {
738             multi_ip->index = i;
739             break;
740         }
741     }
742 }
743 
fdfs_set_server_info_index(TrackerServerInfo * pServer,const char * target_ip,const int target_port)744 void fdfs_set_server_info_index(TrackerServerInfo *pServer,
745         const char *target_ip, const int target_port)
746 {
747     int i;
748     if (pServer->count <= 1)
749     {
750         return;
751     }
752 
753     for (i=0; i<pServer->count; i++)
754     {
755         if (FC_CONNECTION_SERVER_EQUAL(pServer->connections[i],
756                     target_ip, target_port))
757         {
758             pServer->index = i;
759             break;
760         }
761     }
762 }
763 
fdfs_set_server_info(TrackerServerInfo * pServer,const char * ip_addr,const int port)764 void fdfs_set_server_info(TrackerServerInfo *pServer,
765         const char *ip_addr, const int port)
766 {
767     pServer->count = 1;
768     pServer->index = 0;
769     conn_pool_set_server_info(pServer->connections + 0, ip_addr, port);
770 }
771 
fdfs_set_server_info_ex(TrackerServerInfo * pServer,const FDFSMultiIP * ip_addrs,const int port)772 void fdfs_set_server_info_ex(TrackerServerInfo *pServer,
773         const FDFSMultiIP *ip_addrs, const int port)
774 {
775     int i;
776 
777     pServer->count = ip_addrs->count;
778     pServer->index = 0;
779     for (i=0; i<ip_addrs->count; i++)
780     {
781         conn_pool_set_server_info(pServer->connections + i,
782                 ip_addrs->ips[i].address, port);
783     }
784 }
785 
786