Imported Upstream version 0.12.7
[bowtie.git] / SeqAn-1.1 / seqan / file / file_array.h
1  /*==========================================================================
2                 SeqAn - The Library for Sequence Analysis
3                           http://www.seqan.de 
4  ============================================================================
5   Copyright (C) 2007
6
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10   version 3 of the License, or (at your option) any later version.
11
12   This library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17  ============================================================================
18   $Id: file_array.h,v 1.1 2008/08/25 16:20:03 langmead Exp $
19  ==========================================================================*/
20
21 #ifndef SEQAN_HEADER_FILE_ARRAY_H
22 #define SEQAN_HEADER_FILE_ARRAY_H
23
24 #include <sstream>
25 #include <iomanip>
26
27
28 //////////////////////////////////////////////////////////////////////////////
29
30 namespace SEQAN_NAMESPACE_MAIN
31 {
32
33         //template < __int64 _FileSize = 2*1024*1024*1024-1, typename TFile = File<> >
34         //struct Chained;
35
36         //template < unsigned _FileCount = 2, typename TFile = File<> >
37         //struct Striped;
38
39
40     template < __int64 _FileSize, typename TFile >
41     struct Size< File< Chained<_FileSize, TFile> > >
42     {
43         typedef __int64 Type;
44     };
45
46     template < __int64 _FileSize, typename TFile >
47     struct Position< File< Chained<_FileSize, TFile> > >
48     {
49         typedef __int64 Type;
50     };
51
52     template < __int64 _FileSize, typename TFile >
53     struct Difference< File< Chained<_FileSize, TFile> > >
54     {
55         typedef __int64 Type;
56     };
57
58     template < __int64 _FileSize, typename TFile >
59     struct aRequest< File< Chained<_FileSize, TFile> > >
60     {
61                 typedef typename aRequest<TFile>::Type Type;
62     };
63
64
65     template < unsigned _FileCount, typename TFile >
66     struct Size< File< Striped<_FileCount, TFile> > >
67     {
68         typedef __int64 Type;
69     };
70
71     template < unsigned _FileCount, typename TFile >
72     struct Position< File< Striped<_FileCount, TFile> > >
73     {
74         typedef __int64 Type;
75     };
76
77     template < unsigned _FileCount, typename TFile >
78     struct Difference< File< Striped<_FileCount, TFile> > >
79     {
80         typedef __int64 Type;
81     };
82
83     template < unsigned _FileCount, typename TFile >
84     struct aRequest< File< Striped<_FileCount, TFile> > >
85     {
86                 typedef typename aRequest<TFile>::Type Type;
87     };
88
89
90         template < unsigned _FileCount, typename TFile >
91         class File< Striped<_FileCount, TFile> >: public Tuple< TFile, _FileCount > {
92                 File(void *dummy = NULL) {}     // to be compatible with the FILE*(NULL) constructor
93                 operator bool() const { return (*this)[0]; }
94         };
95
96     template < __int64 _FileSize, typename TFile >
97         class File< Chained<_FileSize, TFile> >: public String< TFile > {
98                 typedef String< TFile > Base;
99
100                 ::std::string   baseName;
101                 int                             openMode;
102                 __int64                 fileSize;
103                 bool                    temporary;
104
105                 File(void *dummy = NULL) :      // to be compatible with the FILE*(NULL) constructor
106                         fileSize(0),
107                         _realign(false) {}
108
109         private:
110                 
111                 bool _realign;
112         
113                 template < typename TSize, typename TValue >
114                 inline void _alignFloor(TSize _size, TValue const *) {
115                         __int64 alignment = sizeof(TValue) * sectorSize(TFile());
116                         fileSize = (_size / alignment) * alignment;
117                 }
118
119                 template < typename TSize, typename TValue >
120                 inline void _alignCeil(TSize _size, TValue const *) {
121                         __int64 alignment = sizeof(TValue) * sectorSize(TFile());
122                         fileSize = ((_size + alignment - 1) / alignment) * alignment;
123                 }
124
125         public:
126         
127                 inline ::std::string getFileName(int i) const { 
128                         ::std::stringstream strm;
129                         strm << baseName << '.' << ::std::setfill('0') << ::std::setw(3) << i;
130                         return strm.str();
131                 }
132
133                 inline operator bool() const { 
134                         return (*this)[0]; 
135                 }
136
137                 inline unsigned fileCount() const {
138                         return length(*(Base*)this);
139                 }
140
141                 inline TFile& getFile(int fileNo) {
142                         unsigned _oldFileCount = fileCount();
143                         if (fileNo >= _oldFileCount) {
144                                 resize(*(Base*)this, fileNo + 1);
145                                 for(unsigned i = _oldFileCount; i <= fileNo; ++i)
146                                         if (temporary)
147                                                 openTemp((*this)[i], openMode);
148                                         else
149                                                 open((*this)[i], getFileName(i).c_str(), openMode);
150                         }
151                         return (*this)[fileNo];
152                 }
153
154                 inline void tryOpen() {
155                         unsigned fileCount = 0;
156                         while (fileExists(getFileName(fileCount).c_str())) ++fileCount;
157                         if (fileCount) {
158                                 fileSize = size(getFile(0));
159                                 _realign = (fileCount == 1);
160                                 getFile(fileCount - 1);
161                         } 
162                 }
163
164                 // fileSize dependent functions
165
166                 template < typename TValue >
167                 inline void adjustFileSize(TValue const *dummy) {
168                         if (_realign) {
169                                 _alignCeil(fileSize, dummy);
170                                 _realign = false;
171                                 if (fileSize < _FileSize)
172                                         fileSize = 0;
173                         }
174                         if (!fileSize) 
175                                 _alignFloor(_FileSize, dummy);
176                 }
177
178                 template < typename TPos, typename TOffset, typename TValue >
179                 inline TFile& getFileAndOffset(TPos offset, TOffset &fileOffset, TValue const *dummy) {
180                         adjustFileSize(dummy);
181                         offset *= sizeof(TValue);
182                         fileOffset = (offset % fileSize) / sizeof(TValue);
183                         return getFile(offset / fileSize);
184                 }
185
186                 template < typename TOffset, typename TValue >
187                 inline __int64 restAt(TOffset fileOffset, TValue const *dummy) {
188                         adjustFileSize(dummy);
189                         __int64 restBytes = fileSize;
190                         restBytes -= fileOffset * sizeof(TValue);
191                         return restBytes / sizeof(TValue);
192                 }
193
194                 inline void resizeArray(__int64 _newSize) {
195                         if (fileSize) {
196                                 unsigned _oldFileCount = fileCount();
197                                 unsigned _newFileCount = enclosingBlocks(_newSize, fileSize);
198                                 for(unsigned i = _newFileCount; i < _oldFileCount; ++i) {
199                                         close((*this)[i]);
200                                         if (!temporary) fileUnlink(getFileName(i).c_str());
201                                 }
202                                 resize(*(Base*)this, _newFileCount);
203                                 if (_newFileCount) {
204                                         typename Size<TFile>::Type lastFileSize = _newSize % fileSize;
205                                         if (fileSize) resize((*this)[_newFileCount - 1], lastFileSize);
206                                 }
207                         }
208                 }
209
210         inline void clearInternals() {
211                         clear(*(Base*)this);
212             fileSize = 0;
213             _realign = false;
214                 }
215         };
216
217
218     //////////////////////////////////////////////////////////////////////////////
219     // generic open/close interface
220     template < typename TFileArray >
221     inline bool _openTempFArray(TFileArray &me, int openMode) {
222                 bool result = true;
223                 for(int i = 0; i < length(me); ++i)
224                         result &= openTemp(me[i], openMode);
225                 return result;
226     }
227
228     template < typename TFileArray >
229     inline bool _openTempFArray(TFileArray &me) {
230                 return _openTempFArray(me, DefaultOpenTempMode<TFileArray>::VALUE);
231         }
232
233     template < typename TFileArray >
234     inline bool _reopenFArray(TFileArray &me, int openMode) {
235                 bool result = true;
236                 for(int i = 0; i < length(me); ++i)
237                         result &= reopen(me[i], openMode);
238                 return result;
239     }
240
241     template < typename TFileArray >
242     inline bool _closeFArray(TFileArray &me) {
243                 bool result = true;
244                 for(int i = 0; i < length(me); ++i)
245                         if (me[i]) result &= close(me[i]);
246                 return result;
247     }
248
249     template < typename TFileArray >
250     inline unsigned _sectorSizeFArray(TFileArray &me, int openMode) {
251                 return sectorSize(me[0]);
252     }
253
254     template < typename TFileArray >
255     inline typename Size<TFileArray>::Type
256         _sizeFArray(TFileArray &me) {
257         typename Size<TFileArray>::Type sum = 0;
258                 for(int i = 0; i < length(me); ++i)
259                         sum += size(me[i]);
260                 return sum;
261     }
262
263     template < typename TFileArray >
264     inline bool _flushFArray(TFileArray &me) {
265                 bool result = true;
266                 for(int i = 0; i < length(me); ++i)
267                         result &= flush(me[i]);
268                 return result;
269     }
270
271     template < typename TFileArray, typename TRequest >
272     inline bool _cancelFArray(TFileArray &me, TRequest &request) {
273                 bool result = true;
274                 for(int i = 0; i < length(me); ++i)
275                         result &= cancel(me[i], &request);
276                 return result;
277     }
278
279
280     //////////////////////////////////////////////////////////////////////////////
281     // standard file array wrappers
282
283     template < __int64 _FileSize, typename TFile >
284         inline unsigned length(File< Chained<_FileSize, TFile> > const &me) {
285                 return me.fileCount();
286         }
287
288     template < unsigned _FileCount, typename TFile >
289         inline unsigned length(File< Striped<_FileCount, TFile> > const &me) {
290                 return _FileCount;
291         }
292
293     template < __int64 _FileSize, typename TFile >
294         inline bool open(File< Chained<_FileSize, TFile> > &me, const char *fileName, int openMode) {
295                 me.baseName = fileName;
296                 me.openMode = openMode;
297                 me.temporary = false;
298                 me.tryOpen();
299                 return true;
300         }
301
302     template < __int64 _FileSize, typename TFile >
303         inline bool openTemp(File< Chained<_FileSize, TFile> > &me, int openMode) {
304                 me.openMode = openMode;
305                 me.temporary = true;
306                 return true;
307         }
308
309     template < unsigned _FileCount, typename TFile >
310         inline bool openTemp(File< Striped<_FileCount, TFile> > &me, int openMode) {
311                 return _openTempFArray(me, openMode);
312         }
313
314     template < __int64 _FileSize, typename TFile >
315         inline bool close(File< Chained<_FileSize, TFile> > &me) {
316         _closeFArray(me);
317         me.clearInternals();
318         return true;
319     }
320
321     template < unsigned _FileCount, typename TFile >
322         inline bool close(File< Striped<_FileCount, TFile> > &me) {     return _closeFArray(me); }
323
324     template < __int64 _FileSize, typename TFile >
325         __int64 size(File< Chained<_FileSize, TFile> > &me) {
326                 return _sizeFArray(me);
327         }
328
329     template < unsigned _FileCount, typename TFile >
330         __int64 size(File< Striped<_FileCount, TFile> > &me) {
331                 return _sizeFArray(me);
332         }
333
334     template < __int64 _FileSize, typename TFile, typename TSize >
335     inline void resize(File< Chained<_FileSize, TFile> > &me, TSize new_length) {
336                 me.resizeArray(new_length);
337     }
338
339     template < __int64 _FileSize, typename TFile, typename TValue, typename TSize >
340         inline void allocate(File< Chained<_FileSize, TFile> > const &me, TValue* &data, TSize count) {
341                 allocate(me[0], data, count);
342         }
343
344     template < __int64 _FileSize, typename TFile, typename TValue, typename TSize >
345         inline void deallocate(File< Chained<_FileSize, TFile> > const &me, TValue* &data, TSize count) {
346                 deallocate(me[0], data, count);
347         }
348
349     template < unsigned _FileCount, typename TFile, typename TValue, typename TSize >
350         inline void allocate(File< Striped<_FileCount, TFile> > const &me, TValue* &data, TSize count) {
351                 allocate(me[0], data, count);
352         }
353
354     template < unsigned _FileCount, typename TFile, typename TValue, typename TSize >
355         inline void deallocate(File< Striped<_FileCount, TFile> > const &me, TValue* &data, TSize count) {
356                 deallocate(me[0], data, count);
357         }
358
359
360     //////////////////////////////////////////////////////////////////////////////
361     // read/write wrappers
362
363     template < __int64 _FileSize, typename TFile, typename TValue, typename TSize, typename TOffset >
364     inline bool readAt(File< Chained<_FileSize, TFile> > &me, TValue *memPtr, TSize count, TOffset offset) {
365                 TOffset fileOfs = 0;
366                 while (count) {
367                         TFile &file = me.getFileAndOffset(offset, fileOfs, memPtr);
368                         TSize xmitSize = _min(me.restAt(fileOfs, memPtr), (__int64)count);
369                         if (!readAt(file, memPtr, xmitSize, fileOfs)) return false;
370                         count -= xmitSize;
371                         offset += xmitSize;
372                         memPtr += xmitSize;
373                 }
374                 return true;
375     }
376     
377     template < __int64 _FileSize, typename TFile, typename TValue, typename TSize, typename TOffset >
378     inline bool writeAt(File< Chained<_FileSize, TFile> > &me, TValue const *memPtr, TSize count, TOffset offset) {
379                 TOffset fileOfs = 0;
380                 while (count) {
381                         TFile &file = me.getFileAndOffset(offset, fileOfs, memPtr);
382                         TSize xmitSize = _min(me.restAt(fileOfs, memPtr), (__int64)count);
383                         if (!writeAt(file, memPtr, xmitSize, fileOfs)) return false;
384                         count -= xmitSize;
385                         offset += xmitSize;
386                         memPtr += xmitSize;
387                 }
388                 return true;
389     }
390
391     template < __int64 _FileSize, typename TFile, typename TValue, typename TSize, typename TOffset, typename TRequest >
392     inline bool areadAt(File< Chained<_FileSize, TFile> > &me, TValue *memPtr, TSize count, TOffset offset, TRequest &req) {
393                 TOffset fileOfs = 0;
394                 while (count) {
395                         TFile &file = me.getFileAndOffset(offset, fileOfs, memPtr);
396                         TSize xmitSize = _min(me.restAt(fileOfs, memPtr), (__int64)count);
397                         if (count != xmitSize) {
398                                 if (!readAt(file, memPtr, xmitSize, fileOfs)) return false;
399                         } else
400                                 if (!areadAt(file, memPtr, xmitSize, fileOfs, req)) return false;
401                         count -= xmitSize;
402                         offset += xmitSize;
403                         memPtr += xmitSize;
404                 }
405                 return true;
406     }
407     
408     template < __int64 _FileSize, typename TFile, typename TValue, typename TSize, typename TOffset, typename TRequest  >
409     inline bool awriteAt(File< Chained<_FileSize, TFile> > &me, TValue const *memPtr, TSize count, TOffset offset, TRequest &req) {
410                 TOffset fileOfs = 0;
411                 while (count) {
412                         TFile &file = me.getFileAndOffset(offset, fileOfs, memPtr);
413                         TSize xmitSize = _min(me.restAt(fileOfs, memPtr), (__int64)count);
414                         if (count != xmitSize) {
415                                 if (!writeAt(file, memPtr, xmitSize, fileOfs)) return false;
416                         } else
417                                 if (!awriteAt(file, memPtr, xmitSize, fileOfs, req)) return false;
418                         count -= xmitSize;
419                         offset += xmitSize;
420                         memPtr += xmitSize;
421                 }
422                 return true;
423     }
424
425 }
426
427 #endif