home *** CD-ROM | disk | FTP | other *** search
- /* $Id: rthreads.c,v 2.3 1992/12/14 00:14:13 davison Trn $
- */
-
- #include "EXTERN.h"
- #include "common.h"
- #include "intrp.h"
- #include "rn.h"
- #include "ngdata.h"
- #include "rcln.h"
- #include "bits.h"
- #include "util.h"
- #ifndef USETMPTHREAD
- #include "rcstuff.h"
- #endif
- #ifdef SERVER
- #include "server.h"
- #endif
-
- #ifdef USETHREADS
- #include "threads.h"
- #include "INTERN.h"
- #include "rthreads.h"
-
- static FILE *fp;
-
- static char *strings = Nullch;
-
- static bool tmpthread_created = FALSE;
-
- static int read_item();
- static void safefree();
-
- /* Initialize our thread code by determining the byte-order of the thread
- ** files and our own current byte-order. If they differ, set flags to let
- ** the read code know what we'll need to translate.
- */
- void
- thread_init()
- {
- char *tmpstring; /* OS2 patch */
- int i;
- #ifdef XTHREAD
- long size;
- #endif
-
- /*** OS2: we don't use the /tmp directory, we use the temp-directory
- which is defined in UUPCSYSRC ***/
- /* tmpthread_file = savestr(filexp("/tmp/thread.%$")); */
-
- tmpstring = (char *)malloc(strlen(uupc_rc_settings.temp_name) + 20);
- sprintf(tmpstring,"%s/thread.%$",uupc_rc_settings.temp_name);
- tmpthread_file = savestr(filexp(tmpstring));
- free(tmpstring);
-
- word_same = long_same = TRUE;
- #ifdef XTHREAD
- sprintf(ser_line, "XTHREAD DBINIT");
- # ifdef DEBUGGING
- if (debug & DEB_NNTP) {
- printf(">%s\n", ser_line) ; FLUSH;
- }
- # endif
- put_server(ser_line);
- size = rawcheck_server(ser_line, sizeof ser_line);
- # ifdef DEBUGGING
- if (debug & DEB_NNTP) {
- printf("<%s\n", ser_line) ; FLUSH;
- }
- # endif
- if (size < 0) {
- printf("\nYour NNTP server isn't XTHREAD-compliant.\n") FLUSH;
- return;
- }
- size = rawget_server((char*)&mt_bmap, (long)sizeof (BMAP));
- if (size >= sizeof (BMAP) - 1) {
- #else /* !XTHREAD */
- tmpstring = filexp(DBINIT);
- if ((fp = fos2open(filexp(DBINIT), FOPEN_RB)) != Nullfp
- && fread((char*)&mt_bmap, 1, sizeof(BMAP), fp) >= sizeof (BMAP) - 1) {
- #endif
- if (mt_bmap.version != DB_VERSION) {
- printf("\nThread database is the wrong version -- ignoring it.\n")
- ; FLUSH;
- use_threads = FALSE;
- }
- mybytemap(&my_bmap);
- for (i = 0; i < sizeof (LONG); i++) {
- if (i < sizeof (WORD)) {
- if (my_bmap.w[i] != mt_bmap.w[i]) {
- word_same = FALSE;
- }
- }
- if (my_bmap.l[i] != mt_bmap.l[i]) {
- long_same = FALSE;
- }
- }
- } else {
- printf("\ndb.init read failed -- assuming no byte-order translations.\n\n") ; FLUSH;
- }
- #ifdef XTHREAD
- while (rawget_server(ser_line, (long)sizeof ser_line)) {
- ; /* trash any extraneous bytes */
- }
- #else
- if (fp != Nullfp) {
- fclose(fp);
- }
- #endif
- }
-
- /* Open a thread file to make use of the data it contains. Everything is
- ** slurped into arrays and buffers, and some minor digesting of the data
- ** is performed to make it more palatable. Be sure to call unuse_data()
- ** before calling this again.
- */
- int
- use_data(thread_if_empty)
- bool_int thread_if_empty;
- {
- register int i, j, k;
- register char *ptr;
- char *threadname;
- bool already_tried = FALSE;
- ART_NUM last, first;
-
- last = getngsize(ng);
- first = getabsfirst(ng, last);
- if (last < first) {
- return 0;
- }
- if (tmpthread_group && strEQ(ngname, tmpthread_group)) {
- threadname = tmpthread_file;
- } else {
- #ifdef XTHREAD /* use remote thread file? */
- long size;
-
- threadname = Nullch; /* assume we fail */
- sprintf(ser_line, "XTHREAD THREAD");
- # ifdef DEBUGGING
- if (debug & DEB_NNTP) {
- printf(">%s\n", ser_line) ; FLUSH;
- }
- # endif
- put_server(ser_line);
- size = rawcheck_server(ser_line, sizeof ser_line);
- # ifdef DEBUGGING
- if (debug & DEB_NNTP) {
- printf("<%s\n", ser_line) ; FLUSH;
- }
- # endif
- if (size < 0) {
- fp = Nullfp;
- } else {
- char *tmpbuf;
- long bufsize;
-
- # ifdef SPEEDOVERMEM
- bufsize = size ? size : 1;
- # else
- bufsize = 16384;
- # endif
- fp = fos2open(tmpthread_file, "w");
- tmpbuf = safemalloc(bufsize);
- while ((size = rawget_server(tmpbuf, bufsize)) != 0) {
- if (fp != Nullfp) {
- /* write it out unbuffered */
- write(fileno(fp), tmpbuf, size);
- }
- }
- free(tmpbuf);
- if (fp != Nullfp) {
- fclose(fp);
- growstr(&tmpthread_group, &tmpthread_glen,
- strlen(ngname) + 1);
- strcpy(tmpthread_group, ngname);
- tmpthread_created = FALSE;
- threadname = tmpthread_file;
- }
- }
- #else /* !XTHREAD */
- threadname = thread_name(ngname);
- #endif
- }
- try_to_use:
- #ifdef XTHREAD
- if (!threadname || (fp = fos2open(threadname, FOPEN_RB)) == Nullfp) {
- if (threadname && errno != ENOENT) {
- #else
- if ((fp = fos2open(threadname, FOPEN_RB)) == Nullfp) {
- if (errno != ENOENT) {
- #endif
- printf("\n\nOpen failed for thread data.\n");
- }
- bzero(&total, sizeof (TOTAL));
- if (!thread_if_empty || already_tried) {
- return 0;
- }
- } else if (fread((char*)&total, 1, sizeof(TOTAL), fp) < sizeof(TOTAL)) {
- fclose(fp);
- bzero(&total, sizeof (TOTAL));
- if (already_tried) {
- return 0;
- }
- } else if (threadname != tmpthread_file || !tmpthread_created) {
- lp_bmap(&total.first, 4);
- wp_bmap(&total.root, 5);
- } else if (!total.root) {
- fclose(fp);
- for (i = firstbit; i <= lastart; i++) {
- oneless(i);
- }
- return 0;
- }
-
- if (total.last < last) {
- #ifdef USETMPTHREAD
- char cmd[512];
- ART_NUM max = last - first + 1;
-
- if (fp) {
- fclose(fp);
- }
- sprintf(cmd, "tmpthread %s %s %ld %ld %ld %s",
- #ifdef XTHREAD
- threadname == tmpthread_file ?
- (tmpthread_created ? "-t" : "-T") : nullstr,
- #else
- threadname == tmpthread_file ? "-t" : nullstr,
- #endif
- ngname, (long)last, (long)first, (long)max, tmpthread_file);
- if (system(filexp(cmd))) {
- printf("\n\nFailed to thread data -- continuing unthreaded.\n");
- if (tmpthread_group) {
- *tmpthread_group = '\0';
- }
- return 0;
- }
- growstr(&tmpthread_group, &tmpthread_glen, strlen(ngname) + 1);
- strcpy(tmpthread_group, ngname);
- threadname = tmpthread_file;
- tmpthread_created = TRUE;
- already_tried = TRUE;
- goto try_to_use;
- #else /* !USETMPTHREAD */
- if (lastart > total.last) {
- tobethreaded = last - total.last;
- toread[ng] -= tobethreaded;
- lastart = total.last;
- }
- #endif /* !USETMPTHREAD */
- }
-
- if (!read_item(&author_cnts, (MEM_SIZE)total.author * sizeof (WORD))
- || !read_item(&strings, (MEM_SIZE)total.string1)
- || !read_item(&subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD))
- || !read_item(&p_roots, (MEM_SIZE)total.root * sizeof (PACKED_ROOT))
- || !read_item(&p_articles, (MEM_SIZE)total.article * sizeof (PACKED_ARTICLE))) {
- printf("\n\nRead failed for thread data -- continuing unthreaded.\n");
- fclose(fp);
- unuse_data(0);
- return 0;
- }
- fclose(fp);
-
- if ((threadname != tmpthread_file || !tmpthread_created)
- && (!word_same || !long_same)) {
- wp_bmap(author_cnts, total.author);
- wp_bmap(subject_cnts, total.subject);
- for (i = 0; i < total.root; i++) {
- lp_bmap(&p_roots[i].root_num, 1);
- wp_bmap(&p_roots[i].articles, 3);
- }
- for (i = 0; i < total.article; i++) {
- lp_bmap(&p_articles[i].num, 2);
- wp_bmap(&p_articles[i].subject, 8);
- }
- }
-
- #ifndef lint
- author_ptrs = (char **)safemalloc(total.author * sizeof (char **));
- subject_ptrs = (char **)safemalloc(total.subject * sizeof (char **));
- root_subjects = (WORD *)safemalloc(total.root * sizeof (WORD));
- root_article_cnts = (WORD *)safemalloc(total.root * sizeof (WORD));
- #endif
- selected_roots = safemalloc(total.root * sizeof (char));
-
- bzero(root_article_cnts, total.root * sizeof (WORD));
- bzero(selected_roots, total.root * sizeof (char));
-
- for (i = 0, ptr = strings; i < total.author; i++) {
- author_ptrs[i] = ptr;
- ptr += strlen(ptr) + 1;
- }
-
- for (i = 0, j = 0; i < total.root; i++) {
- root_subjects[i] = j;
- k = p_roots[i].subject_cnt;
- while (k--) {
- root_article_cnts[i] += subject_cnts[j];
- subject_ptrs[j++] = ptr;
- ptr += strlen(ptr) + 1;
- }
- if (saved_selections) {
- for (k = 0; k < selected_root_cnt; k++) {
- if (p_roots[i].root_num == saved_selections[k]) {
- selected_roots[i] = 1;
- break;
- }
- }
- }
- }
-
- if (total.last > lastart) {
- #ifdef SERVER
- if (time(Null(time_t*)) - lastactfetch > MINFETCHTIME) {
- fclose(actfp);
- ngdata_init(); /* re-grab the active file */
- }
- #endif
- grow_ctl(total.last); /* sets lastart */
- ngmax[ng] = lastart; /* ensure getngsize() knows the new maximum */
- }
- count_roots(!saved_selections);
-
- /* Try to clean up the bitmap if articles are missing. */
- if (unthreaded) {
- char *newarea, *oldarea = ctlarea;
- extern MEM_SIZE ctlsize;
-
- newarea = ctlarea = safemalloc(ctlsize);
- bzero(ctlarea, ctlsize);
- for (i = total.article, p_art = p_articles; i--; p_art++) {
- if (p_art->num >= firstbit) {
- ctl_set(p_art->num);
- }
- }
- for (i = firstbit; i <= lastart; i++) {
- if (!ctl_read(i)) {
- ctlarea = oldarea;
- oneless(i);
- ctlarea = newarea;
- }
- }
- ctlarea = oldarea;
- free(newarea);
- p_art = Nullart;
- count_roots(FALSE);
- }
- safefree(&saved_selections);
- select_page = 0;
- return 1;
- }
-
- /* A shorthand for reading a chunk of the file into a malloced array.
- */
- static int
- read_item(dest, len)
- char **dest;
- MEM_SIZE len;
- {
- int ret;
-
- *dest = safemalloc(len);
- ret = fread(*dest, 1, (int)len, fp);
- if (ret != len) {
- free(*dest);
- *dest = Nullch;
- return 0;
- }
- return 1;
- }
-
- /* Free some memory if it hasn't already been freed.
- */
- static void
- safefree(pp)
- char **pp;
- {
- if (*pp) {
- free(*pp);
- *pp = Nullch;
- }
- }
-
- /* Discard the thread data that we received through the use_data() call.
- ** If "save_selections" is non-zero, we'll try to remember which roots
- ** are currently selected long enough for the use_data() call to re-use
- ** them. Only do this when you are going to re-open the same data file
- ** immediately with use_data() (presumably because the data has been
- ** updated while we were using it).
- */
- void
- unuse_data(save_selections)
- bool_int save_selections;
- {
- int i, j;
-
- if (save_selections) {
- #ifndef lint
- saved_selections
- = (ART_NUM *)safemalloc(selected_root_cnt * sizeof (ART_NUM));
- #endif
- for (i = 0, j = 0; i < total.root; i++) {
- if (selected_roots[i]) {
- saved_selections[j++] = p_roots[i].root_num;
- }
- }
- } else {
- selected_root_cnt = selected_count = 0;
- }
- safefree(&p_roots);
- safefree(&root_subjects);
- safefree(&author_cnts);
- safefree(&subject_cnts);
- safefree(&author_ptrs);
- safefree(&subject_ptrs);
- safefree(&root_article_cnts);
- safefree(&selected_roots);
- safefree(&p_articles);
- safefree(&strings);
-
- p_art = curr_p_art = Nullart;
- init_tree(); /* free any tree lines */
-
- bzero(&total, sizeof (TOTAL));
- }
-
- #endif /* USETHREADS */
-