1 // ========================================================================== 2 // SeqAn - The Library for Sequence Analysis 3 // ========================================================================== 4 // Copyright (c) 2006-2015, Knut Reinert, FU Berlin 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions are met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above copyright 13 // notice, this list of conditions and the following disclaimer in the 14 // documentation and/or other materials provided with the distribution. 15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of 16 // its contributors may be used to endorse or promote products derived 17 // from this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE 23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 29 // DAMAGE. 30 // 31 // ========================================================================== 32 // Author: David Weese <david.weese@fu-berlin.de> 33 // ========================================================================== 34 // Memory map a whole file and use it as a string. 35 // ========================================================================== 36 // NOTE(esiragusa): this file is deprecated. 37 38 #ifndef SEQAN_HEADER_STRING_MMAP_H 39 #define SEQAN_HEADER_STRING_MMAP_H 40 41 42 /* IOREV 43 * _tested_ 44 * _windows_ 45 * 46 * 47 * tested in library/demos/howto/efficiently_import_sequences.cpp and stellar 48 * 49 * relation to file_format_mmap.h unclear 50 * 51 * relation to string_external unclear, what benifit does string_mmap provide? 52 * 53 */ 54 55 56 ////////////////////////////////////////////////////////////////////////////// 57 58 namespace SEQAN_NAMESPACE_MAIN 59 { 60 61 /*! 62 * @class MMapConfig 63 * @headerfile <seqan/file.h> 64 * @brief Configuration for @link MMapString MMapStrings @endlink. 65 * 66 * @signature template <[typename TFile, [typename TSize]]> 67 * class MMapConfig; 68 * 69 * @tparam TFile The file type to use for the memory mapped string. Defaults to <tt>File<></tt> 70 * @tparam TSize The size type to use. Defaults to <tt>size_t</tt>. 71 * 72 * 73 * @typedef MMapConfig::TFile; 74 * @signature typedef (..) MMapConfig::TFile; 75 * @brief The type to use for files. 76 * 77 * @typedef MMapConfig::TSize; 78 * @signature typedef (..) MMapConfig::TSize; 79 * @brief The type to use for sizes. 80 */ 81 82 template < typename TFile_ = File<>, // default file type 83 typename TSize_ = size_t > // size type 84 struct MMapConfig { 85 //IOREV _nodoc_ doc says using MMap<MMapConfig> is correct, whats this for? 86 typedef TFile_ TFile; 87 typedef TSize_ TSize; 88 }; 89 90 template < typename TConfig = MMapConfig<> > 91 struct MMap {}; 92 //IOREV 93 94 95 ////////////////////////////////////////////////////////////////////////////// 96 // Memory Mapped String 97 ////////////////////////////////////////////////////////////////////////////// 98 99 /*! 100 * @class MMapString MMap String 101 * @headerfile <seqan/file.h> 102 * @extends String 103 * @brief String that is stored in external memory using direct memory mapping. 104 * 105 * @signature template <typename TValue[, typename TConfig]> 106 * class String<TValue, MMap<TConfig> >; 107 * 108 * @tparam TValue The value type to use for the items/characters. 109 * @tparam TConfig The configuration to use for the underlying file. Default: @link MMapConfig @endlink. 110 * 111 * The MMap String enables to access sequences larger than the available physical memory (RAM) by using external memory 112 * (e.g. Hard disk, Network storage, ...) mapped into memory. The size of the string is limited by external memory and 113 * the logical address space (4GB on a 32bit OS). See the String constructor for more details. 114 * 115 * This string also supports fast appending and removing of values at the end. 116 */ 117 118 /*! 119 * @fn MMapString::String 120 * @brief Constructor. 121 * 122 * @signature String::String(); 123 * @signature String::String(file); 124 * @signature String::String(fileName[, openMode]); 125 * 126 * @param[in,out] file The @link File @endlink to use for reading and writing. You must ensture that 127 * <tt>file</tt> is open as the string will not call <tt>open</tt> and <tt>close</tt> 128 * on the file. 129 * @param[in] fileName The path to open. Type: <tt>char const *</tt> 130 * @param[in] openMode The open mode. 131 */ 132 133 template < typename TValue, 134 typename TConfig > 135 class String<TValue, MMap<TConfig> > 136 { 137 //IOREV 138 public: 139 140 typedef typename TConfig::TFile TFile; 141 typedef typename TConfig::TSize TSize; 142 143 TValue *data_begin; 144 TValue *data_end; 145 146 FileMapping<> mapping; 147 FileMappingAdvise advise; 148 149 explicit 150 String(TSize size = 0): data_begin(NULL)151 data_begin(NULL), 152 data_end(NULL), 153 advise(MAP_NORMAL) 154 { 155 resize(*this, size); 156 } 157 158 // associate a file 159 explicit String(TFile & _file)160 String(TFile &_file): 161 data_begin(NULL), 162 data_end(NULL), 163 advise(MAP_NORMAL) 164 { 165 open(*this, _file); 166 } 167 168 // associate a file given filename [and open mode] 169 explicit 170 String(const char *fileName, int openMode = DefaultOpenMode<TFile>::VALUE): data_begin(NULL)171 data_begin(NULL), 172 data_end(NULL), 173 advise(MAP_NORMAL) 174 { 175 open(*this, fileName, openMode); 176 } 177 178 // copy the contents from another string String(String const & source)179 String(String const & source): 180 data_begin(NULL), 181 data_end(NULL), 182 advise(MAP_NORMAL) 183 { 184 assign(*this, source); 185 } 186 template <typename TSource> String(TSource const & source)187 String(TSource const & source): 188 data_begin(NULL), 189 data_end(NULL), 190 advise(MAP_NORMAL) 191 { 192 assign(*this, source); 193 } 194 195 template <typename TSource> 196 String & operator =(TSource const & source) 197 { 198 assign(*this, source); 199 return *this; 200 } 201 String & operator =(String const & source) 202 { 203 assign(*this, source); 204 return *this; 205 } 206 ~String()207 ~String() 208 { 209 close(*this); 210 } 211 212 //____________________________________________________________________________ 213 214 template <typename TPos> 215 inline typename Reference<String>::Type 216 operator [] (TPos pos) 217 { 218 return value(*this, pos); 219 } 220 221 template <typename TPos> 222 inline typename Reference<String const>::Type 223 operator [] (TPos pos) const 224 { 225 return value(*this, pos); 226 } 227 228 //____________________________________________________________________________ 229 230 inline operator bool() 231 { 232 return mapping; 233 } 234 235 //____________________________________________________________________________ 236 237 }; 238 239 template < typename TValue, typename TConfig > 240 inline typename Iterator<String<TValue, MMap<TConfig> > , Standard>::Type begin(String<TValue,MMap<TConfig>> & me,Standard)241 begin(String<TValue, MMap<TConfig> > & me, 242 Standard) 243 { 244 //IOREV 245 SEQAN_CHECKPOINT 246 return me.data_begin; 247 } 248 template < typename TValue, typename TConfig > 249 inline typename Iterator<String<TValue, MMap<TConfig> > const, Standard>::Type begin(String<TValue,MMap<TConfig>> const & me,Standard)250 begin(String<TValue, MMap<TConfig> > const & me, 251 Standard) 252 { 253 //IOREV 254 SEQAN_CHECKPOINT 255 return me.data_begin; 256 } 257 258 //____________________________________________________________________________ 259 260 template < typename TValue, typename TConfig > 261 inline typename Iterator<String<TValue, MMap<TConfig> > , Standard>::Type end(String<TValue,MMap<TConfig>> & me,Standard)262 end(String<TValue, MMap<TConfig> > & me, 263 Standard) 264 { 265 //IOREV 266 SEQAN_CHECKPOINT 267 return me.data_end; 268 } 269 template < typename TValue, typename TConfig > 270 inline typename Iterator<String<TValue, MMap<TConfig> > const, Standard>::Type end(String<TValue,MMap<TConfig>> const & me,Standard)271 end(String<TValue, MMap<TConfig> > const & me, 272 Standard) 273 { 274 //IOREV 275 SEQAN_CHECKPOINT 276 return me.data_end; 277 } 278 279 //____________________________________________________________________________ 280 281 template < typename TValue, typename TConfig > 282 inline typename Size<String<TValue, MMap<TConfig> > >::Type capacity(String<TValue,MMap<TConfig>> const & me)283 capacity(String<TValue, MMap<TConfig> > const & me) 284 { 285 //IOREV 286 SEQAN_CHECKPOINT 287 return length(me.mapping) / sizeof(TValue); 288 } 289 290 //____________________________________________________________________________ 291 292 template < typename TValue, typename TConfig > 293 inline void _setLength(String<TValue,MMap<TConfig>> & me,size_t new_length)294 _setLength( 295 String<TValue, MMap<TConfig> > & me, 296 size_t new_length) 297 { 298 //IOREV 299 SEQAN_CHECKPOINT 300 me.data_end = me.data_begin + new_length; 301 } 302 303 ////////////////////////////////////////////////////////////////////////////// 304 // meta-function interface 305 306 template < typename TValue, typename TConfig > 307 struct Size< String<TValue, MMap<TConfig> > > 308 { 309 //IOREV 310 typedef typename TConfig::TSize Type; 311 }; 312 313 template < typename TValue, typename TConfig > 314 struct Difference< String<TValue, MMap<TConfig> > > 315 { 316 //IOREV 317 typedef typename MakeSigned_<typename TConfig::TSize>::Type Type; 318 }; 319 //____________________________________________________________________________ 320 321 template < typename TValue, typename TConfig > 322 struct DefaultOverflowExplicit<String<TValue, MMap<TConfig> > > 323 { 324 //IOREV 325 typedef Generous Type; 326 }; 327 328 template < typename TValue, typename TConfig > 329 struct DefaultOverflowImplicit<String<TValue, MMap<TConfig> > > 330 { 331 //IOREV 332 typedef Generous Type; 333 }; 334 //____________________________________________________________________________ 335 336 template < typename TValue, typename TConfig > 337 struct IsContiguous< String<TValue, MMap<TConfig> > > 338 { 339 //IOREV 340 typedef True Type; 341 enum { VALUE = true }; 342 }; 343 344 template < typename TValue, typename TConfig > 345 struct AllowsFastRandomAccess< String<TValue, MMap<TConfig> > > 346 { 347 //IOREV 348 typedef False Type; 349 enum { VALUE = false }; 350 }; 351 352 353 ////////////////////////////////////////////////////////////////////////////// 354 // global interface 355 356 //____________________________________________________________________________ 357 358 /*! 359 * @fn MMapString#flush 360 * @brief Waits for all open read/write requests to complete. 361 * 362 * @signature void flush(str); 363 * 364 * @param[in,out] str The MMapString to flush. 365 */ 366 367 template < typename TValue, typename TConfig > 368 inline bool 369 flush(String<TValue, MMap<TConfig> > &me) 370 { 371 typedef typename Size<typename TConfig::TFile>::Type TFileSize; 372 return flushFileSegment( 373 me.mapping, 374 me.data_begin, 375 0, 376 (TFileSize)capacity(me) * (TFileSize)sizeof(TValue)); 377 } 378 379 /*! 380 * @fn MMapString#mmapAdvise 381 * @brief Call advise function for memory mapped files. 382 * 383 * @signature bool mmapAdvise(str, scheme[, beginPos, size]); 384 * 385 * @param[in,out] str The MMapString to call advise in. 386 * @param[in] scheme The memory access scheme to use. Type: FileMappingAdvise. 387 * @param[in] beginPos Begin position in the string for the advise call. 388 * @param[in] size Size of the range used for the advise call. 389 * 390 * @return bool <tt>true</tt> if the advise was successful, <tt>false</tt> otherwise. 391 */ 392 393 template <typename TValue, typename TConfig, typename TPos, typename TSize> 394 inline bool 395 mmapAdvise(String<TValue, MMap<TConfig> > &me, FileMappingAdvise advise, TPos beginPos, TSize size) 396 { 397 typedef typename Size<typename TConfig::TFile>::Type TFileSize; 398 me.advise = advise; 399 return adviseFileSegment( 400 me.mapping, 401 advise, 402 me.data_begin, 403 (TFileSize)beginPos * (TFileSize)sizeof(TValue), 404 (TFileSize)size * (TFileSize)sizeof(TValue)); 405 } 406 407 template <typename TValue, typename TConfig, typename TPos> 408 inline int 409 mmapAdvise(String<TValue, MMap<TConfig> > &me, FileMappingAdvise advise, TPos beginPos) 410 { 411 return mmapAdvise(me, advise, beginPos, capacity(me) - beginPos); 412 } 413 414 template <typename TValue, typename TConfig> 415 inline int 416 mmapAdvise(String<TValue, MMap<TConfig> > &me, FileMappingAdvise advise) 417 { 418 return mmapAdvise(me, advise, 0, capacity(me)); 419 } 420 421 //____________________________________________________________________________ 422 423 // cancel all transactions 424 template < typename TValue, typename TConfig > 425 inline void 426 cancel(String<TValue, MMap<TConfig> > &me) 427 { 428 typedef typename Size<typename TConfig::TFile>::Type TFileSize; 429 cancelFileSegment( 430 me.mapping, 431 me.data_begin, 432 0, 433 (TFileSize)capacity(me) * (TFileSize)sizeof(TValue)); 434 } 435 436 //____________________________________________________________________________ 437 438 // flush and free all allocated pages 439 template < typename TValue, typename TConfig > 440 inline bool 441 flushAndFree(String<TValue, MMap<TConfig> > &me) 442 { 443 return flush(me) && mmapAdvise(me, MAP_DONTNEED); 444 } 445 446 //____________________________________________________________________________ 447 448 template < typename TValue, typename TConfig > 449 inline bool 450 _map(String<TValue, MMap<TConfig> > &me, size_t new_capacity) 451 { 452 typedef typename Size<typename TConfig::TFile>::Type TFileSize; 453 if (new_capacity > 0) 454 { 455 _ensureFileIsOpen(me); 456 if (capacity(me) < new_capacity) 457 resize(me.mapping, (TFileSize)new_capacity * (TFileSize)sizeof(TValue)); 458 me.data_begin = static_cast<TValue*>(mapFileSegment(me.mapping, 0, length(me.mapping))); 459 if (me.data_begin == NULL) 460 { 461 me.data_end = NULL; 462 return false; 463 } 464 adviseFileSegment(me.mapping, me.advise, me.data_begin, 0, length(me.mapping)); 465 } 466 else 467 resize(me.mapping, 0); 468 _setLength(me, new_capacity); 469 return true; 470 } 471 472 template < typename TValue, typename TConfig > 473 inline bool 474 _unmap(String<TValue, MMap<TConfig> > &me) 475 { 476 bool result = true; 477 if (me.data_begin != NULL) 478 { 479 result = unmapFileSegment(me.mapping, me.data_begin, length(me.mapping)); 480 me.data_begin = NULL; 481 } 482 me.data_end = NULL; 483 return result; 484 } 485 486 template < typename TValue, typename TConfig, typename TCapSize > 487 inline bool 488 _remap(String<TValue, MMap<TConfig> > &me, TCapSize new_capacity) 489 { 490 typedef typename Size<String<TValue, MMap<TConfig> > >::Type TSize; 491 typedef typename Size<typename TConfig::TFile>::Type TFileSize; 492 493 bool result = true; 494 495 #ifndef PLATFORM_WINDOWS 496 // Windows doesn't allow to resize the file while having a mapped file segment 497 // Thus, the following part is only supported on Linux/BSD/Mac OS 498 TSize old_capacity = capacity(me); 499 if (me.data_begin && new_capacity > 0) 500 { 501 // if file gets bigger, resize first 502 if (old_capacity < new_capacity) 503 resize(me.mapping, (TFileSize)new_capacity * (TFileSize)sizeof(TValue)); 504 505 me.data_begin = static_cast<TValue*>(remapFileSegment( 506 me.mapping, 507 me.data_begin, 508 0, 509 (TFileSize)old_capacity * (TFileSize)sizeof(TValue), 510 (TFileSize)new_capacity * (TFileSize)sizeof(TValue))); 511 512 // if file gets smaller, resize at last 513 if (old_capacity > new_capacity) 514 resize(me.mapping, (TFileSize)new_capacity * (TFileSize)sizeof(TValue)); 515 516 if (me.data_begin == NULL) 517 { 518 me.data_end = NULL; 519 return false; 520 } 521 return true; 522 } 523 #endif 524 result &= _unmap(me); 525 result &= _map(me, new_capacity); 526 return result; 527 } 528 529 template < typename TValue, typename TConfig > 530 inline void 531 clear(String<TValue, MMap<TConfig> > &me) 532 { 533 //IOREV 534 cancel(me); 535 _unmap(me); 536 resize(me.mapping, 0); 537 } 538 //____________________________________________________________________________ 539 540 template < typename TValue, typename TConfig, typename TSize > 541 inline typename Value<String<TValue, MMap<TConfig> > >::Type * 542 _allocateStorage(String<TValue, MMap<TConfig> > &me, TSize new_capacity) 543 { 544 //IOREV 545 _map(me, _computeSizeForCapacity(me, new_capacity)); 546 return NULL; 547 } 548 549 template < typename TValue, typename TConfig, typename TSize > 550 inline typename Value<String<TValue, MMap<TConfig> > >::Type * 551 _reallocateStorage( 552 String<TValue, MMap<TConfig> > &me, 553 TSize new_capacity) 554 { 555 //IOREV 556 TSize size = _computeSizeForCapacity(me, new_capacity); 557 _remap(me, size); 558 return NULL; 559 } 560 561 template < typename TValue, typename TConfig, typename TSize > 562 inline void 563 _deallocateStorage(String<TValue, MMap<TConfig> > &/*me*/, TValue * /*ptr*/, TSize /*capacity*/) 564 { 565 //IOREV 566 } 567 //____________________________________________________________________________ 568 /*! 569 * @fn MMapString#open 570 * @brief Open the MMapString's underlying file from a path. 571 * 572 * @signature bool open(str, fileName[, openMode]); 573 * 574 * @param[in,out] str The MMapString to open. 575 * @param[in] fileName Path to the file to open. Type: <tt>char const *</tt>. 576 * @param[in] openMode The open mode. Type: <tt>int</tt>. 577 * 578 * @return bool <tt>true</tt> if the operation succeeded and <tt>false</tt> otherwise. 579 */ 580 581 template < typename TValue, typename TConfig > 582 inline bool 583 open(String<TValue, MMap<TConfig> > &me, const char *fileName, int openMode) 584 { 585 //IOREV 586 close(me); 587 if (open(me.mapping, fileName, openMode)) 588 return _map(me, capacity(me)); 589 return false; 590 } 591 592 template < typename TValue, typename TConfig > 593 inline bool 594 open(String<TValue, MMap<TConfig> > &me, const char *fileName) 595 { 596 //IOREV 597 typedef typename String<TValue, MMap<TConfig> >::TFile TFile; 598 return open(me, fileName, DefaultOpenMode<TFile>::VALUE); 599 } 600 601 template < typename TValue, typename TConfig > 602 inline bool 603 open(String<TValue, MMap<TConfig> > &me, typename TConfig::TFile file) 604 { 605 //IOREV 606 close(me); 607 if (open(me.mapping, file)) 608 return _map(me, capacity(me)); 609 return false; 610 } 611 612 /*! 613 * @fn MMapString#openTemp 614 * @brief Open an MMapString using an temporary file. 615 * 616 * @signature bool openTemp(str); 617 * 618 * @param[in,out] str The MMapString to open using temporary file. 619 * 620 * @return bool <tt>true</tt> if opening succeeded, <tt>false</tt> otherwise. 621 */ 622 623 template < typename TValue, typename TConfig > 624 inline bool 625 openTemp(String<TValue, MMap<TConfig> > &me) 626 { 627 //IOREV 628 close(me); 629 return openTemp(me.mapping); 630 } 631 //____________________________________________________________________________ 632 633 template < typename TValue, typename TConfig > 634 inline void 635 _ensureFileIsOpen(String<TValue, MMap<TConfig> > &me) 636 { 637 //IOREV 638 if (!me) 639 { 640 if (!openTemp(me.mapping)) 641 SEQAN_FAIL("Memory Mapped String couldn't open temporary file"); 642 } 643 } 644 //____________________________________________________________________________ 645 646 template < typename TValue, typename TConfig > 647 inline bool 648 save(String<TValue, MMap<TConfig> > const &/*me*/, const char * /*fileName*/, int /*openMode*/) { 649 //IOREV _nodoc_ shouldn't we flush here? in case of abnormal termination... 650 // Memory Mapped Strings are persistent, thus there is no need to save them 651 //MMapStringsDontNeedToBeSaved error; 652 return true; 653 } 654 655 template < typename TValue, typename TConfig > 656 inline bool 657 save(String<TValue, MMap<TConfig> > const &/*me*/, const char * /*fileName*/) { 658 //IOREV _nodoc_ shouldn't we flush here? in case of abnormal termination... 659 // Memory Mapped Strings are persistent, thus there is no need to save them 660 //MMapStringsDontNeedToBeSaved error; 661 return true; 662 } 663 664 template < typename TValue, typename TConfig > 665 inline bool 666 save(String<TValue, MMap<TConfig> > const &/*me*/, typename TConfig::TFile /*file*/) { 667 //IOREV _nodoc_ shouldn't we flush here? in case of abnormal termination... 668 // Memory Mapped Strings are persistent, thus there is no need to save them 669 //MMapStringsDontNeedToBeSaved error; 670 return true; 671 } 672 //____________________________________________________________________________ 673 /*! 674 * @fn MMapString#close 675 * @brief Close the MMapString. 676 * 677 * @signature bool close(str); 678 * 679 * @param[in] str The MMapString to close the file of. 680 * 681 * @return bool <tt>true</tt> if the closing succeeded, <tt>false</tt> otherwise. 682 */ 683 684 template < typename TValue, typename TConfig > 685 inline bool 686 close(String<TValue, MMap<TConfig> > &me) 687 { 688 typedef typename Size<typename TConfig::TFile>::Type TFileSize; 689 690 if (me) 691 { 692 TFileSize finalLen = (TFileSize)length(me) * (TFileSize)sizeof(TValue); 693 694 // close associated file 695 if (me.mapping.temporary) 696 cancel(me); 697 698 _unmap(me); 699 closeAndResize(me.mapping, finalLen); 700 } 701 return true; 702 } 703 704 705 template < typename TValue, typename TConfig > 706 inline void 707 shrinkToFit(String<TValue, MMap<TConfig> > &me) 708 { 709 _remap(me, length(me)); 710 } 711 712 ////////////////////////////////////////////////////////////////////////////// 713 714 715 716 } //namespace SEQAN_NAMESPACE_MAIN 717 718 #endif //#ifndef SEQAN_HEADER_... 719