Example #1
0
GWBUF *gwbuf_clone_portion(
    GWBUF *buf,
    size_t start_offset,
    size_t length)
{
    GWBUF* clonebuf;

    CHK_GWBUF(buf);
    ss_dassert(start_offset+length <= GWBUF_LENGTH(buf));

    if ((clonebuf = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
    {
        ss_dassert(clonebuf != NULL);
        LOGIF(LE, (skygw_log_write_flush(
                       LOGFILE_ERROR,
                       "Error : Memory allocation failed due to %s.",
                       strerror(errno))));
        return NULL;
    }
    atomic_add(&buf->sbuf->refcount, 1);
    clonebuf->sbuf = buf->sbuf;
    clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone info bits too */
    clonebuf->start = (void *)((char*)buf->start+start_offset);
    clonebuf->end = (void *)((char *)clonebuf->start+length);
    clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone the type for now */
    clonebuf->properties = NULL;
    clonebuf->hint = NULL;
    clonebuf->gwbuf_info = buf->gwbuf_info;
    clonebuf->gwbuf_bufobj = buf->gwbuf_bufobj;
    clonebuf->next = NULL;
    clonebuf->tail = clonebuf;
    CHK_GWBUF(clonebuf);
    return clonebuf;

}
Example #2
0
/**
 * Trim bytes from the end of a GWBUF structure that may be the first
 * in a list. If the buffer has n_bytes or less then it will be freed and
 * the next buffer in the list will be returned, or if none, NULL.
 *
 * @param head		The buffer to trim
 * @param n_bytes	The number of bytes to trim off
 * @return 		The buffer chain or NULL if buffer chain now empty
 */
GWBUF *
gwbuf_rtrim(GWBUF *head, unsigned int n_bytes)
{
    GWBUF *rval = head;
    CHK_GWBUF(head);
    GWBUF_RTRIM(head, n_bytes);
    CHK_GWBUF(head);

    if (GWBUF_EMPTY(head))
    {
        rval = head->next;
        gwbuf_free(head);
    }
    return rval;
}
Example #3
0
/**
 * Consume data from a buffer in the linked list. The assumption is to consume
 * n bytes from the buffer chain.
 *
 * If after consuming the bytes from the first buffer that buffer becomes
 * empty it will be freed and the linked list updated.
 *
 * The return value is the new head of the linked list.
 *
 * This call should be made with the caller holding the lock for the linked
 * list.
 *
 * @param head		The head of the linked list
 * @param length	The amount of data to consume
 * @return The head of the linked list
 */
GWBUF *
gwbuf_consume(GWBUF *head, unsigned int length)
{
GWBUF *rval = head;
        CHK_GWBUF(head);
	GWBUF_CONSUME(head, length);
        CHK_GWBUF(head);
        
	if (GWBUF_EMPTY(head))
	{
		rval = head->next;
		gwbuf_free(head);
	}
	return rval;
}
Example #4
0
/**
 * Increment the usage count of a gateway buffer. This gets a new
 * GWBUF structure that shares the actual data with the existing
 * GWBUF structure but allows for the data copy to be avoided and
 * also for each GWBUF to point to different portions of the same
 * SHARED_BUF.
 *
 * @param buf The buffer to use
 * @return A new GWBUF structure
 */
GWBUF *
gwbuf_clone(GWBUF *buf)
{
    GWBUF	*rval;

    if ((rval = (GWBUF *)calloc(1,sizeof(GWBUF))) == NULL)
    {
        ss_dassert(rval != NULL);
        LOGIF(LE, (skygw_log_write_flush(
                       LOGFILE_ERROR,
                       "Error : Memory allocation failed due to %s.",
                       strerror(errno))));
        return NULL;
    }

    atomic_add(&buf->sbuf->refcount, 1);
    rval->sbuf = buf->sbuf;
    rval->start = buf->start;
    rval->end = buf->end;
    rval->gwbuf_type = buf->gwbuf_type;
    rval->gwbuf_info = buf->gwbuf_info;
    rval->gwbuf_bufobj = buf->gwbuf_bufobj;
    rval->tail = rval;
    CHK_GWBUF(rval);
    return rval;
}
Example #5
0
/**
 * Append a buffer onto a linked list of buffer structures.
 *
 * This call should be made with the caller holding the lock for the linked
 * list.
 *
 * @param head	The current head of the linked list
 * @param tail	The new buffer to make the tail of the linked list
 * @return	The new head of the linked list
 */
GWBUF	*
gwbuf_append(GWBUF *head, GWBUF *tail)
{
GWBUF	*ptr = head;
        
	if (!head)
		return tail;
        CHK_GWBUF(head);
        CHK_GWBUF(tail);
	while (ptr->next)
	{
		ptr = ptr->next;
	}
	ptr->next = tail;
	return head;
}
Example #6
0
/**
 * Free a gateway buffer
 *
 * @param buf The buffer to free
 */
void
gwbuf_free(GWBUF *buf)
{
	CHK_GWBUF(buf);
	if (atomic_add(&buf->sbuf->refcount, -1) == 1)
	{
                free(buf->sbuf->data);
                free(buf->sbuf);
	}
	free(buf);
}
Example #7
0
/**
 * Append a buffer onto a linked list of buffer structures.
 *
 * This call should be made with the caller holding the lock for the linked
 * list.
 *
 * @param head	The current head of the linked list
 * @param tail	The new buffer to make the tail of the linked list
 * @return	The new head of the linked list
 */
GWBUF	*
gwbuf_append(GWBUF *head, GWBUF *tail)
{
    if (!head)
        return tail;
    CHK_GWBUF(head);
    head->tail->next = tail;
    head->tail = tail->tail;

    return head;
}
Example #8
0
/**
 * Consume data from a buffer in the linked list. The assumption is to consume
 * n bytes from the buffer chain.
 *
 * If after consuming the bytes from the first buffer that buffer becomes
 * empty it will be freed and the linked list updated.
 *
 * The return value is the new head of the linked list.
 *
 * This call should be made with the caller holding the lock for the linked
 * list.
 *
 * @param head		The head of the linked list
 * @param length	The amount of data to consume
 * @return The head of the linked list
 */
GWBUF *
gwbuf_consume(GWBUF *head, unsigned int length)
{
    GWBUF *rval = head;

    CHK_GWBUF(head);
    GWBUF_CONSUME(head, length);
    CHK_GWBUF(head);

    if (GWBUF_EMPTY(head))
    {
        rval = head->next;
        if (head->next)
            head->next->tail = head->tail;

        gwbuf_free(head);
    }

    ss_dassert(rval == NULL || (rval->end > rval->start));
    return rval;
}
Example #9
0
/**
 * Set given type to all buffers on the list.
 * *
 * @param buf           The shared buffer
 * @param type          Type to be added
 */
void gwbuf_set_type(
    GWBUF*       buf,
    gwbuf_type_t type)
{
    /** Set type consistenly to all buffers on the list */
    while (buf != NULL)
    {
        CHK_GWBUF(buf);
        buf->gwbuf_type |= type;
        buf=buf->next;
    }
}
Example #10
0
/**
 * Return the number of bytes of data in the linked list.
 *
 * @param head	The current head of the linked list
 * @return The number of bytes of data in the linked list
 */
unsigned int
gwbuf_length(GWBUF *head)
{
int	rval = 0;
        CHK_GWBUF(head);
	while (head)
	{
		rval += GWBUF_LENGTH(head);
		head = head->next;
	}
	return rval;
}
Example #11
0
/**
 * Allocate a new gateway buffer structure of size bytes.
 *
 * For now we allocate memory directly from malloc for buffer the management
 * structure and the actual data buffer itself. We may swap at a future date
 * to a more effecient mechanism.
 *
 * @param	size The size in bytes of the data area required
 * @return	Pointer to the buffer structure or NULL if memory could not
 *		be allocated.
 */
GWBUF	*
gwbuf_alloc(unsigned int size)
{
    GWBUF		*rval;
    SHARED_BUF	*sbuf;

    /* Allocate the buffer header */
    if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
    {
        goto retblock;;
    }

    /* Allocate the shared data buffer */
    if ((sbuf = (SHARED_BUF *)malloc(sizeof(SHARED_BUF))) == NULL)
    {
        free(rval);
        rval = NULL;
        goto retblock;
    }

    /* Allocate the space for the actual data */
    if ((sbuf->data = (unsigned char *)malloc(size)) == NULL)
    {
        ss_dassert(sbuf->data != NULL);
        free(rval);
        free(sbuf);
        rval = NULL;
        goto retblock;
    }
    spinlock_init(&rval->gwbuf_lock);
    rval->start = sbuf->data;
    rval->end = (void *)((char *)rval->start+size);
    sbuf->refcount = 1;
    rval->sbuf = sbuf;
    rval->next = NULL;
    rval->tail = rval;
    rval->hint = NULL;
    rval->properties = NULL;
    rval->gwbuf_type = GWBUF_TYPE_UNDEFINED;
    rval->gwbuf_info = GWBUF_INFO_NONE;
    rval->gwbuf_bufobj = NULL;
    CHK_GWBUF(rval);
retblock:
    if (rval == NULL)
    {
        LOGIF(LE, (skygw_log_write_flush(
                       LOGFILE_ERROR,
                       "Error : Memory allocation failed due to %s.",
                       strerror(errno))));
    }
    return rval;
}
Example #12
0
GWBUF *gwbuf_clone_portion(
        GWBUF *buf,
        size_t start_offset,
        size_t length)
{
        GWBUF* clonebuf;
        
        CHK_GWBUF(buf);
        ss_dassert(start_offset+length <= GWBUF_LENGTH(buf));
        
        if ((clonebuf = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
        {
                return NULL;
        }
        atomic_add(&buf->sbuf->refcount, 1);
        clonebuf->sbuf = buf->sbuf;
        clonebuf->start = (void *)((char*)buf->start)+start_offset;
        clonebuf->end = (void *)((char *)clonebuf->start)+length;
        clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone the type for now */ 
        clonebuf->next = NULL;
        CHK_GWBUF(clonebuf);
        return clonebuf;
        
}
Example #13
0
/**
 * Returns pointer to GWBUF of a requested type.
 * As of 10.3.14 only MySQL to plain text conversion is supported.
 * Return NULL if conversion between types is not supported or due lacking
 * type information.
 */
GWBUF *gwbuf_clone_transform(
        GWBUF *      head, 
        gwbuf_type_t targettype)
{
        gwbuf_type_t src_type;
        GWBUF*       clonebuf;
        
        CHK_GWBUF(head);
        src_type = head->gwbuf_type;
        
        if (targettype == GWBUF_TYPE_UNDEFINED ||
                src_type == GWBUF_TYPE_UNDEFINED ||
                src_type == GWBUF_TYPE_PLAINSQL ||
                targettype == src_type)
        {
                clonebuf = NULL;
                goto return_clonebuf;
        }

        switch (src_type)
        {
                case GWBUF_TYPE_MYSQL:
                        if (targettype == GWBUF_TYPE_PLAINSQL)
                        {
                                /** Crete reference to string part of buffer */
                                clonebuf = gwbuf_clone_portion(
                                                head, 
                                                5, 
                                                GWBUF_LENGTH(head)-5);                                
                                ss_dassert(clonebuf != NULL);
                                /** Overwrite the type with new format */
                                clonebuf->gwbuf_type = targettype;
                        }
                        else
                        {
                                clonebuf = NULL;
                        }
                        break;
                        
                default:
                        clonebuf = NULL;
                        break;                        
        } /*< switch (src_type) */
        
return_clonebuf:
        return clonebuf;
}
Example #14
0
/**
 * Returns pointer to GWBUF of a requested type.
 * As of 10.3.14 only MySQL to plain text conversion is supported.
 * Return NULL if conversion between types is not supported or due lacking
 * type information.
 */
GWBUF *gwbuf_clone_transform(
    GWBUF *      head,
    gwbuf_type_t targettype)
{
    gwbuf_type_t src_type;
    GWBUF*       clonebuf;

    CHK_GWBUF(head);
    src_type = head->gwbuf_type;

    if (targettype == GWBUF_TYPE_UNDEFINED ||
            src_type == GWBUF_TYPE_UNDEFINED ||
            src_type == GWBUF_TYPE_PLAINSQL ||
            targettype == src_type)
    {
        clonebuf = NULL;
        goto return_clonebuf;
    }

    if (GWBUF_IS_TYPE_MYSQL(head))
    {
        if (GWBUF_TYPE_PLAINSQL == targettype)
        {
            /** Crete reference to string part of buffer */
            clonebuf = gwbuf_clone_portion(
                           head,
                           5,
                           GWBUF_LENGTH(head)-5);
            ss_dassert(clonebuf != NULL);
            /** Overwrite the type with new format */
            gwbuf_set_type(clonebuf, targettype);
        }
        else
        {
            clonebuf = NULL;
        }
    }
    else
    {
        clonebuf = NULL;
    }

return_clonebuf:
    return clonebuf;
}
Example #15
0
/**
 * Increment the usage count of a gateway buffer. This gets a new
 * GWBUF structure that shares the actual data with the existing
 * GWBUF structure but allows for the data copy to be avoided and
 * also for each GWBUF to point to different portions of the same
 * SHARED_BUF.
 *
 * @param buf The buffer to use
 * @return A new GWBUF structure
 */
GWBUF *
gwbuf_clone(GWBUF *buf)
{
GWBUF	*rval;

	if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
	{
		return NULL;
	}

	atomic_add(&buf->sbuf->refcount, 1);
	rval->sbuf = buf->sbuf;
	rval->start = buf->start;
	rval->end = buf->end;
        rval->gwbuf_type = buf->gwbuf_type;
	rval->next = NULL;
        CHK_GWBUF(rval);
	return rval;
}
Example #16
0
/**
 * Remove the first mysql statement from buffer. Return pointer to the removed
 * statement or NULL if buffer is empty.
 * 
 * Clone buf, calculate the length of included mysql stmt, and point the 
 * statement with cloned buffer. Move the start pointer of buf accordingly
 * so that it only cover the remaining buffer.
 * 
 */
GWBUF* gw_MySQL_get_next_stmt(
        GWBUF** p_readbuf)
{
        GWBUF*         stmtbuf;
        size_t         buflen;
        size_t         strlen;
        uint8_t*       packet;
        
        if (*p_readbuf == NULL)
        {
                stmtbuf = NULL;
                goto return_stmtbuf;
        }                
        CHK_GWBUF(*p_readbuf);
        
        if (GWBUF_EMPTY(*p_readbuf))
        {
                stmtbuf = NULL;
                goto return_stmtbuf;
        }
        buflen = GWBUF_LENGTH((*p_readbuf));
        packet = GWBUF_DATA((*p_readbuf));
        strlen = MYSQL_GET_PACKET_LEN(packet);

        if (strlen+4 == buflen)
        {
                stmtbuf = *p_readbuf;
                *p_readbuf = NULL;
                goto return_stmtbuf;
        }
        /** vraa :Multi-packet stmt is not supported as of 7.3.14 */
        if (strlen-1 > buflen-5)
        {
                stmtbuf = NULL;
                goto return_stmtbuf;
        }
        stmtbuf = gwbuf_clone_portion(*p_readbuf, 0, strlen+4);
        *p_readbuf = gwbuf_consume(*p_readbuf, strlen+4);
        
return_stmtbuf:
        return stmtbuf;
}
Example #17
0
bool gwbuf_set_type(
        GWBUF*       buf,
        gwbuf_type_t type)
{
        bool succp;
        CHK_GWBUF(buf);
        
        switch (type) {
                case GWBUF_TYPE_MYSQL:
                case GWBUF_TYPE_PLAINSQL:
                case GWBUF_TYPE_UNDEFINED:
                        buf->gwbuf_type = type;
                        succp = true;
                        break;
                default:
                        succp = false;
                        break;
        }
        ss_dassert(succp);
        return succp;
}
Example #18
0
/**
 * Search buffer object which matches with the id.
 *
 * @param buf   GWBUF to be searched
 * @param id    Identifier for the object
 *
 * @return Searched buffer object or NULL if not found
 */
void* gwbuf_get_buffer_object_data(
    GWBUF*      buf,
    bufobj_id_t id)
{
    buffer_object_t* bo;

    CHK_GWBUF(buf);
    /** Lock */
    spinlock_acquire(&buf->gwbuf_lock);
    bo = buf->gwbuf_bufobj;

    while (bo != NULL && bo->bo_id != id)
    {
        bo = bo->bo_next;
    }
    /** Unlock */
    spinlock_release(&buf->gwbuf_lock);
    if(bo) {
        return bo->bo_data;
    }
    return NULL;
}
Example #19
0
/**
 * Add a buffer object to GWBUF buffer.
 *
 * @param buf           GWBUF where object is added
 * @param id            Type identifier for object
 * @param data          Object data
 * @param donefun_dp    Clean-up function to be executed before buffer is freed.
 */
void gwbuf_add_buffer_object(
    GWBUF* buf,
    bufobj_id_t id,
    void*  data,
    void (*donefun_fp)(void *))
{
    buffer_object_t** p_b;
    buffer_object_t*  newb;

    CHK_GWBUF(buf);
    newb = (buffer_object_t *)malloc(sizeof(buffer_object_t));
    ss_dassert(newb != NULL);

    if (newb == NULL)
    {
        LOGIF(LE, (skygw_log_write_flush(
                       LOGFILE_ERROR,
                       "Error : Memory allocation failed due to %s.",
                       strerror(errno))));
        return;
    }
    newb->bo_id = id;
    newb->bo_data = data;
    newb->bo_donefun_fp = donefun_fp;
    newb->bo_next = NULL;
    /** Lock */
    spinlock_acquire(&buf->gwbuf_lock);
    p_b = &buf->gwbuf_bufobj;
    /** Search the end of the list and add there */
    while (*p_b != NULL)
    {
        p_b = &(*p_b)->bo_next;
    }
    *p_b = newb;
    /** Set flag */
    buf->gwbuf_info |= GWBUF_INFO_PARSED;
    /** Unlock */
    spinlock_release(&buf->gwbuf_lock);
}
Example #20
0
/**
 * Free a gateway buffer
 *
 * @param buf The buffer to free
 */
void
gwbuf_free(GWBUF *buf)
{
    BUF_PROPERTY	*prop;

    buffer_object_t* bo;

    CHK_GWBUF(buf);
    if (atomic_add(&buf->sbuf->refcount, -1) == 1)
    {
        free(buf->sbuf->data);
        free(buf->sbuf);
        bo = buf->gwbuf_bufobj;

        while (bo != NULL)
        {
            bo = gwbuf_remove_buffer_object(buf, bo);
        }

    }
    while (buf->properties)
    {
        prop = buf->properties;
        buf->properties = prop->next;
        free(prop->name);
        free(prop->value);
        free(prop);
    }
    /** Release the hint */
    while (buf->hint)
    {
        HINT* h = buf->hint;
        buf->hint = buf->hint->next;
        hint_free(h);
    }
    free(buf);
}
Example #21
0
/**
 * Allocate a new gateway buffer structure of size bytes.
 *
 * For now we allocate memory directly from malloc for buffer the management
 * structure and the actual data buffer itself. We may swap at a future date
 * to a more effecient mechanism.
 *
 * @param	size The size in bytes of the data area required
 * @return	Pointer to the buffer structure or NULL if memory could not
 *		be allocated.
 */
GWBUF	*
gwbuf_alloc(unsigned int size)
{
GWBUF		*rval;
SHARED_BUF	*sbuf;

	// Allocate the buffer header
	if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
	{
		return NULL;
	}

	// Allocate the shared data buffer
	if ((sbuf = (SHARED_BUF *)malloc(sizeof(SHARED_BUF))) == NULL)
	{
		free(rval);
		return NULL;
	}

	// Allocate the space for the actual data
	if ((sbuf->data = (unsigned char *)malloc(size)) == NULL)
	{
		free(rval);
		free(sbuf);
		return NULL;
	}
	rval->start = sbuf->data;
	rval->end = rval->start + size;
	sbuf->refcount = 1;
	rval->sbuf = sbuf;
	rval->next = NULL;
        rval->gwbuf_type = GWBUF_TYPE_UNDEFINED;
	rval->command = 0;
        CHK_GWBUF(rval);
	return rval;
}