summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/clucene/src/CLucene/store/MMapInput.cpp
blob: d660032c61bbcd3e6df650f3fb0405b20abb0201 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/*------------------------------------------------------------------------------
* Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team
* 
* Distributable under the terms of either the Apache License (Version 2.0) or 
* the GNU Lesser General Public License, as specified in the COPYING file.
------------------------------------------------------------------------------*/
#include "CLucene/StdHeader.h"
#if defined(LUCENE_FS_MMAP)

#include "FSDirectory.h"
#include "CLucene/util/Misc.h"
#include "CLucene/debug/condition.h"

#ifndef _CLCOMPILER_MSVC
	#include <sys/mman.h>
#endif

CL_NS_DEF(store)
CL_NS_USE(util)

	FSDirectory::MMapIndexInput::MMapIndexInput(const char* path):
		pos(0),
		data(NULL),
		_length(0),
		isClone(false)
	{
	//Func - Constructor.
	//       Opens the file named path
	//Pre  - path != NULL
	//Post - if the file could not be opened  an exception is thrown.

	  CND_PRECONDITION(path != NULL, "path is NULL");

#ifdef _CLCOMPILER_MSVC
	  mmaphandle = NULL;
	  fhandle = CreateFileA(path,GENERIC_READ,FILE_SHARE_READ, 0,OPEN_EXISTING,0,0);
	  
	  //Check if a valid fhandle was retrieved
	  if (fhandle < 0){
		DWORD err = GetLastError();
        if ( err == ERROR_FILE_NOT_FOUND )
		    _CLTHROWA(CL_ERR_IO, "File does not exist");
        else if ( err == EACCES )
            _CLTHROWA(ERROR_ACCESS_DENIED, "File Access denied");
        else if ( err == ERROR_TOO_MANY_OPEN_FILES )
            _CLTHROWA(CL_ERR_IO, "Too many open files");
		else
			_CLTHROWA(CL_ERR_IO, "File IO Error");
	  }

	  DWORD dummy=0;
	  _length = GetFileSize(fhandle,&dummy);

	  if ( _length > 0 ){
		mmaphandle = CreateFileMappingA(fhandle,NULL,PAGE_READONLY,0,0,NULL);
		if ( mmaphandle != NULL ){
			void* address = MapViewOfFile(mmaphandle,FILE_MAP_READ,0,0,0);
			if ( address != NULL ){
				data = (uint8_t*)address;
				return; //SUCCESS!
			}
		}
		CloseHandle(mmaphandle);

		char* lpMsgBuf=0;
		DWORD dw = GetLastError(); 

		FormatMessageA(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM,
			NULL,
			dw,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			lpMsgBuf,
			0, NULL );

		char* errstr = _CL_NEWARRAY(char, strlen(lpMsgBuf)+40); 
		sprintf(errstr, "MMapIndexInput::MMapIndexInput failed with error %d: %s", dw, lpMsgBuf); 
		LocalFree(lpMsgBuf);
	    
		_CLTHROWA_DEL(CL_ERR_IO,errstr);
	  }

#else //_CLCOMPILER_MSVC
	 fhandle = ::open (path, O_RDONLY);
  	 if (fhandle < 0){
		_CLTHROWA(CL_ERR_IO,strerror(errno));	
  	 }else{
		// stat it
		struct stat sb;
		if (::fstat (fhandle, &sb)){
			_CLTHROWA(CL_ERR_IO,strerror(errno));
		}else{
			// get length from stat
			_length = sb.st_size;
			
			// mmap the file
			void* address = ::mmap(0, _length, PROT_READ, MAP_SHARED, fhandle, 0);
			if (address == MAP_FAILED){
				_CLTHROWA(CL_ERR_IO,strerror(errno));
			}else{
				data = (uint8_t*)address;
			}
		}
  	 }
#endif
  }

  FSDirectory::MMapIndexInput::MMapIndexInput(const MMapIndexInput& clone): IndexInput(clone){
  //Func - Constructor
  //       Uses clone for its initialization
  //Pre  - clone is a valide instance of FSIndexInput
  //Post - The instance has been created and initialized by clone
  
#ifdef _CLCOMPILER_MSVC
	  mmaphandle = NULL;
	  fhandle = NULL;
#endif

	  data = clone.data;
	  pos = clone.pos;

	  //clone the file length
	  _length  = clone._length;
	  //Keep in mind that this instance is a clone
	  isClone = true;
  }

  uint8_t FSDirectory::MMapIndexInput::readByte(){
	  return *(data+(pos++));
  }

  void FSDirectory::MMapIndexInput::readBytes(uint8_t* b, const int32_t len){
	memcpy(b, data+pos, len);
	pos+=len;
  }
  int32_t FSDirectory::MMapIndexInput::readVInt(){
	  uint8_t b = *(data+(pos++));
	  int32_t i = b & 0x7F;
	  for (int shift = 7; (b & 0x80) != 0; shift += 7) {
	    b = *(data+(pos++));
	    i |= (b & 0x7F) << shift;
	  }
	  return i;
  }
  int64_t FSDirectory::MMapIndexInput::getFilePointer() const{
	return pos;
  }
  void FSDirectory::MMapIndexInput::seek(const int64_t pos){
	  this->pos=pos;
  }

  FSDirectory::MMapIndexInput::~MMapIndexInput(){
  //Func - Destructor
  //Pre  - True
  //Post - The file for which this instance is responsible has been closed.
  //       The instance has been destroyed

	  close();
  }

  IndexInput* FSDirectory::MMapIndexInput::clone() const
  {
    return _CLNEW FSDirectory::MMapIndexInput(*this);
  }
  void FSDirectory::MMapIndexInput::close()  {
    //IndexInput::close();

	if ( !isClone ){
#ifdef _CLCOMPILER_MSVC
		if ( data != NULL ){
			if ( ! UnmapViewOfFile(data) ){
				CND_PRECONDITION( false, "UnmapViewOfFile(data) failed"); //todo: change to rich error
			}
		}

		if ( mmaphandle != NULL ){
			if ( ! CloseHandle(mmaphandle) ){
				CND_PRECONDITION( false, "CloseHandle(mmaphandle) failed");
			}
		}
		if ( fhandle != NULL ){
			if ( !CloseHandle(fhandle) ){
				CND_PRECONDITION( false, "CloseHandle(fhandle) failed");
			}
		}
		mmaphandle = NULL;
		fhandle = NULL;
#else
		if ( data != NULL )
	  		::munmap(data, _length);
	  	if ( fhandle > 0 )
	  		::close(fhandle);
	  	fhandle = 0;
#endif
	}
	data = NULL;
	pos = 0;
  }


CL_NS_END
#endif