1 /* Copyright (C) 2000-2015 Lavtech.com corp. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18 #include "udm_config.h"
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 #ifdef HAVE_IO_H
29 #include <io.h>
30 #endif
31 #include <errno.h>
32 #include <math.h>
33
34 #include "udm_common.h"
35 #include "udm_utils.h"
36 #include "udm_searchtool.h"
37 #include "udm_boolean.h"
38 #include "udm_vars.h"
39 #include "udm_conf.h"
40 #include "udm_log.h"
41
42
43 /********** QSORT functions *******************************/
44
45
46 static int
cmppattern(UDM_URLDATALIST * Data,UDM_URLDATA * D,long j,const char * pattern)47 cmppattern(UDM_URLDATALIST *Data, UDM_URLDATA *D,
48 long j, const char *pattern)
49 {
50 int rc;
51
52 for(; *pattern != '\0'; pattern++)
53 {
54 switch(*pattern)
55 {
56 case 'R':
57 case 'r':
58 if (D->score > Data->Item[j].score) return (*pattern == 'R') ? 1 : -1;
59 if (D->score < Data->Item[j].score) return (*pattern == 'R') ? -1 : 1;
60 break;
61 case 'P':
62 case 'p':
63 if (D->pop_rank > Data->Item[j].pop_rank) return (*pattern == 'P') ? 1 : -1;
64 if (D->pop_rank < Data->Item[j].pop_rank) return (*pattern == 'P') ? -1 : 1;
65 break;
66 case 'D':
67 case 'd':
68 if (D->last_mod_time > Data->Item[j].last_mod_time) return (*pattern == 'D') ? 1 : -1;
69 if (D->last_mod_time < Data->Item[j].last_mod_time) return (*pattern == 'D') ? -1 : 1;
70 break;
71 case 'U':
72 case 'u':
73 rc= strcmp(UDM_NULL2EMPTY(D->url), UDM_NULL2EMPTY(Data->Item[j].url));
74 if (rc) return(*pattern == 'U' ? -rc : rc);
75 break;
76 case 'S':
77 case 's':
78 rc= strcmp(UDM_NULL2EMPTY(D->section),
79 UDM_NULL2EMPTY(Data->Item[j].section));
80 if (rc) return(*pattern == 'S' ? -rc : rc);
81 break;
82 }
83 }
84 return 0;
85 }
86
87
88 static int
cmppatternRP(UDM_URLDATA * D1,UDM_URLDATA * D2)89 cmppatternRP(UDM_URLDATA *D1, UDM_URLDATA *D2)
90 {
91 if (D1->score > D2->score) return -1;
92 if (D1->score < D2->score) return 1;
93
94 if (D1->pop_rank > D2->pop_rank) return -1;
95 if (D1->pop_rank < D2->pop_rank) return 1;
96 return 0;
97 }
98
99
100 static int
cmppatternR(UDM_URLDATA * D1,UDM_URLDATA * D2)101 cmppatternR(UDM_URLDATA *D1, UDM_URLDATA *D2)
102 {
103 if (D1->score > D2->score) return -1;
104 if (D1->score < D2->score) return 1;
105 return 0;
106 }
107
108
109
110 /****************************************************/
111
112 static int
cmpsiteid2(UDM_URLDATA * p1,UDM_URLDATA * p2)113 cmpsiteid2(UDM_URLDATA *p1, UDM_URLDATA *p2)
114 {
115 if (p1->site_id > p2->site_id) return -1;
116 if (p1->site_id < p2->site_id) return 1;
117 #if 0
118 if (p1->score > p2->score) return -1;
119 if (p1->score < p2->score) return 1;
120 if (p1->pop_rank > p2->pop_rank) return -1;
121 if (p1->pop_rank < p2->pop_rank) return 1;
122 #endif
123 return 0;
124 }
125
126
127 void
UdmURLDataSortBySite(UDM_URLDATALIST * L)128 UdmURLDataSortBySite(UDM_URLDATALIST *L)
129 {
130 UdmSort((void*) L->Item, L->nitems, sizeof(*L->Item), (udm_qsort_cmp) cmpsiteid2);
131 #if 0
132 {
133 size_t i;
134 printf("L->num: %d num: %d\n", L->ncoords, num);
135 for (i= 0; i < num; i++)
136 printf("%d %d %d %d %.6f\n", i,
137 L->Data[i].url_id, L->Data[i].site_id, L->Data[i].coord, L->Data[i].pop_rank);
138 }
139 #endif
140 }
141
142
143 static void
UdmURLDataSortByPatternRP(UDM_URLDATALIST * L)144 UdmURLDataSortByPatternRP(UDM_URLDATALIST *L)
145 {
146 UdmSort((void*) L->Item, L->nitems, sizeof(*L->Item), (udm_qsort_cmp) cmppatternRP);
147 }
148
149
150 static void
UdmURLDataSortByPatternR(UDM_URLDATALIST * L)151 UdmURLDataSortByPatternR(UDM_URLDATALIST *L)
152 {
153 UdmSort((void*) L->Item, L->nitems, sizeof(*L->Item), (udm_qsort_cmp) cmppatternR);
154 }
155
156
157 static size_t UdmH[] = {1, 5, 19, 41, 109, 209, 505, 929, 2161,
158 3905, 8929, 16001, 36289, 64769};
UdmURLDataSortByPattern(UDM_URLDATALIST * L,const char * pattern)159 void UdmURLDataSortByPattern(UDM_URLDATALIST *L, const char *pattern)
160 {
161 register ssize_t h, i, j;
162 int s = 13;
163 size_t num= L->nitems;
164 UDM_URLDATA Dat;
165
166 if (!strcmp(pattern, "RP"))
167 {
168 UdmURLDataSortByPatternRP(L);
169 goto ret;
170 }
171 if (!strcmp(pattern, "R"))
172 {
173 UdmURLDataSortByPatternR(L);
174 goto ret;
175 }
176
177 while( (s > 0) && ((num / 3) < UdmH[s])) s--;
178 while(s >= 0)
179 {
180 h= UdmH[s];
181 for (j= h; j < (ssize_t) num; j++)
182 {
183 Dat= L->Item[j];
184 i= j - h;
185 D4:
186 if (cmppattern(L, &Dat, i, pattern) <= 0) goto D6;
187 L->Item[i + h]= L->Item[i];
188 i-= h;
189 if (i >= 0) goto D4;
190 D6:
191 L->Item[i + h]= Dat;
192 }
193 s--;
194 }
195
196 ret:
197
198 #if 0
199 {
200 size_t i;
201 printf("L->num: %d num:%d pattern:%s\n", L->ncoords, num, pattern);
202 for (i= 0; i < num; i++)
203 {
204 printf("[%d]%d %d %d %d %.6f\n", i,
205 L->Coords[i].url_id, L->Coords[i].coord,
206 L->Data[i].url_id, L->Data[i].coord, (float) L->Data[i].pop_rank);
207 }
208 }
209 #endif
210 return;
211 }
212
213
214 /* TODO: Reuse the same function in sql.c */
215 static int
cmp_data_urls(UDM_URLDATA * d1,UDM_URLDATA * d2)216 cmp_data_urls(UDM_URLDATA *d1, UDM_URLDATA *d2)
217 {
218 if (d1->url_id > d2->url_id) return 1;
219 if (d1->url_id < d2->url_id) return -1;
220 return 0;
221 }
222
223
UdmURLDataListSearch(UDM_URLDATALIST * List,urlid_t id)224 UDM_URLDATA *UdmURLDataListSearch(UDM_URLDATALIST *List, urlid_t id)
225 {
226 UDM_URLDATA d;
227 void *found;
228 if (!List->nitems)
229 return 0;
230 d.url_id= id;
231 found= UdmBSearch(&d, List->Item, List->nitems, sizeof(UDM_URLDATA),
232 (udm_qsort_cmp) cmp_data_urls);
233 return (UDM_URLDATA*) found;
234 }
235
236
237 void
UdmURLDataListSort(UDM_URLDATALIST * List)238 UdmURLDataListSort(UDM_URLDATALIST *List)
239 {
240 if (List->nitems)
241 UdmSort(List->Item, List->nitems, sizeof(UDM_URLDATA), (udm_qsort_cmp) cmp_data_urls);
242 }
243
244
245 /*
246 Clear all params.
247 Keep url_id untouched.
248 */
249 void
UdmURLDataListClearParams(UDM_URLDATALIST * DataList)250 UdmURLDataListClearParams(UDM_URLDATALIST *DataList)
251 {
252 size_t i;
253 for (i= 0; i < DataList->nitems; i++)
254 {
255 UDM_URLDATA *D= &DataList->Item[i];
256 D->site_id= 0;
257 D->pop_rank= 0;
258 D->last_mod_time= 0;
259 D->url= NULL;
260 D->section= NULL;
261 }
262 }
263
264
265 void
UdmURLDataListInit(UDM_URLDATALIST * L)266 UdmURLDataListInit(UDM_URLDATALIST *L)
267 {
268 bzero((void *) L, sizeof(*L));
269 }
270
271
272 void
UdmURLDataFree(UDM_URLDATA * D)273 UdmURLDataFree(UDM_URLDATA *D)
274 {
275 UDM_FREE(D->url);
276 UDM_FREE(D->section);
277 }
278
279
280 /*
281 Free items in the given range
282 */
283 void
UdmURLDataListFreeItems(UDM_URLDATALIST * DataList,size_t first,size_t last)284 UdmURLDataListFreeItems(UDM_URLDATALIST *DataList, size_t first, size_t last)
285 {
286 size_t i;
287 for (i= first; i < last; i++)
288 UdmURLDataFree(&DataList->Item[i]);
289 }
290
291
292 void
UdmURLDataListFree(UDM_URLDATALIST * DataList)293 UdmURLDataListFree(UDM_URLDATALIST *DataList)
294 {
295 if (DataList->Item)
296 {
297 UdmURLDataListFreeItems(DataList, 0, DataList->nitems);
298 UdmFree(DataList->Item);
299 }
300 bzero((void*) DataList, sizeof(*DataList));
301 }
302
303
304 /*
305 Skip empty records and return the number of non-empty records
306 */
307 size_t
UdmURLDataCompact(UDM_URLDATA * dst,UDM_URLDATA * src,size_t n)308 UdmURLDataCompact(UDM_URLDATA *dst, UDM_URLDATA *src, size_t n)
309 {
310 UDM_URLDATA *dst0= dst, *srcend= src + n;
311 for ( ; src < srcend ; src++)
312 {
313 if (src->site_id)
314 {
315 *dst++= *src;
316 }
317 }
318 return dst - dst0;
319 }
320