• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 //
14 // Copyright 2005-2010 Google, Inc.
15 // Author: sorenj@google.com (Jeffrey Sorensen)
16 
17 #include <fst/mapped-file.h>
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 
22 namespace fst {
23 
24 // Alignment required for mapping structures (in bytes.)  Regions of memory
25 // that are not aligned upon a 128 bit boundary will be read from the file
26 // instead.  This is consistent with the alignment boundary set in the
27 // const and compact fst code.
28 const int MappedFile::kArchAlignment = 16;
29 
MappedFile(const MemoryRegion & region)30 MappedFile::MappedFile(const MemoryRegion &region) : region_(region) { }
31 
~MappedFile()32 MappedFile::~MappedFile() {
33   if (region_.size != 0) {
34     if (region_.mmap != NULL) {
35       VLOG(1) << "munmap'ed " << region_.size << " bytes at " << region_.mmap;
36       if (munmap(region_.mmap, region_.size) != 0) {
37         LOG(ERROR) << "failed to unmap region: "<< strerror(errno);
38       }
39     } else {
40       operator delete(region_.data);
41     }
42   }
43 }
44 
Allocate(size_t size)45 MappedFile* MappedFile::Allocate(size_t size) {
46   MemoryRegion region;
47   region.data = size == 0 ? NULL : operator new(size);
48   region.mmap = NULL;
49   region.size = size;
50   return new MappedFile(region);
51 }
52 
Borrow(void * data)53 MappedFile* MappedFile::Borrow(void *data) {
54   MemoryRegion region;
55   region.data = data;
56   region.mmap = data;
57   region.size = 0;
58   return new MappedFile(region);
59 }
60 
Map(istream * s,const FstReadOptions & opts,size_t size)61 MappedFile* MappedFile::Map(istream* s, const FstReadOptions &opts,
62                             size_t size) {
63   std::streampos spos = s->tellg();
64   if (opts.mode == FstReadOptions::MAP && spos >= 0 &&
65       spos % kArchAlignment == 0) {
66     size_t pos = spos;
67     int fd = open(opts.source.c_str(), O_RDONLY);
68     if (fd != -1) {
69       int pagesize = getpagesize();
70       off_t offset = pos % pagesize;
71       off_t upsize = size + offset;
72       void *map = mmap(0, upsize, PROT_READ, MAP_SHARED, fd, pos - offset);
73       char *data = reinterpret_cast<char*>(map);
74       if (close(fd) == 0 && map != MAP_FAILED) {
75         MemoryRegion region;
76         region.mmap = map;
77         region.size = upsize;
78         region.data = reinterpret_cast<void*>(data + offset);
79         MappedFile *mmf = new MappedFile(region);
80         s->seekg(pos + size, ios::beg);
81         if (s) {
82           VLOG(1) << "mmap'ed region of " << size << " at offset " << pos
83                   << " from " << opts.source.c_str() << " to addr " << map;
84           return mmf;
85         }
86         delete mmf;
87       } else {
88         LOG(INFO) << "Mapping of file failed: " << strerror(errno);
89       }
90     }
91   }
92   // If all else fails resort to reading from file into allocated buffer.
93   if (opts.mode != FstReadOptions::READ) {
94     LOG(WARNING) << "File mapping at offset " << spos << " of file "
95                  << opts.source << " could not be honored, reading instead.";
96   }
97   MappedFile* mf = Allocate(size);
98   if (!s->read(reinterpret_cast<char*>(mf->mutable_data()), size)) {
99     delete mf;
100     return NULL;
101   }
102   return mf;
103 }
104 
105 }  // namespace fst
106