コード例 #1
0
ファイル: testmodutil.c プロジェクト: jhnwkmn/MaxScale
static int
test1()
{
GWBUF   *buffer;
char    *(sql[100]);
int     result, length, residual;

        /* Poll tests */  
        ss_dfprintf(stderr,
                    "testmodutil : Rudimentary tests."); 
        buffer = gwbuf_alloc(100);
        ss_info_dassert(0 == modutil_is_SQL(buffer), "Default buffer should be diagnosed as not SQL");
        /* There would ideally be some straightforward way to create a SQL buffer? */
        ss_dfprintf(stderr, "\t..done\nExtract SQL from buffer");
        ss_info_dassert(0 == modutil_extract_SQL(buffer, sql, &length), "Default buffer should fail");
        ss_dfprintf(stderr, "\t..done\nExtract SQL from buffer different way?");
        ss_info_dassert(0 == modutil_MySQL_Query(buffer, sql, &length, &residual), "Default buffer should fail");
        ss_dfprintf(stderr, "\t..done\nReplace SQL in buffer");
        ss_info_dassert(0 == modutil_replace_SQL(buffer, "select * from some_table;"), "Default buffer should fail");
        ss_dfprintf(stderr, "\t..done\nTidy up.");
        gwbuf_free(buffer);
        ss_dfprintf(stderr, "\t..done\n");
		
	return 0;
        
}
コード例 #2
0
ファイル: modutil.c プロジェクト: Robert-Xie/MaxScale
/**
 * Replace the contents of a GWBUF with the new SQL statement passed as a text string.
 * The routine takes care of the modification needed to the MySQL packet,
 * returning a GWBUF chain that can be used to send the data to a MySQL server
 *
 * @param orig	The original request in a GWBUF
 * @param sql	The SQL text to replace in the packet
 * @return A newly formed GWBUF containing the MySQL packet.
 */
GWBUF *
modutil_replace_SQL(GWBUF *orig, char *sql)
{
unsigned char	*ptr;
int	length, newlength;
GWBUF	*addition;

	if (!modutil_is_SQL(orig))
		return NULL;
	ptr = GWBUF_DATA(orig);
	length = *ptr++;
	length += (*ptr++ << 8);
	length += (*ptr++ << 16);
        ptr += 2;  // Skip sequence id	and COM_QUERY byte

	newlength = strlen(sql);
	if (length - 1 == newlength)
	{
		/* New SQL is the same length as old */
		memcpy(ptr, sql, newlength);
	}
	else if (length - 1 > newlength)
	{
		/* New SQL is shorter */
		memcpy(ptr, sql, newlength);
		GWBUF_RTRIM(orig, (length - 1) - newlength);
                ptr = GWBUF_DATA(orig);
		*ptr++ = (newlength + 1) & 0xff;
		*ptr++ = ((newlength + 1) >> 8) & 0xff;
		*ptr++ = ((newlength + 1) >> 16) & 0xff;
	}
コード例 #3
0
ファイル: slavelag.c プロジェクト: jhnwkmn/MaxScale
/**
 * The routeQuery entry point. This is passed the query buffer
 * to which the filter should be applied. Once applied the
 * query should normally be passed to the downstream component
 * (filter or router) in the filter chain.
 *
 * If the regular expressed configured in the match parameter of the
 * filter definition matches the SQL text then add the hint
 * "Route to named server" with the name defined in the server parameter
 *
 * @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)
{
LAG_INSTANCE	*my_instance = (LAG_INSTANCE *)instance;
LAG_SESSION	*my_session = (LAG_SESSION *)session;
char			*sql;
time_t now = time(NULL);

	if (modutil_is_SQL(queue))
	{
	    if (queue->next != NULL)
	    {
		queue = gwbuf_make_contiguous(queue);
	    }

	    if(!query_is_parsed(queue))
	    {
		parse_query(queue);
	    }

	    if(query_classifier_get_operation(queue) & (QUERY_OP_DELETE|QUERY_OP_INSERT|QUERY_OP_UPDATE))
	    {
		if((sql = modutil_get_SQL(queue)) != NULL)
		{
		    if(my_instance->nomatch == NULL||(my_instance->nomatch && regexec(&my_instance->nore,sql,0,NULL,0) != 0))
		    {
			if(my_instance->match == NULL||
			 (my_instance->match && regexec(&my_instance->re,sql,0,NULL,0) == 0))
			{
			    my_session->hints_left = my_instance->count;
			    my_session->last_modification = now;
			    my_instance->stats.n_modified++;
			}
		    }
		    free(sql);
		}
	    }
	    else if(my_session->hints_left > 0)
	    {
		queue->hint = hint_create_route(queue->hint,
					 HINT_ROUTE_TO_MASTER,
					 NULL);
		my_session->hints_left--;
		my_instance->stats.n_add_count++;
	    }
	    else if(difftime(now,my_session->last_modification) < my_instance->time)
	    {
		queue->hint = hint_create_route(queue->hint,
					 HINT_ROUTE_TO_MASTER,
					 NULL);
		my_instance->stats.n_add_time++;
	    }
	}
	return my_session->down.routeQuery(my_session->down.instance,
			my_session->down.session, queue);
}
コード例 #4
0
ファイル: testfilter.c プロジェクト: bigshuai/MaxScale
/**
 * The routeQuery entry point. This is passed the query buffer
 * to which the filter should be applied. Once applied the
 * query shoudl normally be passed to the downstream component
 * (filter or router) in the filter chain.
 *
 * @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)
{
TEST_SESSION	*my_session = (TEST_SESSION *)session;

	if (modutil_is_SQL(queue))
		my_session->count++;
	return my_session->down.routeQuery(my_session->down.instance,
			my_session->down.session, queue);
}
コード例 #5
0
ファイル: modutil.c プロジェクト: Robert-Xie/MaxScale
/**
 * Extract the SQL portion of a COM_QUERY packet
 *
 * NB This sets *sql to point into the packet and does not
 * allocate any new storage. The string pointed to by *sql is
 * not NULL terminated.
 *
 * This routine is very simplistic and does not deal with SQL text
 * that spans multiple buffers.
 *
 * The length returned is the complete length of the SQL, which may
 * be larger than the amount of data in this packet.
 *
 * @param	buf	The packet buffer
 * @param	sql	Pointer that is set to point at the SQL data
 * @param	length	Length of the SQL query data
 * @return	True if the packet is a COM_QUERY packet
 */
int
modutil_extract_SQL(GWBUF *buf, char **sql, int *length)
{
unsigned char	*ptr;

	if (!modutil_is_SQL(buf))
		return 0;
	ptr = GWBUF_DATA(buf);
	*length = *ptr++;
	*length += (*ptr++ << 8);
	*length += (*ptr++ << 16);
        ptr += 2;  // Skip sequence id	and COM_QUERY byte
	*length = *length - 1;
	*sql = (char *)ptr;
	return 1;
}
コード例 #6
0
ファイル: modutil.c プロジェクト: Robert-Xie/MaxScale
/**
 * Extract the SQL portion of a COM_QUERY packet
 *
 * NB This sets *sql to point into the packet and does not
 * allocate any new storage. The string pointed to by *sql is
 * not NULL terminated.
 *
 * The number of bytes pointed to *sql is returned in *length
 *
 * The remaining number of bytes required for the complete query string
 * are returned in *residual
 *
 * @param	buf		The packet buffer
 * @param	sql		Pointer that is set to point at the SQL data
 * @param	length		Length of the SQL query data pointed to by sql
 * @param	residual	Any remain part of the query in future packets
 * @return	True if the packet is a COM_QUERY packet
 */
int
modutil_MySQL_Query(GWBUF *buf, char **sql, int *length, int *residual)
{
unsigned char	*ptr;

	if (!modutil_is_SQL(buf))
		return 0;
	ptr = GWBUF_DATA(buf);
	*residual = *ptr++;
	*residual += (*ptr++ << 8);
	*residual += (*ptr++ << 16);
        ptr += 2;  // Skip sequence id	and COM_QUERY byte
	*residual = *residual - 1;
	*length = GWBUF_LENGTH(buf) - 5;
	*residual -= *length;
	*sql = (char *)ptr;
	return 1;
}
コード例 #7
0
ファイル: modutil.c プロジェクト: Robert-Xie/MaxScale
/**
 * Calculate the length of MySQL packet and how much is missing from the GWBUF 
 * passed as parameter.
 * 
 * This routine assumes that there is only one MySQL packet in the buffer.
 * 
 * @param buf			buffer list including the query, may consist of 
 * 				multiple buffers
 * @param nbytes_missing	pointer to missing bytecount 
 * 
 * @return the length of MySQL packet and writes missing bytecount to 
 * nbytes_missing.
 */
int modutil_MySQL_query_len(
	GWBUF* buf,
	int*   nbytes_missing)
{
	int     len;
	int     buflen;
	
	if (!modutil_is_SQL(buf))
	{
		len = 0;
		goto retblock;
	}
	len = MYSQL_GET_PACKET_LEN((uint8_t *)GWBUF_DATA(buf)); 
	*nbytes_missing = len-1;
	buflen = gwbuf_length(buf);
	
	*nbytes_missing -= buflen-5;	
	
retblock:
	return len;
}
コード例 #8
0
ファイル: mqfilter.c プロジェクト: AAAAAK/MaxScale
/**
 * 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);
}
コード例 #9
0
ファイル: luafilter.c プロジェクト: bigshuai/MaxScale
/**
 * 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 Luafilter calls the routeQuery functions of both the session and the global script.
 * The query is passed as a string parameter to the routeQuery Lua function and
 * the return values of the session specific function, if any were returned,
 * are interpreted. If the first value is bool, it is interpreted as a decision
 * whether to route the query or to send an error packet to the client.
 * If it is a string, the current query is replaced with the return value and
 * the query will be routed. If nil is returned, the query is routed normally.
 *
 * @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)
{
    LUA_SESSION *my_session = (LUA_SESSION *) session;
    LUA_INSTANCE *my_instance = (LUA_INSTANCE *) instance;
    DCB* dcb = my_session->session->client_dcb;
    char *fullquery = NULL, *ptr;
    bool route = true;
    GWBUF* forward = queue;
    int rc = 0;

    if (modutil_is_SQL(queue) || modutil_is_SQL_prepare(queue))
    {
        fullquery = modutil_get_SQL(queue);

        if (fullquery && my_session->lua_state)
        {
            spinlock_acquire(&my_session->lock);
            lua_getglobal(my_session->lua_state, "routeQuery");
            lua_pushlstring(my_session->lua_state, fullquery, strlen(fullquery));
            if (lua_pcall(my_session->lua_state, 1, 1, 0))
            {
                MXS_ERROR("luafilter: Session scope call to 'routeQuery' failed: '%s'.",
                          lua_tostring(my_session->lua_state, -1));
            }
            else if (lua_gettop(my_session->lua_state))
            {
                if (lua_isstring(my_session->lua_state, -1))
                {
                    if (forward)
                    {
                        gwbuf_free(forward);
                    }
                    forward = modutil_create_query((char*) lua_tostring(my_session->lua_state, -1));
                }
                else if (lua_isboolean(my_session->lua_state, -1))
                {
                    route = lua_toboolean(my_session->lua_state, -1);
                }
            }
            spinlock_release(&my_session->lock);
        }

        if (my_instance->global_lua_state)
        {
            spinlock_acquire(&my_instance->lock);
            lua_getglobal(my_instance->global_lua_state, "routeQuery");
            lua_pushlstring(my_instance->global_lua_state, fullquery, strlen(fullquery));
            if (lua_pcall(my_instance->global_lua_state, 1, 0, 0))
            {
                MXS_ERROR("luafilter: Global scope call to 'routeQuery' failed: '%s'.",
                          lua_tostring(my_session->lua_state, -1));
            }
            else if (lua_gettop(my_instance->global_lua_state))
            {
                if (lua_isstring(my_instance->global_lua_state, -1))
                {
                    if (forward)
                    {
                        gwbuf_free(forward);
                    }
                    forward = modutil_create_query((char*)
                                                   lua_tostring(my_instance->global_lua_state, -1));
                }
                else if (lua_isboolean(my_instance->global_lua_state, -1))
                {
                    route = lua_toboolean(my_instance->global_lua_state, -1);
                }
            }
            spinlock_release(&my_instance->lock);
        }

        free(fullquery);
    }

    if (!route)
    {
        gwbuf_free(queue);
        GWBUF* err = modutil_create_mysql_err_msg(1, 0, 1045, "28000", "Access denied.");
        rc = dcb->func.write(dcb, err);
    }
    else
    {
        rc = my_session->down.routeQuery(my_session->down.instance,
                                         my_session->down.session, forward);
    }

    return rc;
}
コード例 #10
0
ファイル: mqfilter.c プロジェクト: markus456/MaxScale
/**
 * 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 tries to extract a SQL query out of the query buffer,
 * adds a timestamp to it and publishes 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.
 * 
 * @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;
  int		length, err_code = AMQP_STATUS_OK;
  amqp_basic_properties_t prop;
  spinlock_acquire(my_instance->rconn_lock);
  if(my_instance->conn_stat != AMQP_STATUS_OK){

    if(difftime(time(NULL),my_instance->last_rconn) > my_instance->rconn_intv){

      my_instance->last_rconn = time(NULL);

      if(init_conn(my_instance,my_session)){
	my_instance->rconn_intv = 1.0;
	my_instance->conn_stat = AMQP_STATUS_OK;	

      }else{
	my_instance->rconn_intv += 5.0;
	skygw_log_write(LOGFILE_ERROR,
			"Error : Failed to reconnect to the MQRabbit server ");
      }
      err_code = my_instance->conn_stat;
    }
  }
  spinlock_release(my_instance->rconn_lock);

  if(modutil_is_SQL(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 (err_code == AMQP_STATUS_OK){

    if(modutil_extract_SQL(queue, &ptr, &length)){

      my_session->was_query = 1;

      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");

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

      int qlen = 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,ptr,length);
      
      if((err_code = amqp_basic_publish(my_session->conn,my_session->channel,
					amqp_cstring_bytes(my_instance->exchange),
					amqp_cstring_bytes(my_instance->key),
					0,0,&prop,amqp_cstring_bytes(combined))
	  ) != AMQP_STATUS_OK){
	spinlock_acquire(my_instance->rconn_lock);  
	my_instance->conn_stat = err_code;
	spinlock_release(my_instance->rconn_lock);

	skygw_log_write_flush(LOGFILE_ERROR,
			      "Error : Failed to publish message to MQRabbit server: "
			      "%s",amqp_error_string2(err_code));
	
      } 

    }

  }
  /** Pass the query downstream */
  return my_session->down.routeQuery(my_session->down.instance,
				     my_session->down.session, queue);
}