Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

405 lines
10 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Database.cpp
  5. Abstract:
  6. This file contains the implementation of the JetBlue::Database class.
  7. Revision History:
  8. Davide Massarenti (Dmassare) 05/17/2000
  9. created
  10. ******************************************************************************/
  11. #include <stdafx.h>
  12. #include <strsafe.h>
  13. ////////////////////////////////////////////////////////////////////////////////
  14. JetBlue::Database::Database( /*[in]*/ Session* parent ,
  15. /*[in]*/ JET_SESID sesid ,
  16. /*[in]*/ LPCSTR szName )
  17. {
  18. m_parent = parent; // Session* m_parent;
  19. m_sesid = sesid; // JET_SESID m_sesid;
  20. m_dbid = JET_dbidNil; // JET_DBID m_dbid;
  21. m_strName = szName; // MPC::string m_strName;
  22. // TableMap m_mapTables;
  23. }
  24. JetBlue::Database::~Database()
  25. {
  26. (void)Close( true );
  27. }
  28. ////////////////////////////////////////
  29. HRESULT JetBlue::Database::Refresh()
  30. {
  31. __HCP_FUNC_ENTRY( "JetBlue::Database::Refresh" );
  32. HRESULT hr;
  33. JET_OBJECTLIST info; ::ZeroMemory( &info, sizeof(info) ); info.cbStruct = sizeof(info); info.tableid = JET_tableidNil;
  34. Table* tblNew = NULL;
  35. m_mapTables.clear();
  36. if(m_dbid != JET_dbidNil)
  37. {
  38. ////////////////////////////////////////////////////////////////////////////////
  39. //
  40. // Read table definition.
  41. //
  42. // JET_OBJECTLIST
  43. // {
  44. // unsigned long cbStruct;
  45. // JET_TABLEID tableid;
  46. // unsigned long cRecord;
  47. // JET_COLUMNID columnidcontainername;
  48. // JET_COLUMNID columnidobjectname;
  49. // JET_COLUMNID columnidobjtyp;
  50. // JET_COLUMNID columniddtCreate; // XXX -- to be deleted
  51. // JET_COLUMNID columniddtUpdate; // XXX -- to be deleted
  52. // JET_COLUMNID columnidgrbit;
  53. // JET_COLUMNID columnidflags;
  54. // JET_COLUMNID columnidcRecord; /* Level 2 info */
  55. // JET_COLUMNID columnidcPage; /* Level 2 info */
  56. // };
  57. //
  58. // JET_RETRIEVECOLUMN
  59. // {
  60. // JET_COLUMNID columnid;
  61. // void *pvData;
  62. // unsigned long cbData;
  63. // unsigned long cbActual;
  64. // JET_GRBIT grbit;
  65. // unsigned long ibLongValue;
  66. // unsigned long itagSequence;
  67. // JET_COLUMNID columnidNextTagged;
  68. // JET_ERR err;
  69. // };
  70. JET_RETRIEVECOLUMN rc [1 ]; ::ZeroMemory( &rc, sizeof(rc) );
  71. char tblName[JET_cbNameMost+1];
  72. int i;
  73. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetGetObjectInfo( m_sesid, m_dbid, JET_objtypTable, NULL, NULL, &info, sizeof(info), JET_ObjInfoList ));
  74. __MPC_JET_INIT_RETRIEVE_COL( rc, 0, info.columnidobjectname, tblName, JET_cbNameMost );
  75. for(i=0; i<info.cRecord; i++)
  76. {
  77. ::ZeroMemory( tblName, sizeof(tblName) );
  78. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetMove ( m_sesid, info.tableid, (i == 0 ? JET_MoveFirst : JET_MoveNext), 0 ));
  79. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetRetrieveColumns( m_sesid, info.tableid, rc, ARRAYSIZE(rc) ));
  80. __MPC_EXIT_IF_ALLOC_FAILS(hr, tblNew, new Table( m_sesid, m_dbid, tblName ));
  81. m_mapTables[tblName] = tblNew; tblNew = NULL;
  82. }
  83. }
  84. hr = S_OK;
  85. __HCP_FUNC_CLEANUP;
  86. if(info.tableid != JET_tableidNil)
  87. {
  88. __MPC_JET__MTSAFE_NORESULT(m_sesid, ::JetCloseTable( m_sesid, info.tableid ));
  89. }
  90. if(tblNew) delete tblNew;
  91. __HCP_FUNC_EXIT(hr);
  92. }
  93. HRESULT JetBlue::Database::Open( /*[in]*/ bool fReadOnly ,
  94. /*[in]*/ bool fCreate ,
  95. /*[in]*/ bool fRepair )
  96. {
  97. __HCP_FUNC_ENTRY( "JetBlue::Database::Open" );
  98. HRESULT hr;
  99. JET_ERR err;
  100. JET_GRBIT grbit = fReadOnly ? JET_bitDbReadOnly : 0;
  101. bool fLocked = false;
  102. //
  103. // In case we cannot lock the database, we try to release it and relock it.
  104. //
  105. if(m_parent->LockDatabase( m_strName, fReadOnly ) == false)
  106. {
  107. __MPC_EXIT_IF_METHOD_FAILS(hr, Close());
  108. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->ReleaseDatabase( m_strName ));
  109. if(m_parent->LockDatabase( m_strName, fReadOnly ) == false)
  110. {
  111. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BUSY);
  112. }
  113. }
  114. fLocked = true;
  115. if(m_dbid == JET_dbidNil)
  116. {
  117. err = ::JetAttachDatabase( m_sesid, m_strName.c_str(), grbit );
  118. if(err < JET_errSuccess)
  119. {
  120. if(err == JET_errDatabaseCorrupted && fRepair)
  121. {
  122. __MPC_EXIT_IF_METHOD_FAILS(hr, Repair());
  123. err = ::JetAttachDatabase( m_sesid, m_strName.c_str(), grbit );
  124. }
  125. if(err == JET_errDatabaseCorrupted || fCreate == false)
  126. {
  127. __MPC_EXIT_IF_JET_FAILS(hr, err);
  128. }
  129. __MPC_EXIT_IF_JET_FAILS(hr, ::JetCreateDatabase( m_sesid, m_strName.c_str(), NULL, &m_dbid, 0 ));
  130. }
  131. else
  132. {
  133. __MPC_EXIT_IF_JET_FAILS(hr, ::JetOpenDatabase( m_sesid, m_strName.c_str(), NULL, &m_dbid, 0 ));
  134. }
  135. __MPC_EXIT_IF_METHOD_FAILS(hr, Refresh());
  136. }
  137. hr = S_OK;
  138. __HCP_FUNC_CLEANUP;
  139. if(FAILED(hr) && fLocked)
  140. {
  141. m_parent->UnlockDatabase( m_strName );
  142. }
  143. __HCP_FUNC_EXIT(hr);
  144. }
  145. HRESULT JetBlue::Database::Close( /*[in]*/ bool fForce, /*[in]*/ bool fAll )
  146. {
  147. __HCP_FUNC_ENTRY( "JetBlue::Database::Close" );
  148. HRESULT hr;
  149. JET_ERR err;
  150. TableIter it;
  151. for(it = m_mapTables.begin(); it != m_mapTables.end(); it++)
  152. {
  153. Table* tbl = it->second;
  154. if(tbl)
  155. {
  156. HRESULT hr2 = tbl->Close( fForce ); if(!fForce) __MPC_EXIT_IF_METHOD_FAILS(hr, hr2);
  157. delete tbl;
  158. }
  159. }
  160. m_mapTables.clear();
  161. if(fAll && m_dbid != JET_dbidNil)
  162. {
  163. err = ::JetCloseDatabase( m_sesid, m_dbid, 0 ); if(!fForce) __MPC_EXIT_IF_JET_FAILS(hr, err);
  164. m_dbid = JET_dbidNil;
  165. m_parent->UnlockDatabase( m_strName );
  166. }
  167. hr = S_OK;
  168. __HCP_FUNC_CLEANUP;
  169. __HCP_FUNC_EXIT(hr);
  170. }
  171. HRESULT JetBlue::Database::Delete( /*[in]*/ bool fForce )
  172. {
  173. __HCP_FUNC_ENTRY( "JetBlue::Database::Delete" );
  174. USES_CONVERSION;
  175. HRESULT hr;
  176. __MPC_EXIT_IF_METHOD_FAILS(hr, Close( fForce ));
  177. if(m_strName.length() > 0)
  178. {
  179. MPC::FileSystemObject fso( A2W( m_strName.c_str() ) );
  180. __MPC_EXIT_IF_METHOD_FAILS(hr, fso.Delete( fForce ));
  181. }
  182. hr = S_OK;
  183. __HCP_FUNC_CLEANUP;
  184. __HCP_FUNC_EXIT(hr);
  185. }
  186. ////////////////////////////////////////
  187. HRESULT JetBlue::Database::GetTable( /*[in] */ LPCSTR szName ,
  188. /*[out]*/ Table*& tbl ,
  189. /*[in] */ JET_TABLECREATE* pDef )
  190. {
  191. __HCP_FUNC_ENTRY( "JetBlue::Database::GetTable" );
  192. HRESULT hr;
  193. HRESULT hr2;
  194. Table* tblNew = NULL;
  195. TableIter it;
  196. __MPC_JET_CHECKHANDLE(hr,m_sesid,JET_sesidNil );
  197. if(pDef) szName = pDef->szTableName;
  198. it = m_mapTables.find( szName );
  199. if(it == m_mapTables.end())
  200. {
  201. __MPC_EXIT_IF_ALLOC_FAILS(hr, tblNew, new Table( m_sesid, m_dbid, szName ));
  202. m_mapTables[szName] = tblNew;
  203. tbl = tblNew; tblNew = NULL;
  204. }
  205. else
  206. {
  207. tbl = it->second;
  208. }
  209. if(FAILED(hr2 = tbl->Open()))
  210. {
  211. if(pDef == NULL || hr2 != JetERRToHRESULT( JET_errObjectNotFound ))
  212. {
  213. __MPC_SET_ERROR_AND_EXIT(hr, hr2);
  214. }
  215. if(pDef == (JET_TABLECREATE*)-1)
  216. {
  217. __MPC_EXIT_IF_METHOD_FAILS(hr, tbl->Create());
  218. }
  219. else
  220. {
  221. __MPC_EXIT_IF_METHOD_FAILS(hr, tbl->Create( pDef ));
  222. }
  223. }
  224. hr = S_OK;
  225. __HCP_FUNC_CLEANUP;
  226. if(tblNew) delete tblNew;
  227. __HCP_FUNC_EXIT(hr);
  228. }
  229. HRESULT JetBlue::Database::Compact()
  230. {
  231. __HCP_FUNC_ENTRY( "JetBlue::Database::Compact" );
  232. HRESULT hr;
  233. JET_DBUTIL util;
  234. CHAR rgTempDB[MAX_PATH];
  235. ::ZeroMemory( &util, sizeof(util) );
  236. util.cbStruct = sizeof(util);
  237. util.sesid = m_sesid;
  238. util.op = opDBUTILDBDefragment;
  239. util.szDatabase = (LPSTR)m_strName.c_str();
  240. util.szTable = rgTempDB;
  241. StringCbPrintfA( rgTempDB, sizeof(rgTempDB), "%s.temp", util.szDatabase );
  242. (void)::DeleteFileA( rgTempDB );
  243. __MPC_EXIT_IF_METHOD_FAILS(hr, Close());
  244. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetDBUtilities( &util ));
  245. __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::MoveFileExA( rgTempDB, util.szDatabase, MOVEFILE_REPLACE_EXISTING ));
  246. hr = S_OK;
  247. __HCP_FUNC_CLEANUP;
  248. (void)::DeleteFileA( rgTempDB );
  249. __HCP_FUNC_EXIT(hr);
  250. }
  251. HRESULT JetBlue::Database::Repair()
  252. {
  253. __HCP_FUNC_ENTRY( "JetBlue::Database::Repair" );
  254. HRESULT hr;
  255. JET_DBUTIL util;
  256. ::ZeroMemory( &util, sizeof(util) );
  257. util.cbStruct = sizeof(util);
  258. util.sesid = m_sesid;
  259. util.op = opDBUTILEDBRepair;
  260. util.szDatabase = (LPSTR)m_strName.c_str();
  261. __MPC_EXIT_IF_METHOD_FAILS(hr, Close());
  262. __MPC_EXIT_IF_JET_FAILS__MTSAFE(m_sesid, hr, ::JetDBUtilities( &util ));
  263. hr = S_OK;
  264. __HCP_FUNC_CLEANUP;
  265. __HCP_FUNC_EXIT(hr);
  266. }
  267. ////////////////////////////////////////
  268. JetBlue::Table* JetBlue::Database::GetTbl( /*[in]*/ int iPos )
  269. {
  270. for(TableIter it = m_mapTables.begin(); it != m_mapTables.end(); it++)
  271. {
  272. if(iPos-- == 0) return it->second;
  273. }
  274. return NULL;
  275. }
  276. JetBlue::Table* JetBlue::Database::GetTbl( LPCSTR szTbl )
  277. {
  278. TableIter it = m_mapTables.find( szTbl );
  279. return (it == m_mapTables.end()) ? NULL : it->second;
  280. }