Hallo Lude,
Hi ( CK ?),
Steht da 'Christian Kruse' im 'Name'-Feld? :)
ich bat um die Formel, die zu archiviernde
Threads aus der "XML-Hauptdatei" entfernt.
Gibts nicht.
Kann man mir die betreffende Stelle im Code,
eventuell sogar leicht kommentiert, zeigen?
Ehm, warum habe ich den Source offengelegt? Ich
glaube, das naechste wird closed source... da
kann ich dann Geld dafuer verlangen >;)) Aber gut,
Ausnahmsweise ;)
void run_archiver_and_write_to_disk(void) {
/* helper variables */
t_thread *t,*t1 = NULL,*oldest_t,*prev = NULL,**to_archive = NULL,*oldest_prev;
t_posting *p,*oldest,*newest_in_t;
long size,threadnum,pnum;
int status,shall_archive = 0,len = 0;
char buff[256];
pid_t pid;
/* configuration entries */
t_name_value *max_bytes = cfg_get_value(&fo_default_conf,"MainFileMaxBytes");
t_name_value *max_posts = cfg_get_value(&fo_default_conf,"MainFileMaxPostings");
t_name_value *max_threads = cfg_get_value(&fo_default_conf,"MainFileMaxThreads");
t_name_value *mpath = cfg_get_value(&fo_default_conf,"MessagePath");
/* Helper-Variables for XML-Handling */
GdomeDOMImplementation *impl = gdome_di_mkref();
GdomeException e;
GdomeDocument *doc = xml_create_doc(impl,FORUM_DTD);
GdomeElement *el = gdome_doc_documentElement(doc,&e);
/*
* we archive as long as a criterium matches, but the check has to be done
* at least once.
/
do {
/
* read-lock the head variable
*/
if((status = pthread_rwlock_rdlock(&head.lock)) != 0) {
fo_log(LOG_ERR,FILE,LINE,"pthread_rwlock_rdlock: %s\n",strerror(status));
RUN = 0;
return;
}
/*
* initialization of the helper variables
*/
size = head.cache_invisible.len;
t = head.thread;
threadnum = 0;
pnum = 0;
shall_archive = 0;
oldest = NULL;
oldest_t = NULL;
oldest_prev = NULL;
newest_in_t = NULL;
/*
* unlock the head-variable
*/
pthread_rwlock_unlock(&head.lock);
/*
* run through all threads in the forum
/
do {
/
* read-lock the actual thread
*/
if((status = pthread_rwlock_rdlock(&t->lock)) != 0) {
fo_log(LOG_ERR,FILE,LINE,"pthread_rwlock_rdlock: %s\n",strerror(status));
RUN = 0;
return;
}
/*
* we found one more thread
*/
threadnum++;
/*
* find the newest posting in this thread and count the postings
*/
newest_in_t = NULL;
for(p=t->postings;p;p=p->next) {
if(!newest_in_t || newest_in_t->date < p->date) {
newest_in_t = p;
}
pnum++;
}
/*
* check if the thread has a posting elder than the oldest posting before; if yes,
* re-set the helper variables
*/
if(!oldest || newest_in_t->date < oldest->date) {
oldest = newest_in_t;
oldest_t = t;
oldest_prev = prev;
}
/* go to the next thread */
prev = t1;
t1 = t->next;
pthread_rwlock_unlock(&t->lock);
t = t1;
} while(t);
/*
* has the main file more bytes than the configuration limit? If yes, archive a thread
*/
if(size > max_bytes->lvals[0]) {
shall_archive = 1;
fo_log(LOG_STD,FILE,LINE,"Archiver: Criterium: max bytes, Values: Config: %ld, Real: %ld\n",max_bytes->lvals[0],size);
}
/*
* are there more postings than allowed via config? If yes, archive the oldest thread
*/
if(pnum > max_posts->lvals[0]) {
shall_archive = 1;
fo_log(LOG_STD,FILE,LINE,"Archiver: Criterium: max posts, Values: Config: %ld, Real: %ld\n",max_posts->lvals[0],pnum);
}
/*
* are there more threads as given in the config? If yes, archive.
*/
if(threadnum > max_threads->lvals[0]) {
shall_archive = 1;
fo_log(LOG_STD,FILE,LINE,"Archiver: Criterium: max threads, Values: Config: %ld, Real: %ld\n",max_threads->lvals[0],threadnum);
}
/*
* does any of the criteriums match? If yes, push the oldest thread in the tree to an
* array.
*/
if(shall_archive) {
to_archive = realloc(to_archive,++len * sizeof(t_thread *));
to_archive[len-1] = oldest_t;
/*
* is there a thread before? If yes, lock it and re-set the next-pointer. If not,
* we have to re-set the head.thread-pointer.
*/
if(oldest_prev) {
if((status = pthread_rwlock_wrlock(&oldest_prev->lock)) != 0) {
fo_log(LOG_ERR,FILE,LINE,"pthread_rwlock_wrlock: %s\n",strerror(status));
RUN = 0;
return;
}
oldest_prev->next = oldest_t->next;
pthread_rwlock_unlock(&oldest_prev->lock);
}
else {
if((status = pthread_rwlock_wrlock(&head.lock)) != 0) {
fo_log(LOG_ERR,FILE,LINE,"pthread_rwlock_wrlock: %s\n",strerror(status));
RUN = 0;
return;
}
head.thread = oldest_t->next;
pthread_rwlock_unlock(&head.lock);
}
/*
* generate a new cache
*/
generate_cache(NULL);
}
/*
* run archiver as long as any of the criteriums matches
*/
} while(shall_archive);
fo_log(LOG_DBG,FILE,LINE,"archiver ran. Writing threadlists...\n");
/*
* at all, the threads to archive are out of the main-file. So go and write the main file
* and the thread files.
*/
if((status = pthread_rwlock_rdlock(&head.lock)) != 0) {
fo_log(LOG_ERR,FILE,LINE,"pthread_rwlock_rdlock: %s\n",strerror(status));
RUN = 0;
return;
}
t = head.thread;
sprintf(buff,"m%lld",head.mid);
xml_set_attribute(el,"lastMessage",buff);
sprintf(buff,"t%lld",head.tid);
xml_set_attribute(el,"lastThread",buff);
gdome_el_unref(el,&e);
pthread_rwlock_unlock(&head.lock);
/*
* very nasty workaround for a memory leek in the gdome lib
*
* Hm, this has a nice effect: normally when the archiver runs, the
* server would lag a little bit. But since all expensive operations
* are done in a child process, the server itself would not lag longer
/
pid = fork();
switch(pid) {
/ error */
case -1:
fo_log(LOG_ERR,FILE,LINE,"fork: %s\n",strerror(errno));
break;
/* child actions /
case 0:
/ go through the thread list and "stringify" the threads */
do {
if((status = pthread_rwlock_rdlock(&t->lock)) != 0) {
fo_log(LOG_ERR,FILE,LINE,"pthread_rwlock_rdlock: %s\n",strerror(status));
exit(0);
}
stringify_thread_and_write_to_disk(doc,t);
t1 = t->next;
pthread_rwlock_unlock(&t->lock);
t = t1;
} while(t);
/* write the main file */
snprintf(buff,256,"%s/forum.xml",mpath->cvals[0]);
if(!gdome_di_saveDocToFile(impl,doc,buff,0,&e)) {
fo_log(LOG_ERR,FILE,LINE,"ERROR! COULD NOT WRITE XML FILE!\n");
}
gdome_doc_unref(doc,&e);
/* child has done all work */
exit(0);
break;
/* main program actions. We just wait for the child */
default:
fo_log(LOG_STD,FILE,LINE,"archiver started....\n");
wait(&pid);
break;
}
/* delete the main file document */
gdome_doc_unref(doc,&e);
/* are there threads to archive? If yes, write them to the archive. */
if(len) {
long i;
pid = fork();
/* nasty workaround... */
switch(pid) {
case -1:
fo_log(LOG_ERR,FILE,LINE,"fork: %s\n",strerror(errno));
break;
case 0:
archive_threads(to_archive,len);
exit(0);
default:
fo_log(LOG_DBG,FILE,LINE,"waiting for archive_threads\n");
wait(&pid);
break;
}
/* when all threads have been written, free allocated memory */
for(i=0;i<len;i++) {
t_posting *p = NULL,*p1 = NULL;
for(p=to_archive[i]->postings;p;p=p1) {
free(p->user.name);
free(p->user.ip);
free(p->subject);
free(p->unid);
free(p->content);
if(p->user.email) free(p->user.email);
if(p->user.img) free(p->user.img);
if(p->user.hp) free(p->user.hp);
if(p->category) free(p->category);
p1 = p->next;
free(p);
}
}
free(to_archive);
}
/* we don't need any longer the DOM-Implementation */
gdome_di_unref(impl,&e);
}
Gruesse,
CK