1/* 2 * Copyright (C) 2013, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef LATINIME_MMAPPED_BUFFER_H 18#define LATINIME_MMAPPED_BUFFER_H 19 20#include <cerrno> 21#include <fcntl.h> 22#include <stdint.h> 23#include <sys/mman.h> 24#include <unistd.h> 25 26#include "defines.h" 27 28namespace latinime { 29 30class MmappedBuffer { 31 public: 32 static MmappedBuffer* openBuffer(const char *const path, const int bufferOffset, 33 const int bufferSize, const bool isUpdatable) { 34 const int openMode = isUpdatable ? O_RDWR : O_RDONLY; 35 const int mmapFd = open(path, openMode); 36 if (mmapFd < 0) { 37 AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno); 38 return 0; 39 } 40 const int pagesize = getpagesize(); 41 const int offset = bufferOffset % pagesize; 42 int alignedOffset = bufferOffset - offset; 43 int alignedSize = bufferSize + offset; 44 const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ; 45 void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd, 46 alignedOffset); 47 if (mmappedBuffer == MAP_FAILED) { 48 AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno); 49 close(mmapFd); 50 return 0; 51 } 52 uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset; 53 if (!buffer) { 54 AKLOGE("DICT: buffer is null"); 55 close(mmapFd); 56 return 0; 57 } 58 return new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize, mmapFd, 59 isUpdatable); 60 } 61 62 ~MmappedBuffer() { 63 int ret = munmap(mMmappedBuffer, mAlignedSize); 64 if (ret != 0) { 65 AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno); 66 } 67 ret = close(mMmapFd); 68 if (ret != 0) { 69 AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno); 70 } 71 } 72 73 AK_FORCE_INLINE uint8_t *getBuffer() const { 74 return mBuffer; 75 } 76 77 AK_FORCE_INLINE int getBufferSize() const { 78 return mBufferSize; 79 } 80 81 AK_FORCE_INLINE bool isUpdatable() const { 82 return mIsUpdatable; 83 } 84 85 private: 86 AK_FORCE_INLINE MmappedBuffer(uint8_t *const buffer, const int bufferSize, 87 void *const mmappedBuffer, const int alignedSize, const int mmapFd, 88 const bool isUpdatable) 89 : mBuffer(buffer), mBufferSize(bufferSize), mMmappedBuffer(mmappedBuffer), 90 mAlignedSize(alignedSize), mMmapFd(mmapFd), mIsUpdatable(isUpdatable) {} 91 92 DISALLOW_IMPLICIT_CONSTRUCTORS(MmappedBuffer); 93 94 uint8_t *const mBuffer; 95 const int mBufferSize; 96 void *const mMmappedBuffer; 97 const int mAlignedSize; 98 const int mMmapFd; 99 const bool mIsUpdatable; 100}; 101} 102#endif /* LATINIME_MMAPPED_BUFFER_H */ 103