Exemple #1
0
/**
 * Associate a new session with this instance of the filter.
 *
 * Create the file to log to and open it.
 *
 * @param instance	The filter instance data
 * @param session	The session itself
 * @return Session specific data for this session
 */
static	void	*
newSession(FILTER *instance, SESSION *session)
{
TOPN_INSTANCE	*my_instance = (TOPN_INSTANCE *)instance;
TOPN_SESSION	*my_session;
int		i;
char		*remote, *user;

	if ((my_session = calloc(1, sizeof(TOPN_SESSION))) != NULL)
	{
		if ((my_session->filename =
			(char *)malloc(strlen(my_instance->filebase) + 20))
						== NULL)
		{
			free(my_session);
			return NULL;
		}
		sprintf(my_session->filename, "%s.%d", my_instance->filebase,
				my_instance->sessions);
		my_instance->sessions++;
		my_session->top = (TOPNQ **)calloc(my_instance->topN + 1,
						sizeof(TOPNQ *));
		for (i = 0; i < my_instance->topN; i++)
		{
			my_session->top[i] = (TOPNQ *)calloc(1, sizeof(TOPNQ));
			my_session->top[i]->sql = NULL;
		}
		my_session->n_statements = 0;
		my_session->total.tv_sec = 0;
		my_session->total.tv_usec = 0;
		my_session->current = NULL;
		if ((remote = session_get_remote(session)) != NULL)
			my_session->clientHost = strdup(remote);
		else
			my_session->clientHost = NULL;
		if ((user = session_getUser(session)) != NULL)
			my_session->userName = strdup(user);
		else
			my_session->userName = NULL;
		my_session->active = 1;
		if (my_instance->source && strcmp(my_session->clientHost,
							my_instance->source))
			my_session->active = 0;
		if (my_instance->user && strcmp(my_session->userName,
							my_instance->user))
			my_session->active = 0;

		sprintf(my_session->filename, "%s.%d", my_instance->filebase,
				my_instance->sessions);
		gettimeofday(&my_session->connect, NULL);
	}

	return my_session;
}
Exemple #2
0
/**
 * Associate a new session with this instance of the filter.
 *
 * Create the file to log to and open it.
 *
 * @param instance	The filter instance data
 * @param session	The session itself
 * @return Session specific data for this session
 */
static	void	*
newSession(FILTER *instance, SESSION *session)
{
QLA_INSTANCE	*my_instance = (QLA_INSTANCE *)instance;
QLA_SESSION	*my_session;
char		*remote, *userName;

	if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL)
	{
		if ((my_session->filename =
			(char *)malloc(strlen(my_instance->filebase) + 20))
						== NULL)
		{
			free(my_session);
			return NULL;
		}
		my_session->active = 1;
		if (my_instance->source 
			&& (remote = session_get_remote(session)) != NULL)
		{
			if (strcmp(remote, my_instance->source))
				my_session->active = 0;
		}
		userName = session_getUser(session);
		if (my_instance->userName && userName && strcmp(userName,
							my_instance->userName))
			my_session->active = 0;
		sprintf(my_session->filename, "%s.%d", my_instance->filebase,
				my_instance->sessions);
		my_instance->sessions++;
		if (my_session->active)
			my_session->fp = fopen(my_session->filename, "w");
	}

	return my_session;
}
Exemple #3
0
/**
 * The routeQuery entry point. This is passed the query buffer
 * to which the filter should be applied. Once processed the
 * query is passed to the downstream component
 * (filter or router) in the filter chain.
 *
 * The function checks whether required logging trigger conditions are met and if so, 
 * tries to extract a SQL query out of the query buffer, canonize the query, add 
 * a timestamp to it and publish the resulting string on the exchange.
 * The message is tagged with an unique identifier and the clientReply will
 * use the same identifier for the reply from the backend to form a query-reply pair.
 * 
 * @param instance	The filter instance data
 * @param session	The filter session
 * @param queue		The query data
 */
static	int	
routeQuery(FILTER *instance, void *session, GWBUF *queue)
{
  MQ_SESSION	*my_session = (MQ_SESSION *)session;
  MQ_INSTANCE	*my_instance = (MQ_INSTANCE *)instance;
  char		*ptr, t_buf[128], *combined,*canon_q,*sesshost,*sessusr;
  bool		success = false, src_ok = false,schema_ok = false,obj_ok = false;
  int		length, i, j,dbcount = 0;
  char**	sesstbls;
  unsigned int	plen = 0;
  amqp_basic_properties_t *prop;  

  /**The user is changing databases*/
  if(*((char*)(queue->start + 4)) == 0x02){
    if(my_session->db){
      free(my_session->db);
    }
    plen = pktlen(queue->start);
    my_session->db = calloc(plen,sizeof(char));
    memcpy(my_session->db,queue->start + 5,plen - 1);
  }

  if(modutil_is_SQL(queue)){

    /**Parse the query*/
   
    if (!query_is_parsed(queue)){
      success = parse_query(queue);
    }

    if(!success){
      skygw_log_write(LOGFILE_ERROR,"Error: Parsing query failed.");      
      goto send_downstream;
    }

    if(!my_instance->log_all){
      if(!skygw_is_real_query(queue)){
	goto send_downstream;
      }
    } 

    if(my_instance->trgtype == TRG_ALL){
      skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_ALL");
      schema_ok = true;
      src_ok = true;
      obj_ok = true;
      goto validate_triggers;
    }
    
    if(my_instance->trgtype & TRG_SOURCE && my_instance->src_trg){
      
      if(session_isvalid(my_session->session)){
	
        sessusr = session_getUser(my_session->session);
	sesshost = session_get_remote(my_session->session);
	
	/**Username was configured*/
	if(my_instance->src_trg->usize > 0){
	  for(i = 0;i<my_instance->src_trg->usize;i++){

	    if(strcmp(my_instance->src_trg->user[i],sessusr) == 0)
	      {
		skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SOURCE: user: %s = %s",my_instance->src_trg->user[i],sessusr);
		src_ok = true;
		break;
	      }
	    
	  }

	  
	}

	/**If username was not matched, try to match hostname*/

	if(!src_ok && my_instance->src_trg->hsize > 0){

	  for(i = 0;i<my_instance->src_trg->hsize;i++){
	    
	    if(strcmp(my_instance->src_trg->host[i],sesshost) == 0)
	      {
		skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SOURCE: host: %s = %s",my_instance->src_trg->host[i],sesshost);
		src_ok = true;
		break;
	      }
	  
	  }

	}

      }

      if(src_ok && !my_instance->strict_logging){
	schema_ok = true;
	obj_ok = true;
	goto validate_triggers;
      }

    }else{
      src_ok = true;
    }



    if(my_instance->trgtype & TRG_SCHEMA && my_instance->shm_trg){
      int tbsz = 0,z;
      char** tblnames = skygw_get_table_names(queue,&tbsz,true);
      char* tmp;
      bool all_remotes = true;

      for(z = 0;z<tbsz;z++){
	if((tmp = strchr(tblnames[z],'.')) != NULL){
	  char *lasts;
	  tmp = strtok_r(tblnames[z],".",&lasts);
	  for(i = 0; i<my_instance->shm_trg->size; i++){
	    
	    if(strcmp(tmp,my_instance->shm_trg->objects[i]) == 0){
	      
	      skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SCHEMA: %s = %s",tmp,my_instance->shm_trg->objects[i]);
	      
	      schema_ok = true;
	      break;
	    }
	  } 
	}else{
	  all_remotes = false;
	}
	free(tblnames[z]);
      }
      free(tblnames);

      if(!schema_ok && !all_remotes && my_session->db && strlen(my_session->db)>0){

	for(i = 0; i<my_instance->shm_trg->size; i++){
	  
	  if(strcmp(my_session->db,my_instance->shm_trg->objects[i]) == 0){
	    
	    skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_SCHEMA: %s = %s",my_session->db,my_instance->shm_trg->objects[i]);
	    
	    schema_ok = true;
	    break;
	  }
	}
      }

      if(schema_ok && !my_instance->strict_logging){
	src_ok = true;
	obj_ok = true;
	goto validate_triggers;
      }

    }else{
      schema_ok = true;
    }


    if(my_instance->trgtype & TRG_OBJECT && my_instance->obj_trg){

      sesstbls = skygw_get_table_names(queue,&dbcount,false);

      for(j = 0; j<dbcount; j++){      
	char* tbnm = NULL;

	if((strchr(sesstbls[j],'.')) != NULL){
	  char *lasts;
	  tbnm = strtok_r(sesstbls[j],".",&lasts);
	  tbnm = strtok_r(NULL,".",&lasts);
	}else{
	  tbnm = sesstbls[j];
	}
	

	for(i = 0; i<my_instance->obj_trg->size; i++){
	  

	  if(!strcmp(tbnm,my_instance->obj_trg->objects[i])){
	    obj_ok = true;
	    skygw_log_write_flush(LOGFILE_TRACE,"Trigger is TRG_OBJECT: %s = %s",my_instance->obj_trg->objects[i],sesstbls[j]);
	    break;
	  }

	}

      }
      if(dbcount > 0){
	for(j = 0; j<dbcount; j++){
	  free(sesstbls[j]);
	}
	free(sesstbls);
	dbcount = 0;
      }

      if(obj_ok && !my_instance->strict_logging){
	src_ok = true;
	schema_ok = true;
	goto validate_triggers;
      }

    }else{
      obj_ok = true;
    }


  validate_triggers:

    if(src_ok&&schema_ok&&obj_ok){

      /**
       * Something matched the trigger, log the query
       */

      skygw_log_write_flush(LOGFILE_TRACE,"Routing message to: %s:%d %s as %s/%s, exchange: %s<%s> key:%s queue:%s",
			    my_instance->hostname,my_instance->port,
			    my_instance->vhost,my_instance->username,
			    my_instance->password,my_instance->exchange,
			    my_instance->exchange_type,my_instance->key,
			    my_instance->queue);

      if(my_session->uid == NULL){

	my_session->uid = calloc(33,sizeof(char));

	if(!my_session->uid){
	  skygw_log_write(LOGFILE_ERROR,"Error : Out of memory.");
	}else{
	  genkey(my_session->uid,32);
	}

      }
    
      if (queue->next != NULL)
      {
        queue = gwbuf_make_contiguous(queue);
      }
      
      if(modutil_extract_SQL(queue, &ptr, &length)){

	my_session->was_query = true;
      
	if((prop = malloc(sizeof(amqp_basic_properties_t)))){
	  prop->_flags = AMQP_BASIC_CONTENT_TYPE_FLAG |
	    AMQP_BASIC_DELIVERY_MODE_FLAG |
	    AMQP_BASIC_MESSAGE_ID_FLAG | 
	    AMQP_BASIC_CORRELATION_ID_FLAG;
	  prop->content_type = amqp_cstring_bytes("text/plain");
	  prop->delivery_mode = AMQP_DELIVERY_PERSISTENT;
	  prop->correlation_id = amqp_cstring_bytes(my_session->uid);
	  prop->message_id = amqp_cstring_bytes("query");
	}

   

	if(success){
      
	  /**Try to convert to a canonical form and use the plain query if unsuccessful*/
	  if((canon_q = skygw_get_canonical(queue)) == NULL){
	    skygw_log_write_flush(LOGFILE_ERROR,
				  "Error: Cannot form canonical query.");	
	  }

	}
 
	memset(t_buf,0,128);      
	sprintf(t_buf, "%lu|",(unsigned long)time(NULL));

	int qlen = strnlen(canon_q,length) + strnlen(t_buf,128);
	if((combined = malloc((qlen+1)*sizeof(char))) == NULL){
	  skygw_log_write_flush(LOGFILE_ERROR,
				"Error: Out of memory");
	}
	strcpy(combined,t_buf);
	strncat(combined,canon_q,length);
      
	pushMessage(my_instance,prop,combined);
	free(canon_q);
      }

    } 

    /** Pass the query downstream */
  }
 send_downstream:
  return my_session->down.routeQuery(my_session->down.instance,
				     my_session->down.session, queue);
}
Exemple #4
0
/**
 * Associate a new session with this instance of the filter.
 *
 * Create the file to log to and open it.
 *
 * @param instance	The filter instance data
 * @param session	The session itself
 * @return Session specific data for this session
 */
static	void	*
newSession(FILTER *instance, SESSION *session)
{
QLA_INSTANCE	*my_instance = (QLA_INSTANCE *)instance;
QLA_SESSION	*my_session;
char		*remote, *userName;

	if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL)
	{
		if ((my_session->filename =
			(char *)malloc(strlen(my_instance->filebase) + 20))
						== NULL)
		{
			LOGIF(LE, (skygw_log_write(
				LOGFILE_ERROR,
			      "Error : Memory allocation for qla filter "
			      "file name failed due to %d, %s.",
			      errno,
			      strerror(errno))));
			free(my_session);
			return NULL;
		}
		my_session->active = 1;
		
		if (my_instance->source 
			&& (remote = session_get_remote(session)) != NULL)
		{
			if (strcmp(remote, my_instance->source))
				my_session->active = 0;
		}
		userName = session_getUser(session);
		
		if (my_instance->userName && 
			userName && 
			strcmp(userName,my_instance->userName))
		{
			my_session->active = 0;
		}
		sprintf(my_session->filename, "%s.%d", 
			my_instance->filebase,
			my_instance->sessions);

        // Multiple sessions can try to update my_instance->sessions simultaneously
		atomic_add(&(my_instance->sessions), 1);
		
		if (my_session->active)
		{
			my_session->fp = fopen(my_session->filename, "w");
			
			if (my_session->fp == NULL)
			{
				LOGIF(LE, (skygw_log_write(
					LOGFILE_ERROR,
					"Error : Opening output file for qla "
					"fileter failed due to %d, %s",
					errno,
					strerror(errno))));
				free(my_session->filename);
				free(my_session);
				my_session = NULL;
			}
		}
	}
	else
	{
		LOGIF(LE, (skygw_log_write(
			LOGFILE_ERROR,
			"Error : Memory allocation for qla filter failed due to "
			"%d, %s.",
			errno,
			strerror(errno))));
	}
	return my_session;
}
Exemple #5
0
/**
 * Associate a new session with this instance of the filter.
 *
 * Create the file to log to and open it.
 *
 * @param instance	The filter instance data
 * @param session	The session itself
 * @return Session specific data for this session
 */
static void *
newSession(FILTER *instance, SESSION *session)
{
    TEE_INSTANCE *my_instance = (TEE_INSTANCE *) instance;
    TEE_SESSION *my_session;
    char *remote, *userName;

    if (strcmp(my_instance->service->name, session->service->name) == 0)
    {
        MXS_ERROR("%s: Recursive use of tee filter in service.",
                  session->service->name);
        my_session = NULL;
        goto retblock;
    }

    HASHTABLE* ht = hashtable_alloc(100, simple_str_hash, strcmp);
    bool is_loop = detect_loops(my_instance, ht, session->service);
    hashtable_free(ht);

    if (is_loop)
    {
        MXS_ERROR("%s: Recursive use of tee filter in service.",
                  session->service->name);
        my_session = NULL;
        goto retblock;
    }

    if ((my_session = calloc(1, sizeof(TEE_SESSION))) != NULL)
    {
        my_session->active = 1;
        my_session->residual = 0;
        my_session->tee_replybuf = NULL;
        my_session->client_dcb = session->client;
        my_session->instance = my_instance;
        my_session->client_multistatement = false;
        my_session->queue = NULL;
        spinlock_init(&my_session->tee_lock);
        if (my_instance->source &&
            (remote = session_get_remote(session)) != NULL)
        {
            if (strcmp(remote, my_instance->source))
            {
                my_session->active = 0;

                MXS_WARNING("Tee filter is not active.");
            }
        }
        userName = session_getUser(session);

        if (my_instance->userName &&
            userName &&
            strcmp(userName, my_instance->userName))
        {
            my_session->active = 0;

            MXS_WARNING("Tee filter is not active.");
        }

        if (my_session->active)
        {
            DCB* dcb;
            SESSION* ses;
            FILTER_DEF* dummy;
            UPSTREAM* dummy_upstream;

            if ((dcb = dcb_clone(session->client)) == NULL)
            {
                freeSession(instance, (void *) my_session);
                my_session = NULL;

                MXS_ERROR("Creating client DCB for Tee "
                          "filter failed. Terminating session.");

                goto retblock;
            }

            if ((dummy = filter_alloc("tee_dummy", "tee_dummy")) == NULL)
            {
                dcb_close(dcb);
                freeSession(instance, (void *) my_session);
                my_session = NULL;
                MXS_ERROR("tee: Allocating memory for "
                          "dummy filter definition failed."
                          " Terminating session.");

                goto retblock;
            }



            if ((ses = session_alloc(my_instance->service, dcb)) == NULL)
            {
                filter_free(dummy);
                dcb_close(dcb);
                freeSession(instance, (void *) my_session);
                my_session = NULL;
                MXS_ERROR("Creating client session for Tee "
                          "filter failed. Terminating session.");

                goto retblock;
            }

            ss_dassert(ses->ses_is_child);

            dummy->obj = GetModuleObject();
            dummy->filter = NULL;
            my_session->branch_session = ses;
            my_session->branch_dcb = dcb;
            my_session->dummy_filterdef = dummy;

            if ((dummy_upstream = filterUpstream(
                                                 dummy, my_session, &ses->tail)) == NULL)
            {
                filter_free(dummy);
                closeSession(instance, (void*) my_session);
                dcb_close(dcb);
                free(my_session);
                MXS_ERROR("tee: Allocating memory for"
                          "dummy upstream failed."
                          " Terminating session.");

                return NULL;
            }

            ses->tail = *dummy_upstream;
            MySQLProtocol* protocol = (MySQLProtocol*) session->client->protocol;
            my_session->use_ok = protocol->client_capabilities & (1 << 6);
            free(dummy_upstream);
        }
    }
retblock:
    return my_session;
}