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