static atom_t add_string(unsigned char *cs, int len) { pthread_mutex_lock(&mutex_string); //printf("add_string(%c,%c,%i)\n",cs[0],cs[1],len); assert(len >= 0); assert(len < MAX_ENTRY_SIZE); assert(next_free_offset < CHUNK_SIZE); if(next_free_offset + 1 > CHUNK_SIZE - MAX_ENTRY_SIZE) { dieif(current_chunk >= NUM_CHUNKS - 1, "No more chunks"); current_chunk++; assert(!stringtable_chunks[current_chunk]); stringtable_chunks[current_chunk] = malloc(CHUNK_SIZE); dieif(!stringtable_chunks[current_chunk], "error alocating memory"); next_free_offset = 0; } memcpy(stringtable_chunks[current_chunk] + next_free_offset, cs, len); atom_t r = MAKE_ATOM(current_chunk, next_free_offset, len); assert(CHUNK_INDEX(r) == current_chunk); assert(CHUNK_OFFSET(r) == next_free_offset); assert(ATOM_PTR(r) == stringtable_chunks[current_chunk] + next_free_offset); assert(ATOM_LEN(r) == len); next_free_offset += len; assert(next_free_offset < CHUNK_SIZE); assert(current_chunk < NUM_CHUNKS); pthread_mutex_unlock(&mutex_string); return r; }
/*++++++++++++++++++++++++++++++++++++++ starts sk_watchdog thread unless already started, and registers its threadid in the condat structure dies if watchdog already running int SK_watchstart Returns SK_OK on success. sk_conn_st *condat pointer to the connection data structure The structure may (and normally, should) contain the predefined actions set by SK_watch_set... functions. ++++++++++++++++++++++++++++++++++++++*/ int SK_watchstart(sk_conn_st *condat) { dieif( condat->watchdog != 0 ); /* init the mutex in locked state, watchdog will unlock it when it's ready for signal/cancellation */ pthread_mutex_init( & condat->watchmutex, NULL ); pthread_mutex_lock( & condat->watchmutex ); /* Linux doesn't seem to like getting signals in select(), which isn't technically allowed by POSIX. The workaround in this case is simply to not create a watchdog for Linux. This is probably acceptable because we will be changing the query path to perform queries in small chunks, so if a disconnect occurs it won't consume a lot of database resources in any case, even without a watchdog. SCO has a really small stack, so we don't want to create extra threads. */ #if !defined(__linux__) && !defined(SCO) /* NOT DETACHED! */ pthread_create(&condat->watchdog, NULL, sk_watchdog, (void *) condat ); #endif /* __linux__ */ return SK_OK; }
/*++++++++++++++++++++++++++++++++++++++ initialisation for the SIGNAL cancellation mode - initialises the thread specific flag. ++++++++++++++++++++++++++++++++++++++*/ static void sk_real_init(void) { dieif( pthread_key_create( &sk_watch_tsd, NULL) != 0 ); }
/*++++++++++++++++++++++++++++++++++++++ watchdog (SIGNAL VERSION) - started as a separate thread. Selects on the given socket; discards all input. whenever it sees end of file (socket closed), it * sets a corresponding flag in the condat structure, * triggers the predefined actions (by SK_watchtrigger). void *arg - pointer to the connection data structure ++++++++++++++++++++++++++++++++++++++*/ static void *sk_watchdog(void *arg) { sk_conn_st *condat = (sk_conn_st *) arg; int nready; int n; fd_set rset; char buff[STR_S]; int socket = condat->sock; sigset_t sset; struct sigaction act; struct timeval timeout = { 1, 0 }; /* it's a timeout of 1 second */ FD_ZERO(&rset); FD_SET(socket, &rset); sigemptyset(&sset); sigaddset(&sset, SIGUSR2); act.sa_handler = func_sigusr; act.sa_flags = 0; dieif(sigaction(SIGUSR2, &act, NULL) != 0); /* XXX in fact, it's unblocked already. Should be blocked on startup */ dieif(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) != 0); /* clear the handler's flag */ pthread_setspecific(sk_watch_tsd, NULL); /* now ready for signal */ pthread_mutex_unlock( & condat->watchmutex ); /* hey, viva threaded signal handling! There is no way for select to unblock a blocked signal, It must be done by "hand" (above). Consequently, every once in a while, the signal will be delivered before the select starts :-/. So, we have to introduce a timeout for select and check if the signal was delivered anyway....aARGH!!! This adds a <timeout interval> to unlucky queries, about 0.1% of all. */ while ((nready=select(socket+1, &rset, NULL, NULL, &timeout))!=-1) { LG_log(sk_context, LG_DEBUG, "select returned %d", nready); /* don't even try to read if we have been killed */ if( errno == EINTR || pthread_getspecific(sk_watch_tsd) != NULL ) { break; } /* retry if the timeout has triggered */ if( nready == 0 ) { continue; } /* There was some input or client half of connection was closed */ /* Check for the latter */ if (( n=read(socket, buff, sizeof(buff))) == 0) { /* Connection was closed by client */ /* Now send a cancellation request to the whois thread. */ /* mysql thread will be terminated by thread cleanup routine */ /* call the actions: kill and exec (the SK_ functions called check if the action is defined. Will set the RTC flag on condat */ SK_watchtrigger(condat); /* quit */ break; } /* Otherwise dump input and continue */ } /* Exit the watchdog thread, passing NULL as we don't expect a join */ pthread_exit(NULL); /* oh yes. Shouldn't compilers _recognize_ library functions ? */ return NULL; }
/* Loads the aaa table into an in-memory buffer for fast access * Puts write lock on aaa_lock during its operation */ void AA_load() { int i; char buf[1024]; SQ_result_set_t *result; SQ_connection_t *con = NULL; SQ_row_t *row; pthread_rwlock_wrlock(&aaa_lock); for (i = MIN_IPSPACE_ID; i <= MAX_IPSPACE_ID; i++) { /* clear the list */ wr_clear_list(&aaa[i]); /* get the query */ aa_compose_query(i, buf, sizeof(buf)); /* open the database */ if ((con = AC_dbopen_admin()) == NULL) { fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con)); die; } /* select the most specific entry */ if (SQ_execute_query(con, buf, &result) == -1) { fprintf(stderr, "ERROR %d: %s\n", SQ_errno(con), SQ_error(con)); die; } /* read in the rights from the resulting rows */ while ((row = SQ_row_next(result)) != NULL) { aa_rights *rights = calloc(1, sizeof(aa_rights)); dieif(sscanf(SQ_get_column_string_nocopy(result, row, 0), "%u", &rights->ripupdate) < 1); dieif(sscanf(SQ_get_column_string_nocopy(result, row, 1), "%u", &rights->mirror) < 1); dieif(sscanf(SQ_get_column_string_nocopy(result, row, 2), "%s", rights->source) < 1); /* now comes the prefix */ switch (i) { case IP_V4: dieif(IP_pref_f2b_v4(&rights->pref, SQ_get_column_string_nocopy(result, row, 4), SQ_get_column_string_nocopy(result, row, 3)) != IP_OK); break; case IP_V6: dieif(IP_pref_f2b_v6_32(&rights->pref, SQ_get_column_string_nocopy(result, row, 4), SQ_get_column_string_nocopy(result, row, 5), SQ_get_column_string_nocopy(result, row, 6), SQ_get_column_string_nocopy(result, row, 7), SQ_get_column_string_nocopy(result, row, 3)) != IP_OK); dieif(rights->pref.ip.space != IP_V6); /* v4 or v4-mapped address in acl6 table!!! */ break; } aaa[i] = g_list_prepend(aaa[i], rights); } /* release everything */ SQ_free_result(result); /* Close connection */ SQ_close_connection(con); } pthread_rwlock_unlock(&aaa_lock); }