示例#1
0
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;
}
示例#2
0
/*++++++++++++++++++++++++++++++++++++++
   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;
}
示例#3
0
/*++++++++++++++++++++++++++++++++++++++
  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 );
}
示例#4
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;
}
示例#5
0
/* 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);
}