Home | History | Annotate | Download | only in lib
      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 (at) 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 
     30 MappedFile::MappedFile(const MemoryRegion &region) : region_(region) { }
     31 
     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 
     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 
     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 
     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