merge.c
上传用户:qin5330
上传日期:2007-01-05
资源大小:114k
文件大小:23k
源码类别:

搜索引擎

开发平台:

Perl

  1. /*
  2. ** Copyright (C) 1995, 1996, 1997, 1998 Hewlett-Packard Company
  3. ** Originally by Kevin Hughes, kev@kevcom.com, 3/11/94
  4. **
  5. ** This program and library is free software; you can redistribute it and/or
  6. ** modify it under the terms of the GNU (Library) General Public License
  7. ** as published by the Free Software Foundation; either version 2
  8. ** of the License, or any later version.
  9. **
  10. ** This program 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 (Library) General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU (Library) General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. **-----------------------------------------------------------------
  19. ** Fixed the merge option -M
  20. ** G. Hill 3/7/97
  21. **
  22. ** Changed readindexline, mergeindexentries, printindexentry and
  23. ** added marknumMerge, addtoresultlistMerge, markentrylistMerge,
  24. ** ismarkedMerge to add support for METADATA
  25. ** G. Hill 3/26/97 ghill@library.berkeley.edu
  26. */
  27. #include "swish.h"
  28. #include "merge.h"
  29. #include "error.h"
  30. #include "search.h"
  31. #include "index.h"
  32. #include "string.h"
  33. #include "hash.h"
  34. #include "mem.h"
  35. #include "docprop.h"
  36. /* The main merge functions - it accepts three file names.
  37. ** This is a bit hairy. It basically acts as a zipper,
  38. ** zipping up both index files into one.
  39. */
  40. void readmerge(file1, file2, outfile)
  41. char *file1;
  42. char *file2;
  43. char *outfile;
  44. {
  45. int i, j, indexfilenum1, indexfilenum2, result, totalfiles,
  46. skipwords, skipfiles;
  47. long limit1, limit2, fileinfo1, fileinfo2, offsetstart;
  48. char line[MAXSTRLEN];
  49. struct indexentry *ip1, *ip2, *ip3;
  50. struct indexentry *buffer1, *buffer2;
  51. FILE *fp1, *fp2, *fp3;
  52. struct metaMergeEntry *metaFile1, *metaFile2;
  53. int firstTime = 1;
  54. initindexfilehashlist();
  55. /* remapVar is used into addindexfilelist and need to be
  56. ** initialized each time two indexes are merged.
  57. */
  58. remapVar = 0;
  59. metaFile1 = metaFile2 = NULL;
  60. initmapentrylist();
  61. if ((fp1 = openIndexFileForRead(file1)) == NULL) {
  62. sprintf(errorstr, "Couldn't read the index file "%s".",
  63. file1);
  64. progerr(errorstr);
  65. }
  66. if (!isokindexheader(fp1)) {
  67. sprintf(errorstr, ""%s" has an unknown format.",
  68. file1);
  69. progerr(errorstr);
  70. }
  71. if ((fp2 = openIndexFileForRead(file2)) == NULL) {
  72. sprintf(errorstr, "Couldn't read the index file "%s".",
  73. file2);
  74. progerr(errorstr);
  75. }
  76. if (!isokindexheader(fp2)) {
  77. sprintf(errorstr, ""%s" has an unknown format.",
  78. file2);
  79. progerr(errorstr);
  80. }
  81. /* Was stemming applied to both indexes? If so, we want
  82.  * the new index to be marked as "stemming", otherwise
  83.  * it will be marked as "non-stemming" */
  84. applyStemmingRules = wasStemmingAppliedToIndex(fp1) && wasStemmingAppliedToIndex(fp2);
  85. ip1 = ip2 = ip3 = NULL;
  86. buffer1 = buffer2 = NULL;
  87. if (verbose)
  88. printf("Counting files... ");
  89. indexfilenum1 = getindexfilenum(fp1);
  90. indexfilenum2 = getindexfilenum(fp2);
  91. totalfiles = indexfilenum1 + indexfilenum2;
  92. if (verbose) {
  93. printf("%d files.n", indexfilenum1 + indexfilenum2);
  94. printf("Reading stopwords...");
  95. }
  96. readoffsets(fp1);
  97. readstopwords(fp1);
  98. limit1 = offsets[STOPWORDPOS];
  99. fileinfo1 = offsets[FILELISTPOS];
  100. metaFile1 = readMergeMeta(metaFile1,fp1);
  101. readoffsets(fp2);
  102. readstopwords(fp2);
  103. limit2 = offsets[STOPWORDPOS];
  104. fileinfo2 = offsets[FILELISTPOS];
  105. metaFile2 = readMergeMeta(metaFile2,fp2);
  106. /* Create the merged list and modify the
  107.    individual ones with the new meta index
  108. */    
  109. metaEntryList = createMetaMerge(metaFile1, metaFile2);
  110. if (verbose)
  111. printf("nReading file info...");
  112. fseek(fp1, fileinfo1, 0);
  113. for (i = 1; i <= indexfilenum1; i++) {
  114. /* Keep into account that 128th files are skipped */
  115. /*ii = i + (i/128); */
  116. /* addindexfilelist(ii, line, &totalfiles); */
  117. struct docPropertyEntry *docProperties;
  118. readFileEntry(fp1, line, &docProperties);
  119. addindexfilelist(i, line, docProperties, &totalfiles);
  120. #ifdef SUPPORT_DOC_PROPERTIES
  121. /* swap metaName values for properties */
  122. swapDocPropertyMetaNames(docProperties, metaFile1);
  123. #endif
  124. }
  125. fseek(fp2, fileinfo2, 0);
  126. for (i = 1; i <= indexfilenum2; i++) {
  127. /* keep into account that 128th files are skipped */
  128. /*ii = i + (i / 128) + indexfilenum1 + (indexfilenum1 / 128);*/
  129. /* This one is to keep in account the ones skipped earlier */
  130. /*if (!(ii%128))*/
  131. /*  ii++;*/
  132. /*addindexfilelist(ii, line, &totalfiles); */
  133. struct docPropertyEntry *docProperties;
  134. readFileEntry(fp2, line, &docProperties);
  135. addindexfilelist(i + indexfilenum1, line, docProperties, &totalfiles);
  136. #ifdef SUPPORT_DOC_PROPERTIES
  137. /* swap metaName values for properties */
  138. swapDocPropertyMetaNames(docProperties, metaFile2);
  139. #endif
  140. }
  141. if ((fp3 = openIndexFileForWrite(outfile)) == NULL) {
  142. sprintf(errorstr,
  143. "Couldn't write the merged index file "%s".",
  144. outfile);
  145. progerr(errorstr);
  146. }
  147. if (verbose)
  148. printf("nMerging words... ");
  149. printheader(fp3, outfile, 0, totalfiles,1);
  150. offsetstart = ftell(fp3);
  151. for (i = 0; i < MAXCHARS; i++)
  152. fprintf(fp3, "%016li", offsets[i]);
  153. fputc('n', fp3);
  154. readoffsets(fp1);
  155. readoffsets(fp2);
  156. for (i = 0; i < MAXCHARS; i++)
  157. offsets[i] = 0;
  158. skipwords = 0;
  159. while (1) {
  160. if (buffer1 == NULL) {
  161. ip1 = (struct indexentry *) 
  162. readindexline(fp1, limit1,metaFile1);
  163. if (ip1 == NULL) {
  164. if (ip2 == NULL && !firstTime) {
  165. break;
  166. }
  167. }
  168. buffer1 = ip1;
  169. }
  170. firstTime =0;
  171. if (buffer2 == NULL) {
  172. ip2 = (struct indexentry *) 
  173. readindexline(fp2, limit2,metaFile2);
  174. if (ip2 == NULL){
  175. if (ip1 == NULL) {
  176. break;
  177. }
  178. }
  179. else 
  180. addfilenums(ip2, indexfilenum1);
  181. buffer2 = ip2;
  182. }
  183. if (ip1 == NULL)
  184. result = 1;
  185. else if (ip2 == NULL)
  186. result = -1;
  187. else
  188. result = wordcompare(ip1->word, ip2->word);
  189. if (!result) {
  190. ip3 = (struct indexentry *) mergeindexentries(ip1, ip2);
  191. printindexentry(ip3, fp3);
  192. freeindexentry(ip1);
  193. freeindexentry(ip2);
  194. freeindexentry(ip3);
  195. buffer1 = buffer2 = NULL;
  196. skipwords++;
  197. }
  198. else if (result < 0) {
  199. printindexentry(ip1, fp3);
  200. freeindexentry(ip1);
  201. buffer1 = NULL;
  202. }
  203. else {
  204. printindexentry(ip2, fp3);
  205. freeindexentry(ip2);
  206. buffer2 = NULL;
  207. }
  208. }
  209. if (verbose) {
  210. if (skipwords)
  211. printf("%d redundant word%s.", skipwords,
  212. (skipwords == 1) ? "" : "s");
  213. else
  214. printf("no redundant words.");
  215. }
  216. printstopwords(fp3);
  217. if (verbose)
  218. printf("nMerging file info... ");
  219. offsets[FILELISTPOS] = ftell(fp3);
  220. for (i = j = 1; i <= indexfilenum1 + indexfilenum2; i++)
  221. {
  222. if (getmap(i) == j) {
  223. struct docPropertyEntry* docProperties;
  224. char* fileInfo;
  225. addtofilehashlist(j++ - 1, ftell(fp3));
  226. fileInfo = lookupindexfilenum(i, &docProperties);
  227. fprintf(fp3, "%s", fileInfo);
  228. #ifdef SUPPORT_DOC_PROPERTIES
  229. storeDocProperties(docProperties, fp3);
  230. #endif
  231. }
  232. }
  233. skipfiles = (indexfilenum1 + indexfilenum2) - totalfiles;
  234. if (verbose) {
  235. if (skipfiles)
  236. printf("%d redundant file%s.", skipfiles,
  237. (skipfiles == 1) ? "" : "s");
  238. else
  239. printf("no redundant files.");
  240. }
  241. printfileoffsets(fp3);
  242. printMetaNames(fp3);
  243. fseek(fp3, offsetstart, 0);
  244. for (i = 0; i < MAXCHARS; i++)
  245. fprintf(fp3, "%016li", offsets[i]);
  246. fclose(fp3);
  247. fclose(fp1);
  248. fclose(fp2);
  249. if (verbose)
  250. printf("nDone.n");
  251. }
  252. /* Gets the number of files in an index file.
  253. */
  254. int getindexfilenum(fp)
  255. FILE *fp;
  256. {
  257. int i;
  258. char line[MAXSTRLEN];
  259. readoffsets(fp);
  260. fseek(fp, offsets[FILELISTPOS], 0);
  261. i = 0;
  262. while(ftell(fp) != offsets[FILEOFFSETPOS]) 
  263. {
  264. readFileEntry(fp, line, NULL);
  265. i++;
  266. }
  267. return i;
  268. }
  269. /* This adds an offset to the file numbers in a particular
  270. ** result list. For instance, file 1 has file numbers going from
  271. ** 1 to 10, but so does file 2, so I have to add 10 to all the
  272. ** file numbers in file 2 before merging.
  273. */
  274. void addfilenums(ip, num)
  275. struct indexentry *ip;
  276. int num;
  277. {
  278. struct resultMerge *rp;
  279. rp = ip->result;
  280. while (rp != NULL) {
  281. rp->filenum =
  282. encodefilenum(getmap(decodefilenum(rp->filenum) + num));
  283. rp = rp->next;
  284. }
  285. }
  286. /* This reads the next line in the index file and puts the results
  287. ** in a result structure.
  288. */
  289. struct indexentry *readindexline(fp, limit, metaFile)
  290. FILE *fp;
  291. long limit;
  292. struct metaMergeEntry *metaFile;
  293. {
  294. int i, c, x, countnum, rank, filenum, structure,metaName;
  295. char fileword[MAXWORDLEN];
  296. struct resultMerge *rp;
  297. struct indexentry *ip;
  298. struct metaMergeEntry* tmp;
  299. rp = NULL;
  300. if (limit == ftell(fp))
  301. return NULL;
  302. for (i = 0; (c = fgetc(fp)) != 0; ) {
  303. if (c == ':') {
  304. fileword[i] = '';
  305. break;
  306. }
  307. else
  308. fileword[i++] = c;
  309. }
  310. countnum = 1;
  311. ungetc(c, fp);
  312. while ((c = fgetc(fp)) != 0) {
  313. x = 0;
  314. do {
  315. c = fgetc(fp);
  316. if (c == 0)
  317. break;
  318. x *= 128;
  319. x += c & 127;
  320. } while (c & 128);
  321. if (c == 0)
  322. break;
  323. if (x) {
  324. if (countnum == 1) {
  325. filenum = x;
  326. countnum++;
  327. }
  328. else if (countnum == 2) {
  329. rank = x;
  330. countnum++;
  331. }
  332. else if (countnum == 3) {
  333. structure = x;
  334. countnum++;
  335. }
  336. else if (countnum ==4) {
  337. metaName = x;
  338. /*Need to modify metaName with new list*/
  339. for(tmp=metaFile;tmp;tmp=tmp->next) {
  340. if (tmp->oldIndex == metaName) {
  341. metaName = tmp->newIndex;
  342. break;
  343. }
  344. }
  345. rp = (struct resultMerge *)
  346. addtoresultlistMerge(rp, filenum,
  347. rank, structure,metaName);
  348. countnum = 1;
  349. }
  350. }
  351. }
  352. ip = (struct indexentry *) emalloc(sizeof(struct indexentry));
  353. ip->word = (char *) mystrdup(fileword);
  354. ip->result = rp;
  355. return ip;
  356. }
  357. /* This puts all the file info into a hash table so that it can
  358. ** be looked up by its pathname and filenumber. This is how
  359. ** we find redundant file information.
  360. */
  361. void addindexfilelist(num, info, docProperties, totalfiles)
  362. int num;
  363. char *info;
  364. struct docPropertyEntry *docProperties;
  365. int *totalfiles;
  366. {
  367. int i;
  368. unsigned hashval;
  369. char tmpstr[MAXSTRLEN], path[MAXSTRLEN];
  370. struct indexfileinfo *ip1, *ip2;
  371. strcpy(path, extractpath(info));
  372. i = lookupindexfilepath(path);
  373. if (i != -1) {
  374. *totalfiles = *totalfiles - 1;
  375. remap(num, i);
  376. return;
  377. }
  378. remap(num, remapVar + 1);
  379. remapVar++;
  380. ip1 = (struct indexfileinfo *) emalloc(sizeof(struct indexfileinfo));
  381. ip1->filenum = num;
  382. ip1->fileinfo = (char *) mystrdup(info);
  383. ip1->path = (char *) mystrdup(path);
  384. #ifdef SUPPORT_DOC_PROPERTIES
  385. ip1->docProperties = docProperties;
  386. #endif
  387. sprintf(tmpstr, "%d", num);
  388. hashval = bighash(tmpstr);
  389. ip1->next = indexfilehashlist[hashval];
  390. indexfilehashlist[hashval] = ip1;
  391. ip2 = (struct indexfileinfo *) emalloc(sizeof(struct indexfileinfo));
  392. ip2->filenum = num;
  393. ip2->fileinfo = (char *) mystrdup(info);
  394. ip2->path = (char *) mystrdup(path);
  395. #ifdef SUPPORT_DOC_PROPERTIES
  396. ip2->docProperties = docProperties; /* two pointers to the same list! - be careful */
  397. #endif
  398. hashval = bighash(path);
  399. ip2->next = indexfilehashlist[hashval];
  400. indexfilehashlist[hashval] = ip2;
  401. }
  402. /* This extracts the pathname information from the file information
  403. ** line as stored in the index file.
  404. */
  405. char *extractpath(s)
  406. char *s;
  407. {
  408. int i;
  409. static char path[MAXSTRLEN];
  410. for (i = 0; s[i] && s[i] != '"'; i++)
  411. path[i] = s[i];
  412. path[i - 1] = '';
  413. path[i] = '';
  414. return path;
  415. }
  416. /* This returns the file information corresponding to a file number.
  417. */
  418. char *lookupindexfilenum(num, docProperties)
  419. int num;
  420. struct docPropertyEntry** docProperties;
  421. {
  422. unsigned hashval;
  423. char tmpstr[MAXSTRLEN];
  424. struct indexfileinfo *ip;
  425. if (docProperties != NULL)
  426. *docProperties = NULL;
  427. sprintf(tmpstr, "%d", num);
  428. hashval = bighash(tmpstr);
  429. ip = indexfilehashlist[hashval];
  430. while (ip != NULL) {
  431. if (ip->filenum == num)
  432. {
  433. #ifdef SUPPORT_DOC_PROPERTIES
  434. if (docProperties != NULL)
  435. *docProperties = ip->docProperties;
  436. #endif
  437. return ip->fileinfo;
  438. }
  439. ip = ip->next;
  440. }
  441. return NULL;
  442. }
  443. /* This returns the file number corresponding to a pathname.
  444. */
  445. int lookupindexfilepath(path)
  446. char *path;
  447. {
  448. unsigned hashval;
  449. struct indexfileinfo *ip;
  450. hashval = bighash(path);
  451. ip = indexfilehashlist[hashval];
  452. while (ip != NULL) {
  453. if (!strcmp(ip->path, path))
  454. return ip->filenum;
  455. ip = ip->next;
  456. }
  457. return -1;
  458. }
  459. /* This simply concatenates two information lists that correspond
  460. ** to a word found in both index files.
  461. */
  462. struct indexentry *mergeindexentries(ip1, ip2)
  463. struct indexentry *ip1;
  464. struct indexentry *ip2;
  465. {
  466. struct resultMerge *newrp, *rp1, *rp2;
  467. struct indexentry *ep;
  468. rp1 = ip1->result;
  469. rp2 = ip2->result;
  470. newrp = NULL;
  471. while (rp1 != NULL) {
  472. newrp = (struct resultMerge *) addtoresultlistMerge(newrp,
  473. rp1->filenum, rp1->rank, rp1->structure,rp1->metaName);
  474. rp1 = rp1->next;
  475. }
  476. while (rp2 != NULL) {
  477. newrp = (struct resultMerge *) addtoresultlistMerge(newrp,
  478. rp2->filenum, rp2->rank, rp2->structure,rp2->metaName);
  479. rp2 = rp2->next;
  480. }
  481. ep = (struct indexentry *) emalloc(sizeof(struct indexentry));
  482. ep->word = (char *) mystrdup(ip1->word);
  483. ep->result = newrp;
  484. return ep;
  485. }
  486. /* This prints a new word entry into the merged index file,
  487. ** removing redundant file information as it goes along.
  488. */
  489. void printindexentry(ip, fp)
  490. struct indexentry *ip;
  491. FILE *fp;
  492. {
  493. int i, num, metaName;
  494. struct resultMerge *rp;
  495. for (i = 0; indexchars[i] != ''; i++)
  496. {
  497. if ((ip->word)[0] == indexchars[i] && !offsets[i])
  498. offsets[i] = ftell(fp);
  499. }
  500. fprintf(fp, "%s:", ip->word);
  501. initmarkentrylistMerge();
  502. rp = ip->result;
  503. while (rp != NULL) {
  504. num = rp->filenum;
  505. metaName = rp->metaName;
  506. if (!ismarkedMerge(num,metaName)) {
  507. marknumMerge(num,metaName);
  508. compress(num, fp);
  509. compress(rp->rank, fp);
  510. compress(rp->structure, fp);
  511. compress(rp->metaName,fp);
  512. }
  513. rp = rp->next;
  514. }
  515. fputc(0, fp);
  516. }
  517. /* This associates a number with a new number.
  518. ** This function is used to remap file numbers from index
  519. ** files to a new merged index file.
  520. */
  521. void remap(oldnum, newnum)
  522. int oldnum;
  523. int newnum;
  524. {
  525. unsigned hashval;
  526. char tmpstr[MAXSTRLEN];
  527. struct mapentry *mp;
  528. mp = (struct mapentry *) emalloc(sizeof(struct mapentry));
  529. mp->oldnum = oldnum;
  530. mp->newnum = newnum;
  531. sprintf(tmpstr, "%d", oldnum);
  532. hashval = bighash(tmpstr);
  533. mp->next = mapentrylist[hashval];
  534. mapentrylist[hashval] = mp;
  535. }
  536. /* This retrieves the number associated with another.
  537. */
  538. int getmap(num)
  539. int num;
  540. {
  541. unsigned hashval;
  542. char tmpstr[MAXSTRLEN];
  543. struct mapentry *mp;
  544. sprintf(tmpstr, "%d", num);
  545. hashval = bighash(tmpstr);
  546. mp = mapentrylist[hashval];
  547. while (mp != NULL) {
  548. if (mp->oldnum == num)
  549. return mp->newnum;
  550. mp = mp->next;
  551. }
  552. return num;
  553. }
  554. /* This marks a number as having been printed.
  555. */
  556. void marknum(num)
  557. int num;
  558. {
  559. unsigned hashval;
  560. char tmpstr[MAXSTRLEN];
  561. struct markentry *mp;
  562. mp = (struct markentry *) emalloc(sizeof(struct markentry));
  563. mp->num = num;
  564. sprintf(tmpstr, "%d", num);
  565. hashval = bighash(tmpstr);
  566. mp->next = markentrylist[hashval];
  567. markentrylist[hashval] = mp;
  568. }
  569. /* Same thing but for merge only */
  570. void marknumMerge(num, metaName)
  571. int num;
  572. int metaName;
  573. {
  574. unsigned hashval;
  575. char tmpstr[MAXSTRLEN];
  576. struct markentryMerge *mp;
  577. mp = (struct markentryMerge *) emalloc(sizeof(struct markentryMerge));
  578. mp->num = num;
  579. mp->metaName = metaName;
  580. sprintf(tmpstr, "%d", num);
  581. hashval = bighash(tmpstr);
  582. mp->next = markentrylistMerge[hashval];
  583. markentrylistMerge[hashval] = mp;
  584. }      
  585. /* Has a number been printed?
  586. */
  587. int ismarked(num)
  588. int num;
  589. {
  590. unsigned hashval;
  591. char tmpstr[MAXSTRLEN];
  592. struct markentry *mp;
  593. sprintf(tmpstr, "%d", num);
  594. hashval = bighash(tmpstr);
  595. mp = markentrylist[hashval];
  596. while (mp != NULL) {
  597. if (mp->num == num)
  598. return 1;
  599. mp = mp->next;
  600. }
  601. return 0;
  602. }
  603. int ismarkedMerge(num,metaName)
  604. int num;
  605. int metaName;
  606. {
  607. unsigned hashval;
  608. char tmpstr[MAXSTRLEN];
  609. struct markentryMerge *mp;
  610. sprintf(tmpstr, "%d", num);
  611. hashval = bighash(tmpstr);
  612. mp = markentrylistMerge[hashval];
  613. while (mp != NULL) {
  614. if ( (mp->num == num) && (mp->metaName == metaName) )
  615. return 1;
  616. mp = mp->next;
  617. }
  618. return 0;
  619. }
  620. /* Initialize the marking list.
  621. */
  622. void initmarkentrylist()
  623. {
  624. int i;
  625. struct markentry *mp;
  626. for (i = 0; i < BIGHASHSIZE; i++) {
  627. mp = markentrylist[i];
  628. if (mp != NULL)
  629. free(mp);
  630. markentrylist[i] = NULL;
  631. }
  632. }
  633. void initmarkentrylistMerge()
  634. {
  635. int i;
  636. struct markentryMerge *mp;
  637. for (i = 0; i < BIGHASHSIZE; i++) {
  638. mp = markentrylistMerge[i];
  639. if (mp != NULL)
  640. free(mp);
  641. markentrylistMerge[i] = NULL;
  642. }
  643. }      
  644. /* Initialize the main file list.
  645. */
  646. void initindexfilehashlist()
  647. {
  648. int i;
  649. struct indexfileinfo *ip;
  650. for (i = 0; i < BIGHASHSIZE; i++) {
  651. ip = indexfilehashlist[i];
  652. if (ip != NULL)
  653. free(ip);
  654. indexfilehashlist[i] = NULL;
  655. }
  656. }
  657. /* Initialize the mapentrylist 
  658. */
  659. void initmapentrylist()
  660. {
  661. int i;
  662. struct mapentry *ip;
  663. for (i = 0; i < BIGHASHSIZE; i++) {
  664. ip = mapentrylist[i];
  665. if (ip != NULL)
  666. free(ip);
  667. mapentrylist[i] = NULL;
  668. }
  669. }
  670. /* Frees up used index entries, my best attempt at memory management...
  671. ** I still have bytes leaking elsewhere...
  672. */
  673. void freeindexentry(ip)
  674. struct indexentry *ip;
  675. {
  676. struct resultMerge *rp, *oldp;
  677. free(ip->word);
  678. rp = ip->result;
  679. while (rp != NULL) {
  680. oldp = rp;
  681. rp = rp->next;
  682. free(oldp);
  683. }
  684. free(ip);
  685. }
  686. /* Translates a file number into something that can be compressed.
  687. */
  688. int encodefilenum(num)
  689. int num;
  690. {
  691. int i, j;
  692. for (i = j = 0; i != num; i++) {
  693. j++;
  694. if (!(j % 128))
  695. j++;
  696. }
  697. return j;
  698. }
  699. /* Translates a compressed file number into a correct file number.
  700. */
  701. int decodefilenum(num)
  702. int num;
  703. {
  704. int i, extra;
  705. for (i = 1, extra = 0; i < num; i++)
  706. if (!(i % 128)) {
  707. extra++;
  708. i++;
  709. }
  710. num -= extra;
  711. return num;
  712. }
  713. /* Similar to addtoresultlist, but also adding the meta name
  714. */
  715. struct resultMerge *addtoresultlistMerge(rp, filenum, rank, 
  716.  structure, metaName)
  717.  struct resultMerge *rp;
  718. int filenum;
  719. int rank;
  720. int structure;
  721. int metaName;
  722. {
  723. struct resultMerge *newnode;
  724. static struct resultMerge *head;
  725. newnode = (struct resultMerge *) emalloc(sizeof(struct resultMerge));
  726. newnode->filenum = filenum;
  727. newnode->rank = rank;
  728. newnode->structure = structure;
  729. newnode->metaName = metaName;
  730. newnode->next = NULL;
  731. if (rp == NULL)
  732. rp = newnode;
  733. else
  734. head->next = newnode;
  735. head = newnode;
  736. return rp;
  737. }
  738. /* Reads the meta names from the index. Needs to be different from
  739. ** readMetaNames because needs to zero out the counter.
  740. */
  741. struct metaMergeEntry* readMergeMeta(metaFile,fp)
  742. struct metaMergeEntry* metaFile;
  743. FILE* fp;
  744. {     
  745. int i, c, counter;
  746. char word[MAXWORDLEN];
  747. counter = 0;
  748. fseek(fp, offsets[METANAMEPOS], 0);
  749. for (i = 0; (c = fgetc(fp)) != 'n' && c != EOF; ){
  750. if (!isspace(c))
  751. word[i++] = c;
  752. else {
  753. int docPropStyle = 0;
  754. char* docPropStyleTmp;
  755. word[i] = '';
  756. /* parse the meta name style:
  757. * <name>"0   -> normal meta name [default]
  758. * <name>"1   -> doc property name
  759. * <name>"2   -> both
  760. */
  761. docPropStyleTmp = strrchr(word, '"');
  762. if (docPropStyleTmp != NULL)
  763. {
  764. *docPropStyleTmp++ = ''; /* remove (and move past) quote */
  765. docPropStyle = atoi(docPropStyleTmp);
  766. }
  767. metaFile = addMetaMerge(metaFile, 
  768. word, 
  769. (docPropStyle > 0) ? 1 : 0,
  770. (docPropStyle == 1) ? 1 : 0,
  771. &counter);
  772. i = 0;
  773. }
  774. }
  775. return metaFile;
  776. }
  777. /* Adds an entry to the list of meta names for one index, 
  778. ** setting the new index to 0 - it will then be set by 
  779. ** createMetaMerge.
  780. */
  781. struct metaMergeEntry* addMetaMerge(metaFile, metaWord, isDocProp, isOnlyDocProp, counter)
  782. struct metaMergeEntry* metaFile;
  783. char* metaWord;
  784. int isDocProp, isOnlyDocProp;
  785. int* counter;
  786. {
  787. int i;
  788. struct metaMergeEntry* newEntry;
  789. struct metaMergeEntry* tmpEntry;
  790. if (*counter == 0)
  791. *counter = 2;
  792. else if ((*counter) == 1 ||  (!((*counter) % 128)) )
  793. (*counter)++;
  794. for( i=0; metaWord[i]; i++)
  795. metaWord[i] =  tolower(metaWord[i]);
  796. newEntry = (struct metaMergeEntry*) emalloc(sizeof(struct metaMergeEntry));
  797. newEntry->metaName = (char*)mystrdup(metaWord);
  798. #ifdef SUPPORT_DOC_PROPERTIES
  799. newEntry->isDocProperty = isDocProp;
  800. newEntry->isOnlyDocProperty = isOnlyDocProp;
  801. #endif
  802. newEntry->oldIndex = (*counter)++;
  803. newEntry->newIndex = 0;
  804. newEntry->next = NULL;
  805. if (metaFile)
  806.     {
  807. for(tmpEntry=metaFile;tmpEntry->next!=NULL;tmpEntry=tmpEntry->next)
  808. ;
  809. tmpEntry->next = newEntry;
  810.     }
  811. else
  812. metaFile = newEntry;
  813. return metaFile;
  814. }
  815. /* Creates a list of all the meta names in the indexes
  816. */
  817. struct metaEntry* createMetaMerge(metaFile1, metaFile2)
  818. struct metaMergeEntry* metaFile1;
  819. struct metaMergeEntry* metaFile2;
  820. {
  821. struct metaMergeEntry* tmpEntry;
  822. int counter;
  823. metaEntryList = NULL;
  824. counter = 0;
  825. for (tmpEntry=metaFile1;tmpEntry;tmpEntry=tmpEntry->next)
  826. metaEntryList = addMetaMergeList(metaEntryList,tmpEntry,&counter);
  827. for (tmpEntry=metaFile2;tmpEntry;tmpEntry=tmpEntry->next)
  828. metaEntryList = addMetaMergeList(metaEntryList,tmpEntry,&counter);
  829. return metaEntryList;
  830. }
  831. /* Adds an entry to the merged meta names list and changes the
  832.  ** new index in the idividual file entry
  833.  */
  834. struct metaEntry* addMetaMergeList(metaEntryList,metaFileEntry,count)
  835. struct metaEntry* metaEntryList;
  836. struct metaMergeEntry* metaFileEntry;
  837. int* count;
  838. {
  839. int i, wordExists, newIndex;
  840. struct metaEntry* newEntry;
  841. struct metaEntry* tmpEntry;
  842. struct metaEntry* last;
  843. char *metaWord, *compWord;
  844. int isOnlyDocProperty = 0;
  845. int isDocProperty = 0;
  846. wordExists = 0;
  847. if ((*count) == 0)
  848. *count = 2;
  849. else if ((*count) == 1 ||  (!((*count) % 128)) )
  850. (*count)++;
  851. metaWord = metaFileEntry->metaName;
  852. #ifdef SUPPORT_DOC_PROPERTIES
  853. isDocProperty = metaFileEntry->isDocProperty;
  854. isOnlyDocProperty = metaFileEntry->isOnlyDocProperty;
  855. #endif
  856. for( i=0; metaWord[i]; i++)
  857. metaWord[i] =  tolower(metaWord[i]);
  858. if (metaEntryList)
  859.     {
  860. for(tmpEntry=metaEntryList;tmpEntry;tmpEntry=tmpEntry->next)
  861. {
  862. if (tmpEntry->next == NULL)
  863. last = tmpEntry;
  864. compWord = tmpEntry->metaName;
  865. if (!strcmp(compWord,metaWord) ) 
  866. {
  867. wordExists = 1;
  868. newIndex = tmpEntry->index;
  869. /*
  870.  * Keep the docProperties fields in synch.
  871.  * The semantics we want for the metaEntry are:
  872.  * isDocProperty = 1 if either index is using as PropertyName
  873.  * isOnlyDocProperty = 1 if neither index is using as MetaName
  874.  */
  875. if (isDocProperty) /* new entry is docProp, so assert it */
  876. {
  877. tmpEntry->isDocProperty = 1;
  878. }
  879. if (!isOnlyDocProperty) /* new entry is not *only* docProp, so unassert that */
  880. {
  881. tmpEntry->isOnlyDocProperty = 0;
  882. }
  883. break;
  884. }
  885. }
  886. if (wordExists)
  887. {
  888. metaFileEntry->newIndex = newIndex;
  889. }
  890. else 
  891. {
  892. newEntry = (struct metaEntry*) emalloc(sizeof(struct metaEntry));
  893. newEntry->metaName = (char*)mystrdup(metaWord);
  894. newEntry->index = *count;
  895. newEntry->next = NULL;
  896. #ifdef SUPPORT_DOC_PROPERTIES
  897. newEntry->isDocProperty = isDocProperty;
  898. newEntry->isOnlyDocProperty = isOnlyDocProperty;
  899. #endif
  900. metaFileEntry->newIndex = (*count)++;
  901. last->next = newEntry;
  902. }
  903.     }
  904. else {
  905. newEntry = (struct metaEntry*) emalloc(sizeof(struct metaEntry));
  906. newEntry->metaName = (char*)mystrdup(metaWord);
  907. newEntry->index = *count;
  908. newEntry->next = NULL;
  909. #ifdef SUPPORT_DOC_PROPERTIES
  910. newEntry->isDocProperty = isDocProperty; /* init */
  911. newEntry->isOnlyDocProperty = isOnlyDocProperty; /* init */
  912. #endif
  913. metaFileEntry->newIndex = (*count)++;
  914. metaEntryList = newEntry;
  915. }
  916. return metaEntryList;
  917. }
  918.