source: MML/trunk/applications/database/mym/mym.h @ 4

Last change on this file since 4 was 4, checked in by zhangj, 11 years ago

Initial import--MML version from SOLEIL@2013

File size: 10.0 KB
Line 
1/*  mYm is a Matlab interface to MySQL server that support BLOB object
2*   Copyright (C) 2005 Swiss Federal Institute of technology (EPFL), Lausanne, CH
3*
4*   This program is free software; you can redistribute it and/or modify
5*   it under the terms of the GNU General Public License as published by
6*   the Free Software Foundation; either version 2 of the License, or
7*   at your option) any later version.
8*
9*   This program is distributed in the hope that it will be useful,
10*   but WITHOUT ANY WARRANTY; without even the implied warranty of
11*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*   GNU General Public License for more details.
13*
14*   You should have received a copy of the GNU General Public License
15*   along with this program; if not, write to the Free Software
16*   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
17*
18*   Author:                     Yannick Maret
19*   e-mail:                     yannick.maret@a3.epfl.ch
20*   old fashioned paper mail:   EPFL-STI-ITS-LTS1
21*                               Yannick MARET
22*                               ELD241
23*                               Station 11
24*                               CH-1015 Lausanne
25*
26*   Notice: some parts of this code (server connection, fancy print) is based 
27*   on an original code by Robert Almgren (http://www.mmf.utoronto.ca/resrchres/mysql/).
28*   The present code is under GPL license with the express agreement of Mr. Almgren.
29*/
30
31#ifndef MY_MAT_H
32#define MY_MAT H
33
34// some local defintion
35#ifndef ulong
36typedef unsigned long ulong;
37#endif
38#ifndef uchar
39typedef unsigned char uchar;
40#endif
41
42#include <mex.h>  //  Definitions for Matlab API
43
44#define ZLIB_WINAPI
45#include <zlib.h>
46
47#include <math.h>
48
49const bool debug = false;  //  turn on information messages
50
51#if (defined(_WIN32)||defined(_WIN64))&&!defined(__WIN__)
52#include <windows.h>
53#include <winsock.h> // to overcome a bug in mysql.h
54/* We use case-insensitive string comparison functions strcasecmp(), strncasecmp().
55   These are a BSD addition and are also defined on Linux, but not on every OS,
56   in particular Windows. The two "inline" declarations below fix this problem. If
57   you get errors on other platforms, move the declarations outside the WIN32 block */
58inline int strcasecmp(const char *s1, const char *s2) { return strcmp(s1, s2); }
59inline int strncasecmp(const char *s1, const char *s2, size_t n) { return strncmp(s1, s2, n); }
60#endif
61#include <mysql.h>  //  Definitions for MySQL client API
62
63// DLL entry point
64void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]);
65/*************** serializing functions ***************/
66// matlab objects
67char* serializeArray(unsigned long &rnBytes, const mxArray* rpArray, const char* rpArg, const bool);
68char* serializeStruct(unsigned long &rnBytes, const mxArray* rpArray, const char* rpArg, const bool);
69char* serializeCell(unsigned long &rnBytes, const mxArray* rpArray, const char* rpArg, const bool);
70char* serializeScalar(unsigned long &rnBytes, const mxArray* rpArray, const char* rpArg, const bool);
71char* serializeString(unsigned long &rnBytes, const mxArray* rpArray, const char* rpArg, const bool);
72// generic object
73char* serializeBinary(unsigned long &rnBytes, const mxArray* rpArray, const char* rpArg, const bool);
74char* serializeFile(unsigned long &rnBytes, const mxArray* rpArray, const char* rpArg, const bool);
75// deserilaizing functions
76mxArray* deserialize(const char* rpSerial, const unsigned long rlength);
77mxArray* deserializeArray(const char* rpSerial, const unsigned long rlength);
78mxArray* deserializeStruct(const char* rpSerial, const unsigned long rlength);
79mxArray* deserializeCell(const char* rpSerial, const unsigned long rlength);
80// utility functioms
81int file_length(FILE *f); // get the size of a file in byte
82unsigned long min_mysql_escape(char* rpout, const char* rpin, const unsigned long nin);
83/**********************************************************************
84 *
85 * hostport(s):  Given a host name s, possibly containing a port number
86 *  separated by the port separation character (normally ':').
87 * Modify the input string by putting a null at the end of
88 * the host string, and return the integer of the port number.
89 * Return zero in most special cases and error cases.
90 * Modified string will not contain the port separation character.
91 * Examples:  s = "myhost:2515" modifies s to "myhost" and returns 2515.
92 *      s = "myhost"    leaves s unchanged and returns 0.
93 *
94 **********************************************************************/
95const char portsep = ':';   //  separates host name from port number
96static int hostport(char *s) {
97        //   Look for first portsep in s; return 0 if null or can't find
98        if (!s||!(s = strchr(s, portsep))) 
99    return 0;
100        //  If s points to portsep, then truncate and convert tail
101        *s += 0;
102        return atoi(s);   // Returns zero in most special cases
103}
104/*********************************************************************/
105//  Static variables that contain connection state
106/*
107 *  isopen gets set to true when we execute an "open"
108 *  isopen gets set to false when either we execute a "close"
109 *            or when a ping or status fails
110 *   We do not set it to false when a normal query fails;
111 *   this might be due to the server having died, but is much
112 *   more likely to be caused by an incorrect query.
113 */
114class conninfo {
115public:
116        MYSQL *conn;   //  MySQL connection information structure
117        bool isopen;   //  whether we believe that connection is open
118        conninfo() { 
119    conn = NULL; 
120    isopen = false; 
121  }
122};
123const int MAXCONN = 20;
124static conninfo c[MAXCONN];   //  preserve state for MAXCONN different connections
125// for GPL license
126static bool runonce = false;
127/*********************************************************************/
128const char ID_MATLAB[] = "mYm";
129const size_t LEN_ID_MATLAB = strlen(ID_MATLAB);
130const char ID_ARRAY   = 'A';
131const char ID_CELL    = 'C';
132const char ID_STRUCT  = 'S';
133// Placeholder related constants
134const char PH_OPEN[]   = "{";  // placeholder openning symbols                                         
135const char PH_CLOSE[]  = "}";  // placeholder closing symbols                                   
136const char PH_BINARY   = 'B';
137const char PH_FILE     = 'F';
138const char PH_MATLAB   = 'M';
139const char PH_STRING   = 'S';
140// Preamble argument
141const char PRE_NO_COMPRESSION = 'u';
142// Compression
143const ulong MIN_LEN_ZLIB = 1000;        // minimum number of byte for trying compressiom
144const float MIN_CMP_RATE_ZLIB = 1.1f;   // minimum compression ratio
145const char ZLIB_ID[] = "ZL123";
146const size_t LEN_ZLIB_ID = strlen(ZLIB_ID);
147typedef char* (*pfserial)(unsigned long&, const mxArray*, const char*, const bool);
148
149static void getSerialFct(const char* rpt, const mxArray* rparg, pfserial& rpf, bool& rpec) {
150        const unsigned n_dims = mxGetNumberOfDimensions(rparg);
151        const int* p_dim = mxGetDimensions(rparg);
152  bool no_compression = false;
153  const char* pt = rpt;
154  // first check for preamble
155  if (*pt==PRE_NO_COMPRESSION) {
156    no_compression = true;
157    pt++;
158  }
159  if (*pt==PH_MATLAB) {
160    // this placeholder results in a serialized version of array, cell or structure
161    rpec = true;
162    if (mxIsNumeric(rparg)||mxIsChar(rparg))
163      rpf = &serializeArray;
164    else if (mxIsCell(rparg))
165      rpf = &serializeCell;
166    else if (mxIsStruct(rparg))
167      rpf = &serializeStruct;
168    else
169      mexErrMsgTxt("Matlab placeholder only support array, structure, or cell");
170  }
171  else if (*pt==PH_BINARY||*pt==PH_FILE) {
172    // this placeholder results in a binary dump of the corresponding data
173    rpec = true;
174    if (*pt==PH_BINARY)
175      if (n_dims!=2||!(p_dim[0]==1||p_dim[1]==1)||!mxIsUint8(rparg))
176                                mexErrMsgTxt("Binary placeholders only accept UINT8 1-by-M or M-by-1 arrays!");
177      else
178        rpf = &serializeBinary;
179    else
180      if (n_dims!=2||!(p_dim[0]==1||p_dim[1]==1)||!mxIsChar(rparg))
181        mexErrMsgTxt("String placeholders only accept CHAR 1-by-M or M-by-1 arrays!");
182      else
183        rpf = &serializeFile;
184  }
185  else if (*pt==PH_STRING) {
186    // this placeholder results in a text version of the data
187    rpec = false;
188    rpf = &serializeString;
189  }
190  else
191    mexErrMsgTxt("Unknow placeholders!");
192  if (no_compression)
193    rpec = false;
194}
195// entry point
196mxArray* deserialize(const char* rpSerial, const unsigned long rlength) {
197        mxArray* p_res = NULL;
198        bool could_not_deserialize = true;
199  bool used_compression = false;
200  char* p_cmp = NULL;
201  const char* p_serial = rpSerial;
202  unsigned long length = rlength;
203  if (p_serial==0) {
204                // the row is empty: return an empty array
205                p_res = mxCreateNumericArray(0, 0, mxCHAR_CLASS, mxREAL);
206    return p_res;
207  }
208  if (strcmp(p_serial, ZLIB_ID)==0) {
209    p_serial = p_serial+LEN_ZLIB_ID+1;
210    // read the length in bytes
211    ulong len;
212    memcpy((char*)&len, p_serial, sizeof(ulong));
213    p_serial = p_serial+sizeof(ulong);
214    char* p_cmp = (char*)mxCalloc(len, sizeof(char));
215    try {
216      int res = uncompress((Bytef*)p_cmp, &len, (const Bytef*)p_serial, length);
217      if (res==Z_OK) {
218        used_compression = true;
219        p_serial = p_cmp;
220        length = len;
221      }
222      else
223        p_serial = rpSerial;
224    }
225    catch(...) {
226      p_serial = rpSerial;
227    }
228  }
229  if (strcmp(p_serial, ID_MATLAB)==0) {
230    p_serial = p_serial+LEN_ID_MATLAB+1;
231    try {
232      could_not_deserialize = false;
233      if (*p_serial==ID_ARRAY)
234                          // the blob contains an array
235                          p_res = deserializeArray(p_serial+1, length);
236      else if (*p_serial==ID_STRUCT)
237        // the blob contains a struct
238        p_res = deserializeStruct(p_serial+1, length);
239      else if (*p_serial==ID_CELL)
240        // the blob contains a struct
241        p_res = deserializeCell(p_serial+1, length);
242      else
243        // the blob contains an unknow object
244        could_not_deserialize = true;
245    }
246    catch(...) {
247      could_not_deserialize = true;
248      p_serial = rpSerial;
249    }
250  }
251        if (could_not_deserialize) {
252                // we don't know what to do with the stuff in the database
253                // we return a memory dump in UINT8 format
254                int p_dim[2] = {length, 1};
255                p_res = mxCreateNumericArray(2, p_dim, mxUINT8_CLASS, mxREAL);
256                memcpy((char*)mxGetData(p_res), p_serial, length);
257        }
258  if (used_compression)
259    mxFree(p_cmp);
260        return p_res;
261}
262#endif // MY_MAT_H
Note: See TracBrowser for help on using the repository browser.