1/********************************************************************
2 * Copyright (c) 2013 - 2014, Pivotal Inc.
3 * All rights reserved.
4 *
5 * Author: Zhanwei Wang
6 ********************************************************************/
7/********************************************************************
8 * 2014 -
9 * open source under Apache License Version 2.0
10 ********************************************************************/
11/**
12 * Licensed to the Apache Software Foundation (ASF) under one
13 * or more contributor license agreements. See the NOTICE file
14 * distributed with this work for additional information
15 * regarding copyright ownership. The ASF licenses this file
16 * to you under the Apache License, Version 2.0 (the
17 * "License"); you may not use this file except in compliance
18 * with the License. You may obtain a copy of the License at
19 *
20 * http://www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an "AS IS" BASIS,
24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28#include <errno.h>
29#include <fcntl.h>
30#include <sys/mman.h>
31#include <sys/stat.h>
32#include <sys/types.h>
33
34#include <limits>
35#include <string>
36#include <sstream>
37#include <limits>
38
39#include "Exception.h"
40#include "ExceptionInternal.h"
41#include "FileWrapper.h"
42
43namespace Hdfs {
44namespace Internal {
45
46MappedFileWrapper::MappedFileWrapper() :
47 delegate(true), begin(NULL), position(NULL), fd(-1), size(0) {
48}
49
50MappedFileWrapper::~MappedFileWrapper() {
51 close();
52}
53
54bool MappedFileWrapper::openInternal(int fd, bool delegate, size_t size) {
55 this->delegate = delegate;
56#ifdef MAP_NOCACHE
57 void * retval = mmap(NULL, size, PROT_READ, MAP_FILE | MAP_PRIVATE | MAP_NOCACHE, fd, 0);
58#else
59 void * retval = mmap(NULL, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
60#endif
61 begin = position = static_cast<const char *>(retval);
62
63 if (MAP_FAILED == retval) {
64 begin = position = NULL;
65 close();
66 return false;
67 }
68
69 if (posix_madvise(const_cast<char *>(begin), size, POSIX_MADV_SEQUENTIAL)) {
70 close();
71 return false;
72 }
73
74 return true;
75}
76
77bool MappedFileWrapper::open(int fd, bool delegate) {
78 size = lseek(fd, 0, SEEK_END);
79 lseek(fd, 0, SEEK_SET);
80 std::stringstream ss;
81 ss.imbue(std::locale::classic());
82 ss << "FileDescriptor " << fd;
83 path = ss.str();
84
85 if (static_cast<uint64_t>(size) > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) {
86 THROW(HdfsIOException,
87 "Cannot create memory mapped file for \"%s\", file is too large.",
88 path.c_str());
89 }
90
91 return openInternal(fd, delegate, static_cast<size_t>(size));
92}
93
94bool MappedFileWrapper::open(const std::string & path) {
95 struct stat st;
96
97 if (stat(path.c_str(), &st)) {
98 return false;
99 }
100
101 size = st.st_size;
102
103 if (static_cast<uint64_t>(size) > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) {
104 THROW(HdfsIOException,
105 "Cannot create memory mapped file for \"%s\", file is too large.",
106 path.c_str());
107 }
108
109 fd = ::open(path.c_str(), O_RDONLY);
110
111 if (fd < 0) {
112 return false;
113 }
114
115 this->path = path;
116 return openInternal(fd, true, st.st_size);
117}
118
119void MappedFileWrapper::close() {
120 if (NULL != begin) {
121 ::munmap(const_cast<char *>(begin), static_cast<size_t>(size));
122 begin = position = NULL;
123 }
124
125 if (fd >= 0 && delegate) {
126 ::close(fd);
127 }
128
129 fd = -1;
130 size = 0;
131 delegate = true;
132 path.clear();
133}
134
135const char * MappedFileWrapper::read(std::vector<char> & buffer, int32_t size) {
136 assert(NULL != begin && NULL != position);
137 const char * retval = position;
138 position += size;
139 return retval;
140}
141
142void MappedFileWrapper::copy(char * buffer, int32_t size) {
143 assert(NULL != begin && NULL != position);
144 memcpy(buffer, position, size);
145 position += size;
146}
147
148void MappedFileWrapper::seek(int64_t offset) {
149 assert(NULL != begin && NULL != position);
150 position = begin + offset;
151}
152
153}
154}
155