1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
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 Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef MYSQL_WRAPPER_H
18 #define MYSQL_WRAPPER_H
20 #include "nel/misc/types_nl.h"
22 #include "nel/misc/debug.h"
23 #include "nel/misc/common.h"
24 #include "nel/misc/md5.h"
25 #include "nel/net/service.h"
26 #include "nel/net/module_common.h"
27 #include "game_share/utils.h"
29 # include <WinSock2.h>
31 typedef unsigned long ulong
;
34 typedef unsigned long ulong
;
40 #include "game_share/r2_basic_types.h" // for TSessionId
47 /// Utility function to encode a date
48 std::string
encodeDate(NLMISC::TTime date
);
50 /** escape string using 'mysql_real_escape_string' and return a the escaped string.
51 * Note that the function is internally optimized to quickly build the return string
52 * with very little overhead.
54 const std::string
&escapeString(const std::string
&str
, CConnection
&dbCnx
);
58 friend const std::string
&escapeString(const std::string
&str
, CConnection
&dbCnx
);
61 std::string _ConnHostName
;
62 std::string _ConnUserName
;
63 std::string _ConnPassword
;
64 std::string _ConnDefaultDatabase
;
68 /// The mysql connection context
71 /// Flag for connection open
74 typedef std::map
<mysql_option
, const char*> TOptions
;
75 /// A list of pair name/value of connection option
78 /// Internale connect method (this one do the job)
84 : _MysqlContext(NULL
),
92 mysql_close(_MysqlContext
);
95 void addOption(mysql_option option
, const char *value
);
96 void clearOption(mysql_option option
);
98 bool connect(const std::string
&hostName
, const std::string
&userName
, const std::string
&password
, const std::string
&defaultDatabase
, uint port
);
99 bool connect(const NLNET::TParsedCommandLine
&databaseInfo
);
103 bool query(const std::string
&queryString
);
105 uint32
getLastGeneratedId()
107 return uint32(mysql_insert_id(_MysqlContext
));
110 uint32
getAffectedRows()
112 return uint32(mysql_affected_rows(_MysqlContext
));
115 CUniquePtr
<CStoreResult
> storeResult();
116 CUniquePtr
<CUseResult
> useResult();
120 // base class contains method to extract info from a fetched row
124 MYSQL_ROW _CurrentRow
;
125 unsigned long *_FieldLength
;
130 CResultBase(MYSQL_RES
*result
)
141 mysql_free_result(_Result
);
145 /// return the number of fields in the result set
146 uint32
getNumFields()
148 return mysql_num_fields(_Result
);
151 const char *getRawField(uint32 fieldIndex
)
153 nlassert(_CurrentRow
!= NULL
);
154 nlassert(fieldIndex
< getNumFields());
156 static const char *emptyString
= "";
158 char *ret
= _CurrentRow
[fieldIndex
];
160 return ret
!= NULL
? ret
: emptyString
;
163 void getField(uint32 fieldIndex
, std::string
&value
)
165 value
= getRawField(fieldIndex
);
168 void getField(uint32 fieldIndex
, bool &value
)
170 const char *str
= getRawField(fieldIndex
);
173 else if (str
[0] == '0')
176 value
= NLMISC::nlstricmp(str
, "true") == 0;
178 void getField(uint32 fieldIndex
, uint8
&value
)
180 const char *str
= getRawField(fieldIndex
);
181 value
= uint8(strtoul(str
, NULL
, 10));
183 void getField(uint32 fieldIndex
, uint32
&value
)
185 const char *str
= getRawField(fieldIndex
);
186 value
= uint32(strtoul(str
, NULL
, 10));
188 void getField(uint32 fieldIndex
, sint8
&value
)
190 NLMISC::fromString(std::string(getRawField(fieldIndex
)), value
);
192 void getField(uint32 fieldIndex
, sint32
&value
)
194 NLMISC::fromString(std::string(getRawField(fieldIndex
)), value
);
197 void getField(uint32 fieldIndex
, TSessionId
&value
)
200 NLMISC::fromString(std::string(getRawField(fieldIndex
)), val
);
201 value
=TSessionId(val
);
204 void getField(uint32 fieldIndex
, std::vector
<uint8
> &value
)
206 const char *data
= getRawField(fieldIndex
);
207 long size
= _FieldLength
[fieldIndex
];
208 std::vector
<uint8
> vec(data
, data
+size
);
212 void getMD5Field(uint32 fieldIndex
, NLMISC::CHashKeyMD5
&hashKey
)
214 const char *data
= getRawField(fieldIndex
);
215 long size
= _FieldLength
[fieldIndex
];
217 hashKey
.fromString(data
);
220 void getDateField(uint32 fieldIndex
, uint32
&time
);
223 class CUseResult
: public CResultBase
225 friend class CConnection
;
227 CUseResult(MYSQL_RES
*result
)
228 : CResultBase(result
)
233 /// Advance to next row in the result set, return true is there is a row
236 _CurrentRow
= mysql_fetch_row(_Result
);
237 if (_CurrentRow
== NULL
)
239 _FieldLength
= mysql_fetch_lengths(_Result
);
240 nlassert(_FieldLength
!= NULL
);
246 class CStoreResult
: public CResultBase
248 friend class CConnection
;
251 CStoreResult(MYSQL_RES
*result
)
252 : CResultBase(result
)
259 /// Return the number of row in the result set
262 return uint32(mysql_num_rows(_Result
));
265 /// Advance to next row in the result set
268 _CurrentRow
= mysql_fetch_row(_Result
);
269 nlassert(_CurrentRow
!= NULL
);
270 _FieldLength
= mysql_fetch_lengths(_Result
);
271 nlassert(_FieldLength
!= NULL
);
279 //NeL simple Object Persistence Engine
284 /// This is a temporary allocated, not persisted object instance
286 /// This is a persistent object, unmodified since it was loaded
288 /// This is a persistent object, modified in transient space that need to be saved to db
290 /// This is removed object, it should no more be used as it have been removed from db
292 /// This is a persistent object, unmodified but that lie in the object cache.
295 // a tag counter MUST BE LAST
299 const uint32 INVALID_OBJECT_ID
= 0;
301 extern bool AllowedTransition
[os_nb_state
][os_nb_state
];
312 typedef uint32 (*TCacheCmdFunc
)(TCacheCmd cmd
);
315 class CPersistentCache
:
316 public NLNET::IServiceUpdatable
,
317 public NLMISC::ICommandsHandler
319 NLMISC_SAFE_SINGLETON_DECL(CPersistentCache
);
321 typedef std::set
<TCacheCmdFunc
> TUpdateFuncs
;
322 TUpdateFuncs _UpdateFuncs
;
326 NLMISC::CCommandRegistry::getInstance().registerNamedCommandHandler(this, "CPersistentCache");
328 // virtual const std::string &getCommandHandlerClassName() const
330 // static string name("CPersistentCache");
334 virtual const std::string
&getCommandHandlerName() const
336 static std::string
name("sqlObjectCache");
342 void registerCache(TCacheCmdFunc functionPtr
)
344 _UpdateFuncs
.insert(functionPtr
);
347 void serviceLoopUpdate()
349 H_AUTO(CPersistentCache_serviceLoopUpdate
);
351 TUpdateFuncs::iterator
first(_UpdateFuncs
.begin()), last(_UpdateFuncs
.end());
352 for (; first
!= last
; ++first
)
354 TCacheCmdFunc f
= *first
;
359 // delete any unreference object in the cache
362 TUpdateFuncs::iterator
first(_UpdateFuncs
.begin()), last(_UpdateFuncs
.end());
363 for (; first
!= last
; ++first
)
365 TCacheCmdFunc f
= *first
;
370 /// Return the grand total of instance in memory (including in use and in cache objects)
371 uint32
getInstanceCount()
374 TUpdateFuncs::iterator
first(_UpdateFuncs
.begin()), last(_UpdateFuncs
.end());
375 for (; first
!= last
; ++first
)
377 TCacheCmdFunc f
= *first
;
378 total
+= f(cc_instance_count
);
385 NLMISC_COMMAND_HANDLER_TABLE_BEGIN(CPersistentCache
)
386 NLMISC_COMMAND_HANDLER_ADD(CPersistentCache
, clearCache
, "remove any unreferenced cached object from memory", "no params")
387 NLMISC_COMMAND_HANDLER_ADD(CPersistentCache
, dump
, "dump cache status", "no params")
388 NLMISC_COMMAND_HANDLER_TABLE_END
390 NLMISC_CLASS_COMMAND_DECL(dump
)
392 log
.displayNL("Dumping SQL cache for %u class :", _UpdateFuncs
.size());
394 // redirect all logs to log
395 NLMISC::CNLSmartLogOverride
logRedirector(&log
);
396 TUpdateFuncs::iterator
first(_UpdateFuncs
.begin()), last(_UpdateFuncs
.end());
397 for (; first
!= last
; ++first
)
399 TCacheCmdFunc f
= *first
;
405 NLMISC_CLASS_COMMAND_DECL(clearCache
)
416 #endif // MYSQL_WRAPPER_H