1 /*
2  * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3  *
4  * This file is part of MooseFS.
5  *
6  * MooseFS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 2 (only).
9  *
10  * MooseFS is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with MooseFS; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18  * or visit http://www.gnu.org/licenses/gpl-2.0.html
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdlib.h>
26 #include <pthread.h>
27 #include <inttypes.h>
28 
29 #include "labelparser.h"
30 #include "csorder.h"
31 #include "csdb.h"
32 #include "massert.h"
33 #include "datapack.h"
34 
35 /*
36 typedef struct _cspri {
37 	uint32_t ip;
38 	uint16_t port;
39 	uint32_t version;
40 	uint32_t labelmask;
41 	uint32_t priority;
42 } cspri;
43 */
44 
45 static uint8_t labelscnt;
46 static uint32_t labelmasks[9][MASKORGROUP];
47 
csorder_init(char * labelexpr)48 int csorder_init(char *labelexpr) {
49 	if (labelexpr==NULL) {
50 		labelscnt = 0;
51 		return 0;
52 	} else {
53 		return parse_label_expr(labelexpr,&labelscnt,labelmasks);
54 	}
55 }
56 
csorder_calc(uint32_t labelmask)57 uint8_t csorder_calc(uint32_t labelmask) {
58 	uint8_t i,j;
59 //	syslog(LOG_NOTICE,"labelmask: %08"PRIX32,labelmask);
60 	for (i=0 ; i<labelscnt ; i++) {
61 		if (labelmasks[i][0]==0) { // any - not useful here, but formally possible
62 //			syslog(LOG_NOTICE,"labelmasks[%"PRIu8"] = '*'",i);
63 			return i;
64 		}
65 		for (j=0 ; j<MASKORGROUP && labelmasks[i][j]!=0 ; j++) {
66 //			syslog(LOG_NOTICE,"labelmasks[%"PRIu8"][%"PRIu8"]: %08"PRIX32,i,j,labelmasks[i][j]);
67 			if ((labelmasks[i][j]&labelmask)==labelmasks[i][j]) {
68 				return i;
69 			}
70 		}
71 	}
72 //	syslog(LOG_NOTICE,"not found");
73 	return labelscnt;
74 }
75 
csorder_cmp(const void * a,const void * b)76 int csorder_cmp(const void *a,const void *b) {
77 	cspri *aa = (cspri*)a;
78 	cspri *bb = (cspri*)b;
79 	if (aa->priority < bb->priority) {
80 		return -1;
81 	} else if (aa->priority > bb->priority) {
82 		return 1;
83 	} else {
84 		return 0;
85 	}
86 }
87 
88 /*
89 static inline void csorder_log_chain_element(uint8_t indx,cspri *chelem) {
90 	char labelstrbuff[26*2];
91 	uint32_t i,j;
92 	j = 0;
93 	for (i=0 ; i<26 ; i++) {
94 		if (chelem->labelmask & (1<<i)) {
95 			if (j>0) {
96 				labelstrbuff[j++]=',';
97 			}
98 			labelstrbuff[j++]='A'+i;
99 		}
100 	}
101 	if (j==0) {
102 		memcpy(labelstrbuff,"(empty)",7);
103 		j=7;
104 	}
105 	labelstrbuff[j]=0;
106 	syslog(LOG_NOTICE,"chain_log: chunk[%"PRIu8"] = {ip:%u.%u.%u.%u ; port:%"PRIu16" ; labelmask: %s ; priority: %u.%u}",indx,(chelem->ip>>24)&0xFF,(chelem->ip>>16)&0xFF,(chelem->ip>>8)&0xFF,chelem->ip&0xFF,chelem->port,labelstrbuff,(chelem->priority>>24)&0xFF,chelem->priority&0xFFFFFF);
107 }
108 */
109 
csorder_sort(cspri chain[100],uint8_t csdataver,const uint8_t * csdata,uint32_t csdatasize,uint8_t writeflag)110 uint32_t csorder_sort(cspri chain[100],uint8_t csdataver,const uint8_t *csdata,uint32_t csdatasize,uint8_t writeflag) {
111 	const uint8_t *cp,*cpe;
112 //	char labelsbuff[LABELS_BUFF_SIZE];
113 	uint32_t i;
114 //	uint32_t j;
115 
116 //	syslog(LOG_NOTICE,"csorder_sort: csdataver: %"PRIu8" ; csdatasize: %"PRIu32" ; writeflag: %"PRIu8"\n",csdataver,csdatasize,writeflag);
117 	cp = csdata;
118 	cpe = csdata+csdatasize;
119 	i = 0;
120 	while (cp<cpe && i<100) {
121 		chain[i].ip = get32bit(&cp);
122 		chain[i].port = get16bit(&cp);
123 		if (csdataver>0) {
124 			chain[i].version = get32bit(&cp);
125 		} else {
126 			chain[i].version = 0;
127 		}
128 		if (csdataver>1) {
129 			chain[i].labelmask = get32bit(&cp);
130 		} else {
131 			chain[i].labelmask = 0;
132 		}
133 		chain[i].priority = csorder_calc(chain[i].labelmask);
134 		chain[i].priority <<= 24;
135 		if (writeflag) {
136 			chain[i].priority += i;
137 		} else {
138 			chain[i].priority += csdb_getopcnt(chain[i].ip,chain[i].port);
139 		}
140 //		csorder_log_chain_element(i,chain+i);
141 		i++;
142 	}
143 //	syslog(LOG_NOTICE,"csorder_sort: sort using: %s",make_label_expr(labelsbuff,labelscnt,labelmasks));
144 	qsort(chain,i,sizeof(cspri),csorder_cmp);
145 //	for (j=0 ; j<i ; j++) {
146 //		csorder_log_chain_element(j,chain+j);
147 //	}
148 	return i;
149 }
150