home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / trn_12.zip / src / rthreads.c < prev    next >
C/C++ Source or Header  |  1993-12-05  |  11KB  |  429 lines

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