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