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&lt;&gt;</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