Drizzled Public API Documentation

command.cc
Go to the documentation of this file.
00001 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00002  *
00003  * Drizzle Client & Protocol Library
00004  *
00005  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are
00010  * met:
00011  *
00012  *     * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  *
00015  *     * Redistributions in binary form must reproduce the above
00016  * copyright notice, this list of conditions and the following disclaimer
00017  * in the documentation and/or other materials provided with the
00018  * distribution.
00019  *
00020  *     * The names of its contributors may not be used to endorse or
00021  * promote products derived from this software without specific prior
00022  * written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 
00044 #include <libdrizzle/common.h>
00045 
00046 /*
00047  * Private variables.
00048  */
00049 
00050 static drizzle_command_drizzle_t _command_drizzle_map[]=
00051 {
00052  DRIZZLE_COMMAND_DRIZZLE_END,
00053  DRIZZLE_COMMAND_DRIZZLE_QUIT,
00054  DRIZZLE_COMMAND_DRIZZLE_INIT_DB,
00055  DRIZZLE_COMMAND_DRIZZLE_QUERY,
00056  DRIZZLE_COMMAND_DRIZZLE_END,
00057  DRIZZLE_COMMAND_DRIZZLE_END,
00058  DRIZZLE_COMMAND_DRIZZLE_END,
00059  DRIZZLE_COMMAND_DRIZZLE_END,
00060  DRIZZLE_COMMAND_DRIZZLE_SHUTDOWN,
00061  DRIZZLE_COMMAND_DRIZZLE_END, // STATISTICS
00062  DRIZZLE_COMMAND_DRIZZLE_END, // PROCESS_INFO
00063  DRIZZLE_COMMAND_DRIZZLE_END, // CONNECT
00064  DRIZZLE_COMMAND_DRIZZLE_KILL,// PROCESS_KILL
00065  DRIZZLE_COMMAND_DRIZZLE_END,
00066  DRIZZLE_COMMAND_DRIZZLE_PING,
00067  DRIZZLE_COMMAND_DRIZZLE_END,
00068  DRIZZLE_COMMAND_DRIZZLE_END,
00069  DRIZZLE_COMMAND_DRIZZLE_END,
00070  DRIZZLE_COMMAND_DRIZZLE_END,
00071  DRIZZLE_COMMAND_DRIZZLE_END,
00072  DRIZZLE_COMMAND_DRIZZLE_END,
00073  DRIZZLE_COMMAND_DRIZZLE_END,
00074  DRIZZLE_COMMAND_DRIZZLE_END,
00075  DRIZZLE_COMMAND_DRIZZLE_END,
00076  DRIZZLE_COMMAND_DRIZZLE_END,
00077  DRIZZLE_COMMAND_DRIZZLE_END,
00078  DRIZZLE_COMMAND_DRIZZLE_END,
00079  DRIZZLE_COMMAND_DRIZZLE_END,
00080  DRIZZLE_COMMAND_DRIZZLE_END,
00081  DRIZZLE_COMMAND_DRIZZLE_END,
00082  DRIZZLE_COMMAND_DRIZZLE_END
00083 };
00084 
00085 /*
00086  * State Definitions
00087  */
00088 
00089 drizzle_return_t drizzle_state_command_read(drizzle_con_st *con)
00090 {
00091   if (con == NULL)
00092   {
00093     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00094   }
00095 
00096   drizzle_log_debug(con->drizzle, "drizzle_state_command_read");
00097 
00098   if (con->buffer_size == 0)
00099   {
00100     drizzle_state_push(con, drizzle_state_read);
00101     return DRIZZLE_RETURN_OK;
00102   }
00103 
00104   if (con->command_total == 0)
00105   {
00106     con->command= (drizzle_command_t)(con->buffer_ptr[0]);
00107     con->buffer_ptr++;
00108     con->buffer_size--;
00109 
00110     con->command_total= (con->packet_size - 1);
00111   }
00112 
00113   if (con->buffer_size < (con->command_total - con->command_offset))
00114   {
00115     con->command_size= con->buffer_size;
00116     con->command_offset+= con->command_size;
00117   }
00118   else
00119   {
00120     con->command_size= (con->command_total - con->command_offset);
00121     con->command_offset= con->command_total;
00122   }
00123 
00124   con->command_data= con->buffer_ptr;
00125   con->buffer_ptr+= con->command_size;
00126   con->buffer_size-= con->command_size;
00127 
00128   if (con->command_offset == con->command_total)
00129     drizzle_state_pop(con);
00130   else
00131     return DRIZZLE_RETURN_PAUSE;
00132 
00133   return DRIZZLE_RETURN_OK;
00134 }
00135 
00136 drizzle_return_t drizzle_state_command_write(drizzle_con_st *con)
00137 {
00138   uint8_t *start;
00139   uint8_t *ptr;
00140   size_t free_size;
00141   drizzle_return_t ret;
00142 
00143   if (con == NULL)
00144   {
00145     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00146   }
00147 
00148   drizzle_log_debug(con->drizzle, "drizzle_state_command_write");
00149 
00150   if (con->command_data == NULL && con->command_total != 0 &&
00151       con->command != DRIZZLE_COMMAND_CHANGE_USER)
00152   {
00153     return DRIZZLE_RETURN_PAUSE;
00154   }
00155 
00156   if (con->buffer_size == 0)
00157   {
00158     con->buffer_ptr= con->buffer;
00159     start= con->buffer;
00160   }
00161   else
00162   {
00163     start= con->buffer_ptr + con->buffer_size;
00164   }
00165 
00166   if (con->command_offset == 0)
00167   {
00168     /* Make sure we can fit the largest non-streaming packet, currently a
00169        DRIZZLE_COMMAND_CHANGE_USER command. */
00170 
00171     con->packet_size= 1  /* Command */
00172                     + strlen(con->user) + 1
00173                     + 1  /* Scramble size */
00174                     + DRIZZLE_MAX_SCRAMBLE_SIZE
00175                     + strlen(con->db) + 1;
00176 
00177     /* Flush buffer if there is not enough room. */
00178     free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
00179     if (free_size < con->packet_size)
00180     {
00181       drizzle_state_push(con, drizzle_state_write);
00182       return DRIZZLE_RETURN_OK;
00183     }
00184 
00185     /* Store packet size at the end since it may change. */
00186     con->packet_number= 1;
00187     ptr= start;
00188     ptr[3]= 0;
00189     if (con->options & DRIZZLE_CON_MYSQL)
00190     {
00191       ptr[4]= (uint8_t)(con->command);
00192     }
00193     else
00194     {
00195       ptr[4]= (uint8_t)(_command_drizzle_map[con->command]);
00196     }
00197     ptr+= 5;
00198 
00199     if (con->command == DRIZZLE_COMMAND_CHANGE_USER)
00200     {
00201       ptr= drizzle_pack_auth(con, ptr, &ret);
00202       if (ret != DRIZZLE_RETURN_OK)
00203         return ret;
00204 
00205       con->buffer_size+= (4 + con->packet_size);
00206     }
00207     else if (con->command_total == 0)
00208     {
00209       con->packet_size= 1;
00210       con->buffer_size+= 5;
00211     }
00212     else
00213     {
00214       con->packet_size= 1 + con->command_total;
00215       free_size-= 5;
00216 
00217       /* Copy as much of the data in as we can into the write buffer. */
00218       if (con->command_size <= free_size)
00219       {
00220         memcpy(ptr, con->command_data, con->command_size);
00221         con->command_offset= con->command_size;
00222         con->command_data= NULL;
00223         con->buffer_size+= 5 + con->command_size;
00224       }
00225       else
00226       {
00227         memcpy(ptr, con->command_data, free_size);
00228         con->command_offset= free_size;
00229         con->command_data+= free_size;
00230         con->command_size-= free_size;
00231         con->buffer_size+= 5 + free_size;
00232       }
00233     }
00234 
00235     /* Store packet size now. */
00236     drizzle_set_byte3(start, con->packet_size);
00237   }
00238   else
00239   {
00240     /* Write directly from the caller buffer for the rest. */
00241     con->buffer_ptr= con->command_data;
00242     con->buffer_size= con->command_size;
00243     con->command_offset+= con->command_size;
00244     con->command_data= NULL;
00245   }
00246 
00247   if (con->command_offset == con->command_total)
00248   {
00249     drizzle_state_pop(con);
00250 
00251     if (!(con->options & (DRIZZLE_CON_RAW_PACKET |
00252                           DRIZZLE_CON_NO_RESULT_READ)) &&
00253         con->command != DRIZZLE_COMMAND_FIELD_LIST)
00254     {
00255       drizzle_state_push(con, drizzle_state_result_read);
00256       drizzle_state_push(con, drizzle_state_packet_read);
00257     }
00258   }
00259 
00260   drizzle_state_push(con, drizzle_state_write);
00261 
00262   return DRIZZLE_RETURN_OK;
00263 }