00001
00002
00003 #include "ace/Filecache.h"
00004 #include "ace/Object_Manager.h"
00005 #include "ace/Log_Msg.h"
00006 #include "ace/ACE.h"
00007 #include "ace/Guard_T.h"
00008 #include "ace/OS_NS_string.h"
00009 #include "ace/OS_NS_time.h"
00010 #include "ace/OS_NS_unistd.h"
00011 #include "ace/OS_NS_fcntl.h"
00012
00013 ACE_RCSID (ace,
00014 Filecache,
00015 "Filecache.cpp,v 4.84 2006/06/09 07:51:09 jwillemsen Exp")
00016
00017 #if defined (ACE_WIN32)
00018
00019 #define R_MASK ACE_DEFAULT_OPEN_PERMS
00020 #define W_MASK 0
00021 #else
00022 #define R_MASK S_IRUSR|S_IRGRP|S_IROTH
00023 #define W_MASK S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH
00024 #endif
00025
00026 #if defined (ACE_WIN32)
00027
00028 #define READ_FLAGS (FILE_FLAG_SEQUENTIAL_SCAN | \
00029 FILE_FLAG_OVERLAPPED | \
00030 O_RDONLY)
00031
00032
00033 #define WRITE_FLAGS (FILE_FLAG_SEQUENTIAL_SCAN | \
00034 FILE_FLAG_OVERLAPPED | \
00035 O_RDWR | O_CREAT | O_TRUNC)
00036
00037
00038 #else
00039 #define READ_FLAGS O_RDONLY
00040
00041 #define WRITE_FLAGS (O_RDWR | O_CREAT | O_TRUNC)
00042
00043 #endif
00044
00045 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00046
00047
00048 ACE_Filecache *ACE_Filecache::cvf_ = 0;
00049
00050 void
00051 ACE_Filecache_Handle::init (void)
00052 {
00053 this->file_ = 0;
00054 this->handle_ = ACE_INVALID_HANDLE;
00055 }
00056
00057 ACE_Filecache_Handle::ACE_Filecache_Handle (void)
00058 : file_ (0), handle_ (0), mapit_ (0)
00059 {
00060 this->init ();
00061 }
00062
00063 ACE_Filecache_Handle::ACE_Filecache_Handle (const ACE_TCHAR *filename,
00064 ACE_Filecache_Flag mapit)
00065 : file_ (0), handle_ (0), mapit_ (mapit)
00066 {
00067 this->init ();
00068
00069
00070
00071
00072
00073 this->file_ = ACE_Filecache::instance ()->fetch (filename, mapit);
00074 }
00075
00076 ACE_Filecache_Handle::ACE_Filecache_Handle (const ACE_TCHAR *filename,
00077 int size,
00078 ACE_Filecache_Flag mapit)
00079 : file_ (0), handle_ (0), mapit_ (mapit)
00080 {
00081 this->init ();
00082
00083 if (size == 0)
00084 ACE_Filecache::instance ()->remove (filename);
00085 else
00086 {
00087
00088
00089
00090
00091
00092
00093 this->file_ = ACE_Filecache::instance ()->create (filename, size);
00094 }
00095 }
00096
00097 ACE_Filecache_Handle::~ACE_Filecache_Handle (void)
00098 {
00099 if (this->handle_ != ACE_INVALID_HANDLE)
00100
00101 ACE_OS::close (this->handle_);
00102
00103 ACE_Filecache::instance ()->finish (this->file_);
00104 }
00105
00106 void *
00107 ACE_Filecache_Handle::address (void) const
00108 {
00109 return this->file_ == 0 ? 0 : this->file_->address ();
00110 }
00111
00112 ACE_HANDLE
00113 ACE_Filecache_Handle::handle (void) const
00114 {
00115 if (this->handle_ == ACE_INVALID_HANDLE && this->file_ != 0)
00116 {
00117 ACE_Filecache_Handle *mutable_this =
00118 const_cast<ACE_Filecache_Handle *> (this);
00119 mutable_this->handle_ = ACE_OS::dup (this->file_->handle ());
00120 }
00121 return this->handle_;
00122 }
00123
00124 int
00125 ACE_Filecache_Handle::error (void) const
00126 {
00127 if (this->file_ == 0)
00128 return -1;
00129 else
00130 return this->file_->error ();
00131 }
00132
00133 ACE_LOFF_T
00134 ACE_Filecache_Handle::size (void) const
00135 {
00136 if (this->file_ == 0)
00137 return -1;
00138 else
00139 return this->file_->size ();
00140 }
00141
00142
00143
00144
00145
00146 #define ACE_Filecache_Hash \
00147 ACE_Hash_Map_Manager_Ex<const ACE_TCHAR *, ACE_Filecache_Object *, ACE_Hash<const ACE_TCHAR *>, ACE_Equal_To<const ACE_TCHAR *>, ACE_Null_Mutex>
00148 #define ACE_Filecache_Hash_Entry \
00149 ACE_Hash_Map_Entry<const ACE_TCHAR *, ACE_Filecache_Object *>
00150
00151 template <>
00152 ACE_Filecache_Hash_Entry::ACE_Hash_Map_Entry (
00153 const ACE_TCHAR *const &ext_id,
00154 ACE_Filecache_Object *const &int_id,
00155 ACE_Filecache_Hash_Entry *next,
00156 ACE_Filecache_Hash_Entry *prev)
00157 : ext_id_ (ext_id
00158 ? ACE_OS::strdup (ext_id)
00159 : ACE_OS::strdup (ACE_LIB_TEXT (""))),
00160 int_id_ (int_id),
00161 next_ (next),
00162 prev_ (prev)
00163 {
00164 }
00165
00166 template <>
00167 ACE_Filecache_Hash_Entry::ACE_Hash_Map_Entry (ACE_Filecache_Hash_Entry *next,
00168 ACE_Filecache_Hash_Entry *prev)
00169 : ext_id_ (0),
00170 next_ (next),
00171 prev_ (prev)
00172 {
00173 }
00174
00175 template <>
00176 ACE_Filecache_Hash_Entry::~ACE_Hash_Map_Entry (void)
00177 {
00178 ACE_OS::free ((void *) ext_id_);
00179 }
00180
00181
00182
00183
00184 template <>
00185 unsigned long
00186 ACE_Filecache_Hash::hash (const ACE_TCHAR *const &ext_id)
00187 {
00188 return ACE::hash_pjw (ext_id);
00189 }
00190
00191 template <>
00192 int
00193 ACE_Filecache_Hash::equal (const ACE_TCHAR *const &id1,
00194 const ACE_TCHAR *const &id2)
00195 {
00196 return ACE_OS::strcmp (id1, id2) == 0;
00197 }
00198
00199 #undef ACE_Filecache_Hash
00200 #undef ACE_Filecache_Hash_Entry
00201
00202
00203
00204
00205
00206
00207 ACE_Filecache *
00208 ACE_Filecache::instance (void)
00209 {
00210
00211 if (ACE_Filecache::cvf_ == 0)
00212 {
00213 ACE_SYNCH_RW_MUTEX &lock =
00214 *ACE_Managed_Object<ACE_SYNCH_RW_MUTEX>::get_preallocated_object
00215 (ACE_Object_Manager::ACE_FILECACHE_LOCK);
00216 ACE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX, ace_mon, lock, 0);
00217
00218
00219
00220 if (ACE_Filecache::cvf_ == 0)
00221 ACE_NEW_RETURN (ACE_Filecache::cvf_,
00222 ACE_Filecache,
00223 0);
00224 }
00225
00226 return ACE_Filecache::cvf_;
00227 }
00228
00229 ACE_Filecache::ACE_Filecache (void)
00230 : size_ (ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE),
00231 hash_ (this->size_)
00232 {
00233 }
00234
00235 ACE_Filecache::~ACE_Filecache (void)
00236 {
00237 }
00238
00239 ACE_Filecache_Object *
00240 ACE_Filecache::insert_i (const ACE_TCHAR *filename,
00241 ACE_SYNCH_RW_MUTEX &filelock,
00242 int mapit)
00243 {
00244 ACE_Filecache_Object *handle = 0;
00245
00246 if (this->hash_.find (filename, handle) == -1)
00247 {
00248 ACE_NEW_RETURN (handle,
00249 ACE_Filecache_Object (filename, filelock, 0, mapit),
00250 0);
00251
00252
00253
00254 if (this->hash_.bind (filename, handle) == -1)
00255 {
00256 delete handle;
00257 handle = 0;
00258 }
00259 }
00260 else
00261 handle = 0;
00262
00263 return handle;
00264 }
00265
00266 ACE_Filecache_Object *
00267 ACE_Filecache::remove_i (const ACE_TCHAR *filename)
00268 {
00269 ACE_Filecache_Object *handle = 0;
00270
00271
00272 if (this->hash_.unbind (filename, handle) == 0)
00273 {
00274 handle->stale_ = 1;
00275
00276
00277
00278 if (handle->lock_.tryacquire_write () == 0)
00279 {
00280 delete handle;
00281 handle = 0;
00282 }
00283 }
00284 else
00285 handle = 0;
00286
00287 return handle;
00288 }
00289
00290 ACE_Filecache_Object *
00291 ACE_Filecache::update_i (const ACE_TCHAR *filename,
00292 ACE_SYNCH_RW_MUTEX &filelock,
00293 int mapit)
00294 {
00295 ACE_Filecache_Object *handle = 0;
00296
00297 handle = this->remove_i (filename);
00298 handle = this->insert_i (filename, filelock, mapit);
00299
00300 return handle;
00301 }
00302
00303 int
00304 ACE_Filecache::find (const ACE_TCHAR *filename)
00305 {
00306 return this->hash_.find (filename);
00307 }
00308
00309
00310 ACE_Filecache_Object *
00311 ACE_Filecache::remove (const ACE_TCHAR *filename)
00312 {
00313 ACE_Filecache_Object *handle = 0;
00314
00315 u_long loc = ACE::hash_pjw (filename) % this->size_;
00316 ACE_SYNCH_RW_MUTEX &hashlock = this->hash_lock_[loc];
00317
00318
00319 if (this->hash_.find (filename, handle) != -1)
00320 {
00321 ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
00322 ace_mon,
00323 hashlock,
00324 0);
00325
00326 return this->remove_i (filename);
00327 }
00328
00329 return 0;
00330 }
00331
00332
00333 ACE_Filecache_Object *
00334 ACE_Filecache::fetch (const ACE_TCHAR *filename, int mapit)
00335 {
00336 ACE_Filecache_Object *handle = 0;
00337
00338 u_long loc = ACE::hash_pjw (filename) % this->size_;
00339 ACE_SYNCH_RW_MUTEX &hashlock = this->hash_lock_[loc];
00340 ACE_SYNCH_RW_MUTEX &filelock = this->file_lock_[loc];
00341
00342 filelock.acquire_read ();
00343
00344 if (this->hash_.find (filename, handle) == -1)
00345 {
00346 ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
00347 ace_mon,
00348 hashlock,
00349 0);
00350
00351
00352 handle = this->insert_i (filename, filelock, mapit);
00353
00354 if (handle == 0)
00355 filelock.release ();
00356 }
00357 else
00358 {
00359 if (handle->update ())
00360 {
00361 {
00362
00363 ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
00364 ace_mon,
00365 hashlock,
00366 0);
00367
00368
00369 handle = this->update_i (filename, filelock, mapit);
00370
00371 if (handle == 0)
00372 filelock.release ();
00373 }
00374 }
00375
00376 }
00377
00378 return handle;
00379 }
00380
00381 ACE_Filecache_Object *
00382 ACE_Filecache::create (const ACE_TCHAR *filename, int size)
00383 {
00384 ACE_Filecache_Object *handle = 0;
00385
00386 u_long loc = ACE::hash_pjw (filename) % this->size_;
00387 ACE_SYNCH_RW_MUTEX &filelock = this->file_lock_[loc];
00388
00389 ACE_NEW_RETURN (handle,
00390 ACE_Filecache_Object (filename, size, filelock),
00391 0);
00392 handle->acquire ();
00393
00394 return handle;
00395 }
00396
00397 ACE_Filecache_Object *
00398 ACE_Filecache::finish (ACE_Filecache_Object *&file)
00399 {
00400 if (file == 0)
00401 return file;
00402
00403 u_long loc = ACE::hash_pjw (file->filename_) % this->size_;
00404 ACE_SYNCH_RW_MUTEX &hashlock = this->hash_lock_[loc];
00405
00406 if (file != 0)
00407 switch (file->action_)
00408 {
00409 case ACE_Filecache_Object::ACE_WRITING:
00410 {
00411 ACE_WRITE_GUARD_RETURN (ACE_SYNCH_RW_MUTEX,
00412 ace_mon,
00413 hashlock,
00414 0);
00415
00416 file->release ();
00417
00418 this->remove_i (file->filename_);
00419 #if 0
00420 int result = this->hash_.bind (file->filename (), file);
00421
00422 if (result == 0)
00423 file->acquire ();
00424 #else
00425
00426 if (file->stale_)
00427 {
00428
00429
00430 if (file->lock_.tryacquire_write () == 0)
00431 {
00432 delete file;
00433 file = 0;
00434 }
00435 }
00436 #endif
00437 }
00438
00439 break;
00440 default:
00441 file->release ();
00442
00443
00444 if (file->stale_)
00445 {
00446
00447
00448 if (file->lock_.tryacquire_write () == 0)
00449 {
00450 delete file;
00451 file = 0;
00452 }
00453 }
00454
00455 break;
00456 }
00457
00458 return file;
00459 }
00460
00461 void
00462 ACE_Filecache_Object::init (void)
00463 {
00464 this->filename_[0] = '\0';
00465 this->handle_ = ACE_INVALID_HANDLE;
00466 this->error_ = ACE_SUCCESS;
00467 this->tempname_ = 0;
00468 this->size_ = 0;
00469
00470 ACE_OS::memset (&(this->stat_), 0, sizeof (this->stat_));
00471 }
00472
00473 ACE_Filecache_Object::ACE_Filecache_Object (void)
00474 : tempname_ (0),
00475 mmap_ (),
00476 handle_ (0),
00477
00478 size_ (0),
00479 action_ (0),
00480 error_ (0),
00481 stale_ (0),
00482
00483 junklock_ (),
00484 lock_ (junklock_)
00485 {
00486 this->init ();
00487 }
00488
00489 ACE_Filecache_Object::ACE_Filecache_Object (const ACE_TCHAR *filename,
00490 ACE_SYNCH_RW_MUTEX &lock,
00491 LPSECURITY_ATTRIBUTES sa,
00492 int mapit)
00493 : tempname_ (0),
00494 mmap_ (),
00495 handle_ (0),
00496
00497 size_ (0),
00498 action_ (0),
00499 error_ (0),
00500 stale_ (0),
00501 sa_ (sa),
00502 junklock_ (),
00503 lock_ (lock)
00504 {
00505 this->init ();
00506
00507
00508 ACE_OS::strcpy (this->filename_, filename);
00509 this->action_ = ACE_Filecache_Object::ACE_READING;
00510
00511
00512
00513 if (ACE_OS::access (this->filename_, R_OK) == -1)
00514 {
00515 this->error_i (ACE_Filecache_Object::ACE_ACCESS_FAILED);
00516 return;
00517 }
00518
00519
00520 if (ACE_OS::stat (this->filename_, &this->stat_) == -1)
00521 {
00522 this->error_i (ACE_Filecache_Object::ACE_STAT_FAILED);
00523 return;
00524 }
00525
00526 this->size_ = this->stat_.st_size;
00527 this->tempname_ = this->filename_;
00528
00529
00530 this->handle_ = ACE_OS::open (this->tempname_,
00531 READ_FLAGS, R_MASK, this->sa_);
00532 if (this->handle_ == ACE_INVALID_HANDLE)
00533 {
00534 this->error_i (ACE_Filecache_Object::ACE_OPEN_FAILED,
00535 ACE_LIB_TEXT ("ACE_Filecache_Object::ctor: open"));
00536 return;
00537 }
00538
00539 if (mapit)
00540 {
00541
00542 if (this->mmap_.map (this->handle_, -1,
00543 PROT_READ, ACE_MAP_PRIVATE, 0, 0, this->sa_) != 0)
00544 {
00545 this->error_i (ACE_Filecache_Object::ACE_MEMMAP_FAILED,
00546 ACE_LIB_TEXT ("ACE_Filecache_Object::ctor: map"));
00547 ACE_OS::close (this->handle_);
00548 this->handle_ = ACE_INVALID_HANDLE;
00549 return;
00550 }
00551 }
00552
00553
00554 this->action_ = ACE_Filecache_Object::ACE_READING;
00555 }
00556
00557 ACE_Filecache_Object::ACE_Filecache_Object (const ACE_TCHAR *filename,
00558 off_t size,
00559 ACE_SYNCH_RW_MUTEX &lock,
00560 LPSECURITY_ATTRIBUTES sa)
00561 : stale_ (0),
00562 sa_ (sa),
00563 lock_ (lock)
00564 {
00565 this->init ();
00566
00567 this->size_ = size;
00568 ACE_OS::strcpy (this->filename_, filename);
00569 this->action_ = ACE_Filecache_Object::ACE_WRITING;
00570
00571
00572 if (ACE_OS::access (this->filename_, R_OK|W_OK) == -1
00573
00574 && ACE_OS::access (this->filename_, F_OK) != -1)
00575 {
00576
00577 this->error_i (ACE_Filecache_Object::ACE_ACCESS_FAILED);
00578 return;
00579 }
00580
00581 this->tempname_ = this->filename_;
00582
00583
00584 this->handle_ = ACE_OS::open (this->tempname_, WRITE_FLAGS, W_MASK, this->sa_);
00585 if (this->handle_ == ACE_INVALID_HANDLE)
00586 {
00587 this->error_i (ACE_Filecache_Object::ACE_OPEN_FAILED,
00588 ACE_LIB_TEXT ("ACE_Filecache_Object::acquire: open"));
00589 return;
00590 }
00591
00592
00593 if (ACE_OS::pwrite (this->handle_, "", 1, this->size_ - 1) != 1)
00594 {
00595 this->error_i (ACE_Filecache_Object::ACE_WRITE_FAILED,
00596 ACE_LIB_TEXT ("ACE_Filecache_Object::acquire: write"));
00597 ACE_OS::close (this->handle_);
00598 return;
00599 }
00600
00601
00602 if (this->mmap_.map (this->handle_, this->size_, PROT_RDWR, MAP_SHARED,
00603 0, 0, this->sa_) != 0)
00604 {
00605 this->error_i (ACE_Filecache_Object::ACE_MEMMAP_FAILED,
00606 ACE_LIB_TEXT ("ACE_Filecache_Object::acquire: map"));
00607 ACE_OS::close (this->handle_);
00608 }
00609
00610
00611 }
00612
00613 ACE_Filecache_Object::~ACE_Filecache_Object (void)
00614 {
00615 if (this->error_ == ACE_SUCCESS)
00616 {
00617 this->mmap_.unmap ();
00618 ACE_OS::close (this->handle_);
00619 this->handle_ = ACE_INVALID_HANDLE;
00620 }
00621 }
00622
00623 int
00624 ACE_Filecache_Object::acquire (void)
00625 {
00626 return this->lock_.tryacquire_read ();
00627 }
00628
00629 int
00630 ACE_Filecache_Object::release (void)
00631 {
00632 if (this->action_ == ACE_WRITING)
00633 {
00634
00635
00636 #if 0
00637 ACE_HANDLE original = ACE_OS::open (this->filename_, WRITE_FLAGS, W_MASK,
00638 this->sa_);
00639 if (original == ACE_INVALID_HANDLE)
00640 this->error_ = ACE_Filecache_Object::ACE_OPEN_FAILED;
00641 else if (ACE_OS::write (original, this->mmap_.addr (),
00642 this->size_) == -1)
00643 {
00644 this->error_ = ACE_Filecache_Object::ACE_WRITE_FAILED;
00645 ACE_OS::close (original);
00646 ACE_OS::unlink (this->filename_);
00647 }
00648 else if (ACE_OS::stat (this->filename_, &this->stat_) == -1)
00649 this->error_ = ACE_Filecache_Object::ACE_STAT_FAILED;
00650 #endif
00651
00652 this->mmap_.unmap ();
00653 ACE_OS::close (this->handle_);
00654 this->handle_ = ACE_INVALID_HANDLE;
00655
00656 #if 0
00657
00658 this->handle_ = ACE_OS::open (this->tempname_, READ_FLAGS, R_MASK);
00659 if (this->handle_ == ACE_INVALID_HANDLE)
00660 {
00661 this->error_i (ACE_Filecache_Object::ACE_OPEN_FAILED,
00662 "ACE_Filecache_Object::acquire: open");
00663 }
00664 else if (this->mmap_.map (this->handle_, -1,
00665 PROT_READ,
00666 ACE_MAP_PRIVATE,
00667 0,
00668 0,
00669 this->sa_) != 0)
00670 {
00671 this->error_i (ACE_Filecache_Object::ACE_MEMMAP_FAILED,
00672 "ACE_Filecache_Object::acquire: map");
00673 ACE_OS::close (this->handle_);
00674 this->handle_ = ACE_INVALID_HANDLE;
00675 }
00676
00677 this->action_ = ACE_Filecache_Object::ACE_READING;
00678 #endif
00679 }
00680
00681 return this->lock_.release ();
00682 }
00683
00684 int
00685 ACE_Filecache_Object::error (void) const
00686 {
00687
00688 return this->error_;
00689 }
00690
00691 int
00692 ACE_Filecache_Object::error_i (int error_value, const ACE_TCHAR *s)
00693 {
00694 s = s;
00695 ACE_ERROR ((LM_ERROR, ACE_LIB_TEXT ("%p.\n"), s));
00696 this->error_ = error_value;
00697 return error_value;
00698 }
00699
00700 const ACE_TCHAR *
00701 ACE_Filecache_Object::filename (void) const
00702 {
00703
00704 return this->filename_;
00705 }
00706
00707 ACE_LOFF_T
00708 ACE_Filecache_Object::size (void) const
00709 {
00710
00711 return this->size_;
00712 }
00713
00714 ACE_HANDLE
00715 ACE_Filecache_Object::handle (void) const
00716 {
00717
00718 return this->handle_;
00719 }
00720
00721 void *
00722 ACE_Filecache_Object::address (void) const
00723 {
00724
00725 return this->mmap_.addr ();
00726 }
00727
00728 int
00729 ACE_Filecache_Object::update (void) const
00730 {
00731
00732 int result;
00733 ACE_stat statbuf;
00734
00735 if (ACE_OS::stat (this->filename_, &statbuf) == -1)
00736 result = 1;
00737 else
00738
00739 #if defined (ACE_HAS_WINCE)
00740
00741
00742
00743 result = 1;
00744 #else
00745 result = ACE_OS::difftime (this->stat_.st_mtime, statbuf.st_mtime) < 0;
00746 #endif
00747
00748 return result;
00749 }
00750
00751 ACE_END_VERSIONED_NAMESPACE_DECL