home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / trn / part04 / rthreads.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-02  |  9.9 KB  |  416 lines

  1. /* $Id: rthreads.c,v 4.4.3.1 1991/11/22 04:12:18 davison Trn $
  2. **
  3. ** $Log: rthreads.c,v $
  4. ** Revision 4.4.3.1  1991/11/22  04:12:18  davison
  5. ** Trn Release 2.0
  6. ** 
  7. */
  8.  
  9. #include "EXTERN.h"
  10. #include "common.h"
  11. #include "intrp.h"
  12. #include "rn.h"
  13. #include "ngdata.h"
  14. #include "rcln.h"
  15. #include "bits.h"
  16. #include "util.h"
  17. #ifndef USETMPTHREAD
  18. #include "rcstuff.h"
  19. #endif
  20. #ifdef SERVER
  21. #include "server.h"
  22. #endif
  23.  
  24. #ifdef USETHREADS
  25. #include "threads.h"
  26. #include "INTERN.h"
  27. #include "rthreads.h"
  28.  
  29. static FILE *fp;
  30.  
  31. static char *strings = Nullch;
  32.  
  33. static bool tmpthread_created = FALSE;
  34.  
  35. static int read_item();
  36. static void safefree();
  37.  
  38. /* Initialize our thread code by determining the byte-order of the thread
  39. ** files and our own current byte-order.  If they differ, set flags to let
  40. ** the read code know what we'll need to translate.
  41. */
  42. void
  43. thread_init()
  44. {
  45.     int i;
  46. #ifdef XTHREAD
  47.     long size;
  48. #endif
  49.  
  50.     tmpthread_file = savestr(filexp("/tmp/thread.%$"));
  51.  
  52.     word_same = long_same = TRUE;
  53. #ifdef XTHREAD
  54.     sprintf(ser_line, "XTHREAD DBINIT");
  55. # ifdef DEBUGGING
  56.     if (debug & DEB_NNTP) {
  57.     printf(">%s\n", ser_line) FLUSH;
  58.     }
  59. # endif
  60.     put_server(ser_line);
  61.     rawcheck_server(ser_line, sizeof ser_line);
  62. # ifdef DEBUGGING
  63.     if (debug & DEB_NNTP) {
  64.     printf("<%s\n", ser_line) FLUSH;
  65.     }
  66. # endif
  67.     size = rawget_server((char*)&mt_bmap, sizeof (BMAP));
  68.     if (size >= sizeof (BMAP) - 1) {
  69. #else /* !XTHREAD */
  70.     if ((fp = fopen(filexp(DBINIT), FOPEN_RB)) != Nullfp
  71.      && fread((char*)&mt_bmap, 1, sizeof(BMAP), fp) >= sizeof (BMAP) - 1) {
  72. #endif
  73.     if (mt_bmap.version != DB_VERSION) {
  74.         printf("\nThread database is the wrong version -- ignoring it.\n")
  75.         FLUSH;
  76.         use_threads = FALSE;
  77.     }
  78.     mybytemap(&my_bmap);
  79.     for (i = 0; i < sizeof (LONG); i++) {
  80.         if (i < sizeof (WORD)) {
  81.         if (my_bmap.w[i] != mt_bmap.w[i]) {
  82.             word_same = FALSE;
  83.         }
  84.         }
  85.         if (my_bmap.l[i] != mt_bmap.l[i]) {
  86.         long_same = FALSE;
  87.         }
  88.     }
  89.     } else {
  90.     printf("\ndb.init read failed -- assuming no byte-order translations.\n\n") FLUSH;
  91.     }
  92. #ifdef XTHREAD
  93.     while (rawget_server(ser_line, sizeof ser_line)) {
  94.     ;        /* trash any extraneous bytes */
  95.     }
  96. #else
  97.     if (fp != Nullfp) {
  98.     fclose(fp);
  99.     }
  100. #endif
  101. }
  102.  
  103. /* Open a thread file to make use of the data it contains.  Everything is
  104. ** slurped into arrays and buffers, and some minor digesting of the data
  105. ** is performed to make it more palatable.  Be sure to call unuse_data()
  106. ** before calling this again.
  107. */
  108. int
  109. use_data(thread_if_empty)
  110. bool_int thread_if_empty;
  111. {
  112.     register int i, j, k;
  113.     register char *ptr;
  114.     char *threadname;
  115.     bool already_tried = FALSE;
  116.     ART_NUM last, first;
  117.  
  118.     last = getngsize(ng);
  119.     first = getabsfirst(ng, last);
  120.     if (last < first) {
  121.     return 0;
  122.     }
  123.     if (tmpthread_group && strEQ(ngname, tmpthread_group)) {
  124.     threadname = tmpthread_file;
  125.     } else {
  126. #ifdef XTHREAD        /* use remote thread file? */
  127.     long size;
  128.  
  129.     threadname = Nullch;        /* assume we fail */
  130.     sprintf(ser_line, "XTHREAD THREAD");
  131. # ifdef DEBUGGING
  132.     if (debug & DEB_NNTP) {
  133.         printf(">%s\n", ser_line) FLUSH;
  134.     }
  135. # endif
  136.     put_server(ser_line);
  137.     size = rawcheck_server(ser_line, sizeof ser_line);
  138. # ifdef DEBUGGING
  139.     if (debug & DEB_NNTP) {
  140.         printf("<%s\n", ser_line) FLUSH;
  141.     }
  142. # endif
  143.     if (size < 0) {
  144.         fp = Nullfp;
  145.     } else {
  146.         char *tmpbuf;
  147.         long bufsize;
  148.  
  149. # ifdef SPEEDOVERMEM
  150.         bufsize = size ? size : 1;
  151. # else
  152.         bufsize = 16384;
  153. # endif
  154.         fp = fopen(tmpthread_file, "w");
  155.         tmpbuf = safemalloc(bufsize);
  156.         while ((size = rawget_server(tmpbuf, bufsize)) != 0) {
  157.         if (fp != Nullfp) {
  158.             /* write it out unbuffered */
  159.             write(fileno(fp), tmpbuf, size);
  160.         }
  161.         }
  162.         free(tmpbuf);
  163.         if (fp != Nullfp) {
  164.         fclose(fp);
  165.         growstr(&tmpthread_group, &tmpthread_glen,
  166.             strlen(ngname) + 1);
  167.         strcpy(tmpthread_group, ngname);
  168.         tmpthread_created = FALSE;
  169.         threadname = tmpthread_file;
  170.         }
  171.     }
  172. #else /* !XTHREAD */
  173.     threadname = thread_name(ngname);
  174. #endif
  175.     }
  176. try_to_use:
  177. #ifdef XTHREAD
  178.     if (!threadname || (fp = fopen(threadname, FOPEN_RB)) == Nullfp) {
  179.     if (threadname && errno != ENOENT) {
  180. #else
  181.     if ((fp = fopen(threadname, FOPEN_RB)) == Nullfp) {
  182.     if (errno != ENOENT) {
  183. #endif
  184.         printf("\n\nOpen failed for thread data.\n");
  185.     }
  186.     bzero(&total, sizeof (TOTAL));
  187.     if (!thread_if_empty || already_tried) {
  188.         return 0;
  189.     }
  190.     } else if (fread((char*)&total, 1, sizeof(TOTAL), fp) < sizeof(TOTAL)) {
  191.     fclose(fp);
  192.     bzero(&total, sizeof (TOTAL));
  193.     if (already_tried) {
  194.         return 0;
  195.     }
  196.     } else if (threadname != tmpthread_file || !tmpthread_created) {
  197.     lp_bmap(&total.first, 4);
  198.     wp_bmap(&total.root, 5);
  199.     } else if (!total.root) {
  200.     fclose(fp);
  201.     return 0;
  202.     }
  203.  
  204.     if (total.last < last) {
  205. #ifdef USETMPTHREAD
  206.     char cmd[512];
  207.     ART_NUM max = last - first + 1;
  208.  
  209.     if (fp) {
  210.         fclose(fp);
  211.     }
  212.     sprintf(cmd, "tmpthread %s %s %ld %ld %ld %s",
  213. #ifdef XTHREAD
  214.         threadname == tmpthread_file ?
  215.             (tmpthread_created ? "-t" : "-T") : nullstr,
  216. #else
  217.         threadname == tmpthread_file ? "-t" : nullstr,
  218. #endif
  219.         ngname, (long)last, (long)first, (long)max, tmpthread_file);
  220.     if (system(filexp(cmd))) {
  221.         printf("\n\nFailed to thread data -- continuing unthreaded.\n");
  222.         if (tmpthread_group) {
  223.         *tmpthread_group = '\0';
  224.         }
  225.         return 0;
  226.     }
  227.     growstr(&tmpthread_group, &tmpthread_glen, strlen(ngname) + 1);
  228.     strcpy(tmpthread_group, ngname);
  229.     threadname = tmpthread_file;
  230.     tmpthread_created = TRUE;
  231.     already_tried = TRUE;
  232.     goto try_to_use;
  233. #else /* !USETMPTHREAD */
  234.     if (lastart > total.last) {
  235.         tobethreaded = last - total.last;
  236.         toread[ng] -= tobethreaded;
  237.         lastart = total.last;
  238.     }
  239. #endif /* !USETMPTHREAD */
  240.     }
  241.  
  242.     if (total.last > lastart) {
  243. #ifdef SERVER
  244.     fclose(actfp);
  245.     ngdata_init();        /* re-grab the active file */
  246. #endif
  247.     grow_ctl(total.last);    /* sets lastart */
  248.     ngmax[ng] = lastart;    /* ensure getngsize() knows the new maximum */
  249.     }
  250.  
  251.     if (!read_item(&author_cnts, (MEM_SIZE)total.author * sizeof (WORD))
  252.      || !read_item(&strings, (MEM_SIZE)total.string1) 
  253.      || !read_item(&subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD))
  254.      || !read_item(&p_roots, (MEM_SIZE)total.root * sizeof (PACKED_ROOT))
  255.      || !read_item(&p_articles, (MEM_SIZE)total.article * sizeof (PACKED_ARTICLE))) {
  256.     printf("\n\nRead failed for thread data -- continuing unthreaded.\n");
  257.     fclose(fp);
  258.     unuse_data(0);
  259.     return 0;
  260.     }
  261.     fclose(fp);
  262.  
  263.     if ((threadname != tmpthread_file || !tmpthread_created)
  264.      && (!word_same || !long_same)) {
  265.     wp_bmap(author_cnts, total.author);
  266.     wp_bmap(subject_cnts, total.subject);
  267.     for (i = 0; i < total.root; i++) {
  268.         lp_bmap(&p_roots[i].root_num, 1);
  269.         wp_bmap(&p_roots[i].articles, 3);
  270.     }
  271.     for (i = 0; i < total.article; i++) {
  272.         lp_bmap(&p_articles[i].num, 2);
  273.         wp_bmap(&p_articles[i].subject, 8);
  274.     }
  275.     }
  276.  
  277. #ifndef lint
  278.     author_ptrs = (char **)safemalloc(total.author * sizeof (char **));
  279.     subject_ptrs = (char **)safemalloc(total.subject * sizeof (char **));
  280.     root_subjects = (WORD *)safemalloc(total.root * sizeof (WORD));
  281.     root_article_cnts = (WORD *)safemalloc(total.root * sizeof (WORD));
  282. #endif
  283.     selected_roots = safemalloc(total.root * sizeof (char));
  284.  
  285.     bzero(root_article_cnts, total.root * sizeof (WORD));
  286.     bzero(selected_roots, total.root * sizeof (char));
  287.  
  288.     for (i = 0, ptr = strings; i < total.author; i++) {
  289.     author_ptrs[i] = ptr;
  290.     ptr += strlen(ptr) + 1;
  291.     }
  292.  
  293.     for (i = 0, j = 0; i < total.root; i++) {
  294.     root_subjects[i] = j;
  295.     k = p_roots[i].subject_cnt;
  296.     while (k--) {
  297.         root_article_cnts[i] += subject_cnts[j];
  298.         subject_ptrs[j++] = ptr;
  299.         ptr += strlen(ptr) + 1;
  300.     }
  301.     if (saved_selections) {
  302.         for (k = 0; k < selected_root_cnt; k++) {
  303.         if (p_roots[i].root_num == saved_selections[k]) {
  304.             selected_roots[i] = 1;
  305.             break;
  306.         }
  307.         }
  308.     }
  309.     }
  310.     count_roots(!saved_selections);
  311.  
  312.     /* Try to clean up the bitmap if articles are missing. */
  313.     if (unthreaded) {
  314.       char *newarea, *oldarea = ctlarea;
  315.       extern MEM_SIZE ctlsize;
  316.  
  317.     newarea = ctlarea = safemalloc(ctlsize);
  318.     bzero(ctlarea, ctlsize);
  319.     for (i = total.article, p_art = p_articles; i--; p_art++) {
  320.         if (p_art->num >= firstbit) {
  321.         ctl_set(p_art->num);
  322.         }
  323.     }
  324.     for (i = firstbit; i <= lastart; i++) {
  325.         if (!ctl_read(i)) {
  326.         ctlarea = oldarea;
  327.         oneless(i);
  328.         ctlarea = newarea;
  329.         }
  330.     }
  331.     ctlarea = oldarea;
  332.     free(newarea);
  333.     p_art = Nullart;
  334.     count_roots(FALSE);
  335.     }
  336.     safefree(&saved_selections);
  337.     select_page = 0;
  338.     return 1;
  339. }
  340.  
  341. /* A shorthand for reading a chunk of the file into a malloced array.
  342. */
  343. static int
  344. read_item(dest, len)
  345. char **dest;
  346. MEM_SIZE len;
  347. {
  348.     int ret;
  349.  
  350.     *dest = safemalloc(len);
  351.     ret = fread(*dest, 1, (int)len, fp);
  352.     if (ret != len) {
  353.     free(*dest);
  354.     *dest = Nullch;
  355.     return 0;
  356.     }
  357.     return 1;
  358. }
  359.  
  360. /* Free some memory if it hasn't already been freed.
  361. */
  362. static void
  363. safefree(pp)
  364. char **pp;
  365. {
  366.     if (*pp) {
  367.     free(*pp);
  368.     *pp = Nullch;
  369.     }
  370. }
  371.  
  372. /* Discard the thread data that we received through the use_data() call.
  373. ** If "save_selections" is non-zero, we'll try to remember which roots
  374. ** are currently selected long enough for the use_data() call to re-use
  375. ** them.  Only do this when you are going to re-open the same data file
  376. ** immediately with use_data() (presumably because the data has been
  377. ** updated while we were using it).
  378. */
  379. void
  380. unuse_data(save_selections)
  381. bool_int save_selections;
  382. {
  383.     int i, j;
  384.  
  385.     if (save_selections) {
  386. #ifndef lint
  387.     saved_selections
  388.       = (ART_NUM *)safemalloc(selected_root_cnt * sizeof (ART_NUM));
  389. #endif
  390.     for (i = 0, j = 0; i < total.root; i++) {
  391.         if (selected_roots[i]) {
  392.         saved_selections[j++] = p_roots[i].root_num;
  393.         }
  394.     }
  395.     } else {
  396.     selected_root_cnt = selected_count = 0;
  397.     }
  398.     safefree(&p_roots);
  399.     safefree(&root_subjects);
  400.     safefree(&author_cnts);
  401.     safefree(&subject_cnts);
  402.     safefree(&author_ptrs);
  403.     safefree(&subject_ptrs);
  404.     safefree(&root_article_cnts);
  405.     safefree(&selected_roots);
  406.     safefree(&p_articles);
  407.     safefree(&strings);
  408.  
  409.     p_art = curr_p_art = Nullart;
  410.     init_tree();        /* free any tree lines */
  411.  
  412.     bzero(&total, sizeof (TOTAL));
  413. }
  414.  
  415. #endif /* USETHREADS */
  416.