summaryrefslogtreecommitdiff
path: root/storage/connect/maputil.cpp
blob: 903798bccdd1ccc56b0dddc5c1b9abd938bf44b9 (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
#include "my_global.h"
#ifdef UNIX
#include "osutil.h"
#include <errno.h>
#include <stddef.h>
#else /* WINDOWS */
//#include <windows.h>
#include "osutil.h"
#endif /* WINDOWS */
#include <stdlib.h>
#include <stdio.h>

#include "global.h"
#include "plgdbsem.h"
#include "maputil.h"

#ifdef _WIN32
/***********************************************************************/
/*  In Insert mode, just open the file for append. Otherwise           */
/*  create the mapping file object. The map handle can be released     */
/*  immediately because they will not be used anymore.                 */
/*  If del is true in DELETE mode, then delete the whole file.         */
/*  Returns the file handle that can be used by caller.                */
/***********************************************************************/
HANDLE CreateFileMap(PGLOBAL g, LPCSTR filename,
                     MEMMAP *mm, MODE mode, bool del)
  {
  HANDLE hFile;
  HANDLE hFileMap;
  DWORD  access, share, disposition;

  memset(mm, 0, sizeof(MEMMAP));
  *g->Message = '\0';

  switch (mode) {
    case MODE_READ:
      access = GENERIC_READ;
      share = FILE_SHARE_READ;
      disposition = OPEN_EXISTING;
      break;
    case MODE_UPDATE:
    case MODE_DELETE:
      access = GENERIC_READ | GENERIC_WRITE;
      share = 0;
      disposition = (del) ? TRUNCATE_EXISTING : OPEN_EXISTING;
      break;
    case MODE_INSERT:
      access = GENERIC_WRITE;
      share = 0;
      disposition = OPEN_ALWAYS;
      break;
    default:
      snprintf(g->Message, sizeof(g->Message), MSG(BAD_FUNC_MODE), "CreateFileMap", mode);
      return INVALID_HANDLE_VALUE;
    } // endswitch

  hFile = CreateFile(filename, access, share, NULL,  disposition,
                     FILE_ATTRIBUTE_NORMAL, NULL);
  
  if (hFile != INVALID_HANDLE_VALUE)
    if (mode != MODE_INSERT) {
      /*****************************************************************/
      /*  Create the file-mapping object.                              */
      /*****************************************************************/
      access = (mode == MODE_READ) ? PAGE_READONLY : PAGE_READWRITE;
      hFileMap = CreateFileMapping(hFile, NULL,  access, 0, 0, NULL);
      
      if (!hFileMap) {
        DWORD ler = GetLastError();
      
        if (ler && ler != 1006) {
          snprintf(g->Message, sizeof(g->Message), MSG(FILE_MAP_ERROR), filename, ler);
          CloseHandle(hFile);
          return INVALID_HANDLE_VALUE;
        } else {
          snprintf(g->Message, sizeof(g->Message), MSG(FILE_IS_EMPTY), filename);
          return hFile;
        } // endif ler
      
        } // endif hFileMap
      
      access = (mode == MODE_READ) ? FILE_MAP_READ : FILE_MAP_WRITE;

      if (!(mm->memory = MapViewOfFile(hFileMap, access, 0, 0, 0))) {
        DWORD ler = GetLastError();
      
        snprintf(g->Message, sizeof(g->Message), "Error %ld in MapViewOfFile %s",
                ler, filename);
        CloseHandle(hFile);
        return INVALID_HANDLE_VALUE;
        } // endif memory

      // lenH is the high-order word of the file size
      mm->lenL = GetFileSize(hFile, &mm->lenH);
      CloseHandle(hFileMap);                    // Not used anymore
    }  else // MODE_INSERT
      /*****************************************************************/
      /*  The starting point must be the end of file as for append.    */
      /*****************************************************************/
      SetFilePointer(hFile, 0, NULL, FILE_END);

  return hFile;  
  }  // end of CreateFileMap

bool CloseMemMap(LPVOID memory, size_t dwSize) 
  {
  return (memory) ? !UnmapViewOfFile(memory) : false;
  } // end of CloseMemMap

#else  /* UNIX */
// Code to handle Linux and Solaris
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

/***********************************************************************/
/*  In Insert mode, just open the file for append. Otherwise           */
/*  create the mapping file object. The map handle can be released     */
/*  immediately because they will not be used anymore.                 */
/*  If del is true in DELETE mode, then delete the whole file.         */
/*  Returns the file handle that can be used by caller.                */
/***********************************************************************/
HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName, 
                         MEMMAP *mm, MODE mode, bool del) 
  {
  unsigned int openMode;
  int          protmode;
  HANDLE       fd;
  size_t       filesize;
  struct stat  st; 

  memset(mm, 0, sizeof(MEMMAP));
  *g->Message = '\0';

  switch (mode) {
    case MODE_READ:
      openMode = O_RDONLY;
      protmode = PROT_READ;
      break;
    case MODE_UPDATE:
    case MODE_DELETE:
      openMode = (del) ? (O_RDWR | O_TRUNC) : O_RDWR;
      protmode = PROT_READ | PROT_WRITE;
      break;
    case MODE_INSERT:
      openMode = (O_WRONLY | O_CREAT | O_APPEND);
      protmode = PROT_WRITE;
      break;
     default:
      snprintf(g->Message, sizeof(g->Message), MSG(BAD_FUNC_MODE), "CreateFileMap", mode);
      return INVALID_HANDLE_VALUE;
   } // endswitch

  // Try to open the addressed file.
  fd= global_open(g, MSGID_NONE, fileName, openMode);

  if (fd != INVALID_HANDLE_VALUE && mode != MODE_INSERT) {
    /* We must know about the size of the file. */
    if (fstat(fd, &st)) {
      snprintf(g->Message, sizeof(g->Message), MSG(FILE_MAP_ERROR), fileName, errno);
      close(fd);
      return INVALID_HANDLE_VALUE;
      }  // endif fstat
    
    if ((filesize = st.st_size))
      // Now we are ready to load the file.  If mmap() is available we try
      //   this first.  If not available or it failed we try to load it.
      mm->memory = mmap(NULL, filesize, protmode, MAP_SHARED, fd, 0);
    else
      mm->memory = 0;

    if (mm->memory != MAP_FAILED) {
      mm->lenL = (mm->memory != 0) ? filesize : 0;
      mm->lenH = 0;
    } else {
      strcpy(g->Message, "Memory mapping failed");
      close(fd);
      return INVALID_HANDLE_VALUE;
    } // endif memory

    }  /* endif fd */
  
  // mmap() call was successful. ??????????
  return fd;
  }  // end of CreateFileMap

bool CloseMemMap(void *memory, size_t dwSize) 
  {
  if (memory) {
    // All this must be redesigned
    msync((char*)memory, dwSize, MS_SYNC);
    return (munmap((char*)memory, dwSize) < 0) ? true : false;
  } else
    return false;

  }  // end of CloseMemMap

#endif   // UNIX