llapr.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:16k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llapr.cpp
  3.  * @author Phoenix
  4.  * @date 2004-11-28
  5.  * @brief Helper functions for using the apache portable runtime library.
  6.  *
  7.  * $LicenseInfo:firstyear=2004&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2004-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #include "linden_common.h"
  35. #include "llapr.h"
  36. apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
  37. LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
  38. apr_thread_mutex_t *gLogMutexp = NULL;
  39. apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
  40. const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
  41. void ll_init_apr()
  42. {
  43. if (!gAPRPoolp)
  44. {
  45. // Initialize APR and create the global pool
  46. apr_initialize();
  47. apr_pool_create(&gAPRPoolp, NULL);
  48. // Initialize the logging mutex
  49. apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
  50. apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
  51. }
  52. if(!LLAPRFile::sAPRFilePoolp)
  53. {
  54. LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
  55. }
  56. }
  57. void ll_cleanup_apr()
  58. {
  59. LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
  60. if (gLogMutexp)
  61. {
  62. // Clean up the logging mutex
  63. // All other threads NEED to be done before we clean up APR, so this is okay.
  64. apr_thread_mutex_destroy(gLogMutexp);
  65. gLogMutexp = NULL;
  66. }
  67. if (gCallStacksLogMutexp)
  68. {
  69. // Clean up the logging mutex
  70. // All other threads NEED to be done before we clean up APR, so this is okay.
  71. apr_thread_mutex_destroy(gCallStacksLogMutexp);
  72. gCallStacksLogMutexp = NULL;
  73. }
  74. if (gAPRPoolp)
  75. {
  76. apr_pool_destroy(gAPRPoolp);
  77. gAPRPoolp = NULL;
  78. }
  79. if (LLAPRFile::sAPRFilePoolp)
  80. {
  81. delete LLAPRFile::sAPRFilePoolp ;
  82. LLAPRFile::sAPRFilePoolp = NULL ;
  83. }
  84. apr_terminate();
  85. }
  86. //
  87. //
  88. //LLAPRPool
  89. //
  90. LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) 
  91. : mParent(parent),
  92. mReleasePoolFlag(releasePoolFlag),
  93. mMaxSize(size),
  94. mPool(NULL)
  95. {
  96. createAPRPool() ;
  97. }
  98. LLAPRPool::~LLAPRPool() 
  99. {
  100. releaseAPRPool() ;
  101. }
  102. void LLAPRPool::createAPRPool()
  103. {
  104. if(mPool)
  105. {
  106. return ;
  107. }
  108. mStatus = apr_pool_create(&mPool, mParent);
  109. ll_apr_warn_status(mStatus) ;
  110. if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
  111. {
  112. apr_allocator_t *allocator = apr_pool_allocator_get(mPool); 
  113. if (allocator) 
  114. apr_allocator_max_free_set(allocator, mMaxSize) ;
  115. }
  116. }
  117. }
  118. void LLAPRPool::releaseAPRPool()
  119. {
  120. if(!mPool)
  121. {
  122. return ;
  123. }
  124. if(!mParent || mReleasePoolFlag)
  125. {
  126. apr_pool_destroy(mPool) ;
  127. mPool = NULL ;
  128. }
  129. }
  130. //virtual
  131. apr_pool_t* LLAPRPool::getAPRPool() 
  132. {
  133. return mPool ; 
  134. }
  135. LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) 
  136.   : LLAPRPool(parent, size, releasePoolFlag),
  137.   mNumActiveRef(0),
  138.   mNumTotalRef(0),
  139.   mMutexPool(NULL),
  140.   mMutexp(NULL)
  141. {
  142. //create mutex
  143. if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
  144. {
  145. apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
  146. apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
  147. }
  148. }
  149. LLVolatileAPRPool::~LLVolatileAPRPool()
  150. {
  151. //delete mutex
  152. if(mMutexp)
  153. {
  154. apr_thread_mutex_destroy(mMutexp);
  155. apr_pool_destroy(mMutexPool);
  156. }
  157. }
  158. //
  159. //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
  160. //
  161. //virtual 
  162. apr_pool_t* LLVolatileAPRPool::getAPRPool() 
  163. {
  164. return LLVolatileAPRPool::getVolatileAPRPool() ;
  165. }
  166. apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() 
  167. {
  168. LLScopedLock lock(mMutexp) ;
  169. mNumTotalRef++ ;
  170. mNumActiveRef++ ;
  171. if(!mPool)
  172. {
  173. createAPRPool() ;
  174. }
  175. return mPool ;
  176. }
  177. void LLVolatileAPRPool::clearVolatileAPRPool() 
  178. {
  179. LLScopedLock lock(mMutexp) ;
  180. if(mNumActiveRef > 0)
  181. {
  182. mNumActiveRef--;
  183. if(mNumActiveRef < 1)
  184. {
  185. if(isFull()) 
  186. {
  187. mNumTotalRef = 0 ;
  188. //destroy the apr_pool.
  189. releaseAPRPool() ;
  190. }
  191. else 
  192. {
  193. //This does not actually free the memory, 
  194. //it just allows the pool to re-use this memory for the next allocation. 
  195. apr_pool_clear(mPool) ;
  196. }
  197. }
  198. }
  199. else
  200. {
  201. llassert_always(mNumActiveRef > 0) ;
  202. }
  203. //paranoia check if the pool is jammed.
  204. //will remove the check before going to release.
  205. llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
  206. }
  207. BOOL LLVolatileAPRPool::isFull()
  208. {
  209. return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
  210. }
  211. //---------------------------------------------------------------------
  212. //
  213. // LLScopedLock
  214. //
  215. LLScopedLock::LLScopedLock(apr_thread_mutex_t* mutex) : mMutex(mutex)
  216. {
  217. if(mutex)
  218. {
  219. if(ll_apr_warn_status(apr_thread_mutex_lock(mMutex)))
  220. {
  221. mLocked = false;
  222. }
  223. else
  224. {
  225. mLocked = true;
  226. }
  227. }
  228. else
  229. {
  230. mLocked = false;
  231. }
  232. }
  233. LLScopedLock::~LLScopedLock()
  234. {
  235. unlock();
  236. }
  237. void LLScopedLock::unlock()
  238. {
  239. if(mLocked)
  240. {
  241. if(!ll_apr_warn_status(apr_thread_mutex_unlock(mMutex)))
  242. {
  243. mLocked = false;
  244. }
  245. }
  246. }
  247. //---------------------------------------------------------------------
  248. bool ll_apr_warn_status(apr_status_t status)
  249. {
  250. if(APR_SUCCESS == status) return false;
  251. char buf[MAX_STRING]; /* Flawfinder: ignore */
  252. apr_strerror(status, buf, MAX_STRING);
  253. LL_WARNS("APR") << "APR: " << buf << LL_ENDL;
  254. return true;
  255. }
  256. void ll_apr_assert_status(apr_status_t status)
  257. {
  258. llassert(ll_apr_warn_status(status) == false);
  259. }
  260. //---------------------------------------------------------------------
  261. //
  262. // LLAPRFile functions
  263. //
  264. LLAPRFile::LLAPRFile()
  265. : mFile(NULL),
  266.   mCurrentFilePoolp(NULL)
  267. {
  268. }
  269. LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
  270. : mFile(NULL),
  271.   mCurrentFilePoolp(NULL)
  272. {
  273. open(filename, flags, pool);
  274. }
  275. LLAPRFile::~LLAPRFile()
  276. {
  277. close() ;
  278. }
  279. apr_status_t LLAPRFile::close() 
  280. {
  281. apr_status_t ret = APR_SUCCESS ;
  282. if(mFile)
  283. {
  284. ret = apr_file_close(mFile);
  285. mFile = NULL ;
  286. }
  287. if(mCurrentFilePoolp)
  288. {
  289. mCurrentFilePoolp->clearVolatileAPRPool() ;
  290. mCurrentFilePoolp = NULL ;
  291. }
  292. return ret ;
  293. }
  294. apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
  295. {
  296. apr_status_t s ;
  297. //check if already open some file
  298. llassert_always(!mFile) ;
  299. llassert_always(!mCurrentFilePoolp) ;
  300. apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ;
  301. s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool));
  302. if (s != APR_SUCCESS || !mFile)
  303. {
  304. mFile = NULL ;
  305. if (sizep)
  306. {
  307. *sizep = 0;
  308. }
  309. }
  310. else if (sizep)
  311. {
  312. S32 file_size = 0;
  313. apr_off_t offset = 0;
  314. if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
  315. {
  316. llassert_always(offset <= 0x7fffffff);
  317. file_size = (S32)offset;
  318. offset = 0;
  319. apr_file_seek(mFile, APR_SET, &offset);
  320. }
  321. *sizep = file_size;
  322. }
  323. if(!mCurrentFilePoolp)
  324. {
  325. mCurrentFilePoolp = pool ;
  326. if(!mFile)
  327. {
  328. close() ;
  329. }
  330. }
  331. return s ;
  332. }
  333. //use gAPRPoolp.
  334. apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool)
  335. {
  336. apr_status_t s;
  337. //check if already open some file
  338. llassert_always(!mFile) ;
  339. llassert_always(!mCurrentFilePoolp) ;
  340. llassert_always(use_global_pool) ; //be aware of using gAPRPoolp.
  341. s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
  342. if (s != APR_SUCCESS || !mFile)
  343. {
  344. mFile = NULL ;
  345. close() ;
  346. return s;
  347. }
  348. return s;
  349. }
  350. apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
  351. {
  352. if(!pool)
  353. {
  354. mCurrentFilePoolp = sAPRFilePoolp ;
  355. return mCurrentFilePoolp->getVolatileAPRPool() ;
  356. }
  357. return pool ;
  358. }
  359. // File I/O
  360. S32 LLAPRFile::read(void *buf, S32 nbytes)
  361. {
  362. llassert_always(mFile) ;
  363. apr_size_t sz = nbytes;
  364. apr_status_t s = apr_file_read(mFile, buf, &sz);
  365. if (s != APR_SUCCESS)
  366. {
  367. ll_apr_warn_status(s);
  368. return 0;
  369. }
  370. else
  371. {
  372. llassert_always(sz <= 0x7fffffff);
  373. return (S32)sz;
  374. }
  375. }
  376. S32 LLAPRFile::write(const void *buf, S32 nbytes)
  377. {
  378. llassert_always(mFile) ;
  379. apr_size_t sz = nbytes;
  380. apr_status_t s = apr_file_write(mFile, buf, &sz);
  381. if (s != APR_SUCCESS)
  382. {
  383. ll_apr_warn_status(s);
  384. return 0;
  385. }
  386. else
  387. {
  388. llassert_always(sz <= 0x7fffffff);
  389. return (S32)sz;
  390. }
  391. }
  392. S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
  393. {
  394. return LLAPRFile::seek(mFile, where, offset) ;
  395. }
  396. //
  397. //*******************************************************************************************************************************
  398. //static components of LLAPRFile
  399. //
  400. //static
  401. apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool) 
  402. {
  403. apr_status_t ret = APR_SUCCESS ;
  404. if(file_handle)
  405. {
  406. ret = apr_file_close(file_handle);
  407. file_handle = NULL ;
  408. }
  409. if(pool)
  410. {
  411. pool->clearVolatileAPRPool() ;
  412. }
  413. return ret ;
  414. }
  415. //static
  416. apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
  417. {
  418. apr_status_t s;
  419. apr_file_t* file_handle ;
  420. pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
  421. s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
  422. if (s != APR_SUCCESS || !file_handle)
  423. {
  424. ll_apr_warn_status(s);
  425. LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
  426. file_handle = NULL ;
  427. close(file_handle, pool) ;
  428. return NULL;
  429. }
  430. return file_handle ;
  431. }
  432. //static
  433. S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
  434. {
  435. if(!file_handle)
  436. {
  437. return -1 ;
  438. }
  439. apr_status_t s;
  440. apr_off_t apr_offset;
  441. if (offset >= 0)
  442. {
  443. apr_offset = (apr_off_t)offset;
  444. s = apr_file_seek(file_handle, where, &apr_offset);
  445. }
  446. else
  447. {
  448. apr_offset = 0;
  449. s = apr_file_seek(file_handle, APR_END, &apr_offset);
  450. }
  451. if (s != APR_SUCCESS)
  452. {
  453. ll_apr_warn_status(s);
  454. return -1;
  455. }
  456. else
  457. {
  458. llassert_always(apr_offset <= 0x7fffffff);
  459. return (S32)apr_offset;
  460. }
  461. }
  462. //static
  463. S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
  464. {
  465. //*****************************************
  466. apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY); 
  467. //*****************************************
  468. if (!file_handle)
  469. {
  470. return 0;
  471. }
  472. S32 off;
  473. if (offset < 0)
  474. off = LLAPRFile::seek(file_handle, APR_END, 0);
  475. else
  476. off = LLAPRFile::seek(file_handle, APR_SET, offset);
  477. apr_size_t bytes_read;
  478. if (off < 0)
  479. {
  480. bytes_read = 0;
  481. }
  482. else
  483. {
  484. bytes_read = nbytes ;
  485. apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
  486. if (s != APR_SUCCESS)
  487. {
  488. LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
  489. ll_apr_warn_status(s);
  490. bytes_read = 0;
  491. }
  492. else
  493. {
  494. llassert_always(bytes_read <= 0x7fffffff);
  495. }
  496. }
  497. //*****************************************
  498. close(file_handle, pool) ; 
  499. //*****************************************
  500. return (S32)bytes_read;
  501. }
  502. //static
  503. S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
  504. {
  505. apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
  506. if (offset < 0)
  507. {
  508. flags |= APR_APPEND;
  509. offset = 0;
  510. }
  511. //*****************************************
  512. apr_file_t* file_handle = open(filename, pool, flags);
  513. //*****************************************
  514. if (!file_handle)
  515. {
  516. return 0;
  517. }
  518. if (offset > 0)
  519. {
  520. offset = LLAPRFile::seek(file_handle, APR_SET, offset);
  521. }
  522. apr_size_t bytes_written;
  523. if (offset < 0)
  524. {
  525. bytes_written = 0;
  526. }
  527. else
  528. {
  529. bytes_written = nbytes ;
  530. apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
  531. if (s != APR_SUCCESS)
  532. {
  533. LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL;
  534. ll_apr_warn_status(s);
  535. bytes_written = 0;
  536. }
  537. else
  538. {
  539. llassert_always(bytes_written <= 0x7fffffff);
  540. }
  541. }
  542. //*****************************************
  543. LLAPRFile::close(file_handle, pool);
  544. //*****************************************
  545. return (S32)bytes_written;
  546. }
  547. //static
  548. bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
  549. {
  550. apr_status_t s;
  551. pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
  552. s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool());
  553. pool->clearVolatileAPRPool() ;
  554. if (s != APR_SUCCESS)
  555. {
  556. ll_apr_warn_status(s);
  557. LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
  558. return false;
  559. }
  560. return true;
  561. }
  562. //static
  563. bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool)
  564. {
  565. apr_status_t s;
  566. pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
  567. s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool());
  568. pool->clearVolatileAPRPool() ;
  569. if (s != APR_SUCCESS)
  570. {
  571. ll_apr_warn_status(s);
  572. LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
  573. return false;
  574. }
  575. return true;
  576. }
  577. //static
  578. bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
  579. {
  580. apr_file_t* apr_file;
  581. apr_status_t s;
  582. pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
  583. s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
  584. if (s != APR_SUCCESS || !apr_file)
  585. {
  586. pool->clearVolatileAPRPool() ;
  587. return false;
  588. }
  589. else
  590. {
  591. apr_file_close(apr_file) ;
  592. pool->clearVolatileAPRPool() ;
  593. return true;
  594. }
  595. }
  596. //static
  597. S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
  598. {
  599. apr_file_t* apr_file;
  600. apr_finfo_t info;
  601. apr_status_t s;
  602. pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
  603. s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool());
  604. if (s != APR_SUCCESS || !apr_file)
  605. {
  606. pool->clearVolatileAPRPool() ;
  607. return 0;
  608. }
  609. else
  610. {
  611. apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
  612. apr_file_close(apr_file) ;
  613. pool->clearVolatileAPRPool() ;
  614. if (s == APR_SUCCESS)
  615. {
  616. return (S32)info.size;
  617. }
  618. else
  619. {
  620. return 0;
  621. }
  622. }
  623. }
  624. //static
  625. bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
  626. {
  627. apr_status_t s;
  628. pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
  629. s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool());
  630. pool->clearVolatileAPRPool() ;
  631. if (s != APR_SUCCESS)
  632. {
  633. ll_apr_warn_status(s);
  634. LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
  635. return false;
  636. }
  637. return true;
  638. }
  639. //static
  640. bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
  641. {
  642. apr_status_t s;
  643. pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
  644. s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool());
  645. pool->clearVolatileAPRPool() ;
  646. if (s != APR_SUCCESS)
  647. {
  648. ll_apr_warn_status(s);
  649. LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
  650. return false;
  651. }
  652. return true;
  653. }
  654. //
  655. //end of static components of LLAPRFile
  656. //*******************************************************************************************************************************
  657. //