MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PosixAsyncFile.cpp
1 /*
2  Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 #include <my_sys.h>
20 #include <my_pthread.h>
21 
22 #ifdef HAVE_XFS_XFS_H
23 #include <xfs/xfs.h>
24 #endif
25 
26 #include "Ndbfs.hpp"
27 #include "AsyncFile.hpp"
28 #include "PosixAsyncFile.hpp"
29 
30 #include <ErrorHandlingMacros.hpp>
31 #include <kernel_types.h>
32 #include <ndbd_malloc.hpp>
33 #include <NdbThread.h>
34 #include <signaldata/FsRef.hpp>
35 #include <signaldata/FsOpenReq.hpp>
36 #include <signaldata/FsReadWriteReq.hpp>
37 
38 #include <NdbTick.h>
39 
40 // For readv and writev
41 #include <sys/uio.h>
42 #include <dirent.h>
43 
44 PosixAsyncFile::PosixAsyncFile(SimulatedBlock& fs) :
45  AsyncFile(fs),
46  theFd(-1),
47  use_gz(0)
48 {
49  memset(&nzf,0,sizeof(nzf));
50  init_mutex();
51 }
52 
53 int PosixAsyncFile::init()
54 {
55  /*
56  Preallocate read and write buffers for ndbzio to workaround
57  default behaviour of alloc/free at open/close
58  */
59  const size_t read_size = ndbz_bufsize_read();
60  const size_t write_size = ndbz_bufsize_write();
61 
62  nzfBufferUnaligned= ndbd_malloc(read_size + write_size +
63  NDB_O_DIRECT_WRITE_ALIGNMENT-1);
64  nzf.inbuf= (Byte*)(((UintPtr)nzfBufferUnaligned
65  + NDB_O_DIRECT_WRITE_ALIGNMENT - 1) &
66  ~(UintPtr)(NDB_O_DIRECT_WRITE_ALIGNMENT - 1));
67  nzf.outbuf= nzf.inbuf + read_size;
68 
69  /* Preallocate inflate/deflate buffers for ndbzio */
70  nz_mempool.size = nz_mempool.mfree =
71  ndbz_inflate_mem_size() + ndbz_deflate_mem_size();
72 
73  ndbout_c("NDBFS/AsyncFile: Allocating %u for In/Deflate buffer",
74  (unsigned int)nz_mempool.size);
75  nz_mempool.mem = (char*) ndbd_malloc(nz_mempool.size);
76 
77  nzf.stream.opaque= &nz_mempool;
78 
79  return 0;
80 }
81 
82 #ifdef O_DIRECT
83 static char g_odirect_readbuf[2*GLOBAL_PAGE_SIZE -1];
84 #endif
85 
86 int PosixAsyncFile::check_odirect_write(Uint32 flags, int& new_flags, int mode)
87 {
88  assert(new_flags & (O_CREAT | O_TRUNC));
89 #ifdef O_DIRECT
90  int ret;
91  char * bufptr = (char*)((UintPtr(g_odirect_readbuf)+(GLOBAL_PAGE_SIZE - 1)) & ~(GLOBAL_PAGE_SIZE - 1));
92  while (((ret = ::write(theFd, bufptr, GLOBAL_PAGE_SIZE)) == -1) &&
93  (errno == EINTR)) {};
94  if (ret == -1)
95  {
96  new_flags &= ~O_DIRECT;
97  ndbout_c("%s Failed to write using O_DIRECT, disabling",
98  theFileName.c_str());
99  }
100 
101  close(theFd);
105  theFd = ::open(theFileName.c_str(), new_flags | O_TRUNC, mode);
106  if (theFd == -1)
107  return errno;
108 #endif
109 
110  return 0;
111 }
112 
113 int PosixAsyncFile::check_odirect_read(Uint32 flags, int &new_flags, int mode)
114 {
115 #ifdef O_DIRECT
116  int ret;
117  char * bufptr = (char*)((UintPtr(g_odirect_readbuf)+(GLOBAL_PAGE_SIZE - 1)) & ~(GLOBAL_PAGE_SIZE - 1));
118  while (((ret = ::read(theFd, bufptr, GLOBAL_PAGE_SIZE)) == -1) &&
119  (errno == EINTR)) {};
120  if (ret == -1)
121  {
122  ndbout_c("%s Failed to read using O_DIRECT, disabling",
123  theFileName.c_str());
124  goto reopen;
125  }
126 
127  if(lseek(theFd, 0, SEEK_SET) != 0)
128  {
129  return errno;
130  }
131 
132  if ((flags & FsOpenReq::OM_CHECK_SIZE) == 0)
133  {
134  struct stat buf;
135  if ((fstat(theFd, &buf) == -1))
136  {
137  return errno;
138  }
139  else if ((buf.st_size % GLOBAL_PAGE_SIZE) != 0)
140  {
141  ndbout_c("%s filesize not a multiple of %d, disabling O_DIRECT",
142  theFileName.c_str(), GLOBAL_PAGE_SIZE);
143  goto reopen;
144  }
145  }
146 
147  return 0;
148 
149 reopen:
150  close(theFd);
151  new_flags &= ~O_DIRECT;
152  theFd = ::open(theFileName.c_str(), new_flags, mode);
153  if (theFd == -1)
154  return errno;
155 #endif
156  return 0;
157 }
158 
160 {
161  m_auto_sync_freq = 0;
162  m_write_wo_sync = 0;
163  m_open_flags = request->par.open.flags;
164 
165  // for open.flags, see signal FSOPENREQ
166  Uint32 flags = request->par.open.flags;
167  int new_flags = 0;
168 
169  // Convert file open flags from Solaris to Liux
170  if (flags & FsOpenReq::OM_CREATE)
171  {
172  new_flags |= O_CREAT;
173  }
174 
175  if (flags & FsOpenReq::OM_TRUNCATE){
176  new_flags |= O_TRUNC;
177  }
178 
179  if (flags & FsOpenReq::OM_AUTOSYNC)
180  {
181  m_auto_sync_freq = request->par.open.auto_sync_size;
182  }
183 
184  if (flags & FsOpenReq::OM_APPEND){
185  new_flags |= O_APPEND;
186  }
187 
188 #ifdef O_DIRECT
189  if (flags & FsOpenReq::OM_DIRECT)
190  {
191  new_flags |= O_DIRECT;
192  }
193 #endif
194 
195  if ((flags & FsOpenReq::OM_SYNC) && ! (flags & FsOpenReq::OM_INIT))
196  {
197 #ifdef O_SYNC
198  new_flags |= O_SYNC;
199 #endif
200  }
201 
202  const char * rw = "";
203  switch(flags & 0x3){
204  case FsOpenReq::OM_READONLY:
205  rw = "r";
206  new_flags |= O_RDONLY;
207  break;
208  case FsOpenReq::OM_WRITEONLY:
209  rw = "w";
210  new_flags |= O_WRONLY;
211  break;
212  case FsOpenReq::OM_READWRITE:
213  rw = "rw";
214  new_flags |= O_RDWR;
215  break;
216  default:
217  request->error = 1000;
218  break;
219  return;
220  }
221  if (flags & FsOpenReq::OM_GZ)
222  {
223  use_gz = 1;
224  }
225  else
226  {
227  use_gz = 0;
228  }
229 
230  // allow for user to choose any permissionsa with umask
231  const int mode = S_IRUSR | S_IWUSR |
232  S_IRGRP | S_IWGRP |
233  S_IROTH | S_IWOTH;
234  if (flags & FsOpenReq::OM_CREATE_IF_NONE)
235  {
236  Uint32 tmp_flags = new_flags;
237 #ifdef O_DIRECT
238  tmp_flags &= ~O_DIRECT;
239 #endif
240  if ((theFd = ::open(theFileName.c_str(), tmp_flags, mode)) != -1)
241  {
242  close(theFd);
243  request->error = FsRef::fsErrFileExists;
244  return;
245  }
246  new_flags |= O_CREAT;
247  flags |= FsOpenReq::OM_CREATE;
248  }
249 
250 no_odirect:
251  theFd = ::open(theFileName.c_str(), new_flags, mode);
252  if (-1 == theFd)
253  {
254  PRINT_ERRORANDFLAGS(new_flags);
255  if ((errno == ENOENT) && (new_flags & O_CREAT))
256  {
257  createDirectories();
258  theFd = ::open(theFileName.c_str(), new_flags, mode);
259  if (-1 == theFd)
260  {
261 #ifdef O_DIRECT
262  if (new_flags & O_DIRECT)
263  {
264  new_flags &= ~O_DIRECT;
265  goto no_odirect;
266  }
267 #endif
268  PRINT_ERRORANDFLAGS(new_flags);
269  request->error = errno;
270  return;
271  }
272  }
273 #ifdef O_DIRECT
274  else if (new_flags & O_DIRECT)
275  {
276  new_flags &= ~O_DIRECT;
277  goto no_odirect;
278  }
279 #endif
280  else
281  {
282  request->error = errno;
283  return;
284  }
285  }
286 
287  if (flags & FsOpenReq::OM_CHECK_SIZE)
288  {
289  struct stat buf;
290  if ((fstat(theFd, &buf) == -1))
291  {
292  request->error = errno;
293  }
294  else if((Uint64)buf.st_size != request->par.open.file_size)
295  {
296  request->error = FsRef::fsErrInvalidFileSize;
297  }
298  if (request->error)
299  return;
300  }
301 
302  if (flags & FsOpenReq::OM_INIT)
303  {
304  off_t off = 0;
305  const off_t sz = request->par.open.file_size;
306  SignalT<25> tmp;
307  Signal * signal = new (&tmp) Signal(0);
308  bzero(signal, sizeof(tmp));
309  FsReadWriteReq* req = (FsReadWriteReq*)signal->getDataPtrSend();
310 
311  Uint32 index = 0;
312  Uint32 block = refToMain(request->theUserReference);
313  Uint32 instance = refToInstance(request->theUserReference);
314 
315 #ifdef HAVE_XFS_XFS_H
316  if(platform_test_xfs_fd(theFd))
317  {
318  ndbout_c("Using xfsctl(XFS_IOC_RESVSP64) to allocate disk space");
319  xfs_flock64_t fl;
320  fl.l_whence= 0;
321  fl.l_start= 0;
322  fl.l_len= (off64_t)sz;
323  if(xfsctl(NULL, theFd, XFS_IOC_RESVSP64, &fl) < 0)
324  ndbout_c("failed to optimally allocate disk space");
325  }
326 #endif
327 #ifdef HAVE_POSIX_FALLOCATE
328  posix_fallocate(theFd, 0, sz);
329 #endif
330 
331 #ifdef VM_TRACE
332 #define TRACE_INIT
333 #endif
334 
335 #ifdef TRACE_INIT
336  Uint32 write_cnt = 0;
337  Uint64 start = NdbTick_CurrentMillisecond();
338 #endif
339  while(off < sz)
340  {
341  off_t size = 0;
342  Uint32 cnt = 0;
343  while (cnt < m_page_cnt && (off + size) < sz)
344  {
345  req->filePointer = 0; // DATA 0
346  req->userPointer = request->theUserPointer; // DATA 2
347  req->numberOfPages = 1; // DATA 5
348  req->varIndex = index++;
349  req->data.pageData[0] = m_page_ptr.i + cnt;
350 
351  m_fs.EXECUTE_DIRECT(block, GSN_FSWRITEREQ, signal,
352  FsReadWriteReq::FixedLength + 1,
353  instance);
354 
355  cnt++;
356  size += request->par.open.page_size;
357  }
358  retry:
359  off_t save_size = size;
360  char* buf = (char*)m_page_ptr.p;
361  while(size > 0)
362  {
363 #ifdef TRACE_INIT
364  write_cnt++;
365 #endif
366  int n;
367  if(use_gz)
368  n= ndbzwrite(&nzf, buf, size);
369  else
370  n= write(theFd, buf, size);
371  if(n == -1 && errno == EINTR)
372  {
373  continue;
374  }
375  if(n == -1 || n == 0)
376  {
377  ndbout_c("ndbzwrite|write returned %d: errno: %d my_errno: %d",n,errno,my_errno);
378  break;
379  }
380  size -= n;
381  buf += n;
382  }
383  if(size != 0)
384  {
385  int err = errno;
386 #ifdef O_DIRECT
387  if ((new_flags & O_DIRECT) && off == 0)
388  {
389  ndbout_c("error on first write(%d), disable O_DIRECT", err);
390  new_flags &= ~O_DIRECT;
391  close(theFd);
392  theFd = ::open(theFileName.c_str(), new_flags, mode);
393  if (theFd != -1)
394  goto retry;
395  }
396 #endif
397  close(theFd);
398  unlink(theFileName.c_str());
399  request->error = err;
400  return;
401  }
402  off += save_size;
403  }
404  ::fsync(theFd);
405 #ifdef TRACE_INIT
406  Uint64 stop = NdbTick_CurrentMillisecond();
407  Uint64 diff = stop - start;
408  if (diff == 0)
409  diff = 1;
410  ndbout_c("wrote %umb in %u writes %us -> %ukb/write %umb/s",
411  Uint32(sz /1024/1024),
412  write_cnt,
413  Uint32(diff / 1000),
414  Uint32(sz / 1024 / write_cnt),
415  Uint32(sz / diff));
416 #endif
417 
418  if(lseek(theFd, 0, SEEK_SET) != 0)
419  request->error = errno;
420  }
421  else if (flags & FsOpenReq::OM_DIRECT)
422  {
423 #ifdef O_DIRECT
424  if (flags & (FsOpenReq::OM_TRUNCATE | FsOpenReq::OM_CREATE))
425  {
426  request->error = check_odirect_write(flags, new_flags, mode);
427  }
428  else
429  {
430  request->error = check_odirect_read(flags, new_flags, mode);
431  }
432 
433  if (request->error)
434  return;
435 #endif
436  }
437 
438 #ifdef VM_TRACE
439  if (flags & FsOpenReq::OM_DIRECT)
440  {
441 #ifdef O_DIRECT
442  ndbout_c("%s %s O_DIRECT: %d",
443  theFileName.c_str(), rw,
444  !!(new_flags & O_DIRECT));
445 #else
446  ndbout_c("%s %s O_DIRECT: 0",
447  theFileName.c_str(), rw);
448 #endif
449  }
450 #endif
451 
452  if ((flags & FsOpenReq::OM_SYNC) && (flags & FsOpenReq::OM_INIT))
453  {
454 #ifdef O_SYNC
455 
458  close(theFd);
459  new_flags &= ~(O_CREAT | O_TRUNC);
460  new_flags |= O_SYNC;
461  theFd = ::open(theFileName.c_str(), new_flags, mode);
462  if (theFd == -1)
463  {
464  request->error = errno;
465  }
466 #endif
467  }
468 
469 #if ! defined(O_DIRECT) && defined HAVE_DIRECTIO && defined(DIRECTIO_ON)
470  if (flags & FsOpenReq::OM_DIRECT)
471  {
472  if (directio(theFd, DIRECTIO_ON) == -1)
473  {
474  ndbout_c("%s Failed to set DIRECTIO_ON errno: %u",
475  theFileName.c_str(), errno);
476  }
477 #ifdef VM_TRACE
478  else
479  {
480  ndbout_c("%s DIRECTIO_ON", theFileName.c_str());
481  }
482 #endif
483  }
484 #endif
485 
486  if(use_gz)
487  {
488  int err;
489  if((err= ndbzdopen(&nzf, theFd, new_flags)) < 1)
490  {
491  ndbout_c("Stewart's brain broke: %d %d %s",
492  err, my_errno, theFileName.c_str());
493  abort();
494  }
495  }
496 }
497 
499  size_t size, off_t offset)
500 {
501  int return_value;
502  req->par.readWrite.pages[0].size = 0;
503  off_t seek_val;
504 #if ! defined(HAVE_PREAD)
505  FileGuard guard(this);
506  if(!use_gz)
507  {
508  while((seek_val= lseek(theFd, offset, SEEK_SET)) == (off_t)-1
509  && errno == EINTR) {};
510  if(seek_val == (off_t)-1)
511  {
512  return errno;
513  }
514  }
515 #endif
516  if(use_gz)
517  {
518  while((seek_val= ndbzseek(&nzf, offset, SEEK_SET)) == (off_t)-1
519  && errno == EINTR) {};
520  if(seek_val == (off_t)-1)
521  {
522  return errno;
523  }
524  }
525 
526  int error;
527 
528  while (size > 0) {
529  size_t bytes_read = 0;
530 
531 #if ! defined(HAVE_PREAD)
532  if(use_gz)
533  return_value = ndbzread(&nzf, buf, size, &error);
534  else
535  return_value = ::read(theFd, buf, size);
536 #else // UNIX
537  if(!use_gz)
538  return_value = ::pread(theFd, buf, size, offset);
539  else
540  return_value = ndbzread(&nzf, buf, size, &error);
541 #endif
542  if (return_value == -1 && errno == EINTR) {
543  DEBUG(ndbout_c("EINTR in read"));
544  continue;
545  } else if (!use_gz) {
546  if (return_value == -1)
547  return errno;
548  }
549  else if (return_value < 1 && nzf.z_eof!=1)
550  {
551  if(my_errno==0 && errno==0 && error==0 && nzf.z_err==Z_STREAM_END)
552  break;
553  DEBUG(ndbout_c("ERROR DURING %sRead: %d off: %d from %s",(use_gz)?"gz":"",size,offset,theFileName.c_str()));
554  ndbout_c("ERROR IN PosixAsyncFile::readBuffer %d %d %d %d",
555  my_errno, errno, nzf.z_err, error);
556  if(use_gz)
557  return my_errno;
558  return errno;
559  }
560  bytes_read = return_value;
561  req->par.readWrite.pages[0].size += bytes_read;
562  if(bytes_read == 0){
563  if(req->action == Request::readPartial)
564  {
565  return 0;
566  }
567  DEBUG(ndbout_c("Read underflow %d %d\n %x\n%d %d",
568  size, offset, buf, bytes_read, return_value));
569  return ERR_ReadUnderflow;
570  }
571 
572  if(bytes_read != size){
573  DEBUG(ndbout_c("Warning partial read %d != %d on %s",
574  bytes_read, size, theFileName.c_str()));
575  }
576 
577  buf += bytes_read;
578  size -= bytes_read;
579  offset += bytes_read;
580  }
581  return 0;
582 }
583 
584 void PosixAsyncFile::readvReq(Request *request)
585 {
586 #if ! defined(HAVE_PREAD)
587  readReq(request);
588  return;
589 #else
590  int return_value;
591  int length = 0;
592  struct iovec iov[20]; // the parameter in the signal restricts this to 20 deep
593  for(int i=0; i < request->par.readWrite.numberOfPages ; i++) {
594  iov[i].iov_base= request->par.readWrite.pages[i].buf;
595  iov[i].iov_len= request->par.readWrite.pages[i].size;
596  length = length + iov[i].iov_len;
597  }
598  lseek( theFd, request->par.readWrite.pages[0].offset, SEEK_SET );
599  return_value = ::readv(theFd, iov, request->par.readWrite.numberOfPages);
600  if (return_value == -1) {
601  request->error = errno;
602  return;
603  } else if (return_value != length) {
604  request->error = 1011;
605  return;
606  }
607 #endif
608 }
609 
610 int PosixAsyncFile::writeBuffer(const char *buf, size_t size, off_t offset)
611 {
612  size_t chunk_size = 256*1024;
613  size_t bytes_to_write = chunk_size;
614  int return_value;
615 
616  m_write_wo_sync += size;
617 
618 #if ! defined(HAVE_PWRITE)
619  FileGuard guard(this);
620  off_t seek_val;
621  while((seek_val= lseek(theFd, offset, SEEK_SET)) == (off_t)-1
622  && errno == EINTR) {};
623  if(seek_val == (off_t)-1)
624  {
625  return errno;
626  }
627 #endif
628 
629  while (size > 0) {
630  if (size < bytes_to_write){
631  // We are at the last chunk
632  bytes_to_write = size;
633  }
634  size_t bytes_written = 0;
635 
636 #if ! defined(HAVE_PWRITE)
637  if(use_gz)
638  return_value= ndbzwrite(&nzf, buf, bytes_to_write);
639  else
640  return_value = ::write(theFd, buf, bytes_to_write);
641 #else // UNIX
642  if(use_gz)
643  return_value= ndbzwrite(&nzf, buf, bytes_to_write);
644  else
645  return_value = ::pwrite(theFd, buf, bytes_to_write, offset);
646 #endif
647  if (return_value == -1 && errno == EINTR) {
648  bytes_written = 0;
649  DEBUG(ndbout_c("EINTR in write"));
650  } else if (return_value == -1 || return_value < 1){
651  ndbout_c("ERROR IN PosixAsyncFile::writeBuffer %d %d %d",
652  my_errno, errno, nzf.z_err);
653  if(use_gz)
654  return my_errno;
655  return errno;
656  } else {
657  bytes_written = return_value;
658 
659  if(bytes_written == 0){
660  DEBUG(ndbout_c("no bytes written"));
661  abort();
662  }
663 
664  if(bytes_written != bytes_to_write){
665  DEBUG(ndbout_c("Warning partial write %d != %d",
666  bytes_written, bytes_to_write));
667  }
668  }
669 
670  buf += bytes_written;
671  size -= bytes_written;
672  offset += bytes_written;
673  }
674  return 0;
675 }
676 
677 void PosixAsyncFile::closeReq(Request *request)
678 {
679  if (m_open_flags & (
680  FsOpenReq::OM_WRITEONLY |
681  FsOpenReq::OM_READWRITE |
682  FsOpenReq::OM_APPEND )) {
683  syncReq(request);
684  }
685  int r;
686  if(use_gz)
687  r= ndbzclose(&nzf);
688  else
689  r= ::close(theFd);
690  use_gz= 0;
691  Byte *a,*b;
692  a= nzf.inbuf;
693  b= nzf.outbuf;
694  memset(&nzf,0,sizeof(nzf));
695  nzf.inbuf= a;
696  nzf.outbuf= b;
697  nzf.stream.opaque = (void*)&nz_mempool;
698 
699  if (-1 == r) {
700 #ifndef DBUG_OFF
701  if (theFd == -1) {
702  DEBUG(ndbout_c("close on fd = -1"));
703  abort();
704  }
705 #endif
706  request->error = errno;
707  }
708  theFd = -1;
709 }
710 
711 bool PosixAsyncFile::isOpen(){
712  return (theFd != -1);
713 }
714 
715 
716 void PosixAsyncFile::syncReq(Request *request)
717 {
718  if(m_auto_sync_freq && m_write_wo_sync == 0){
719  return;
720  }
721  if (-1 == ::fsync(theFd)){
722  request->error = errno;
723  return;
724  }
725  m_write_wo_sync = 0;
726 }
727 
728 void PosixAsyncFile::appendReq(Request *request)
729 {
730  const char * buf = request->par.append.buf;
731  Uint32 size = request->par.append.size;
732 
733  m_write_wo_sync += size;
734 
735  while(size > 0){
736  int n;
737  if(use_gz)
738  n= ndbzwrite(&nzf,buf,size);
739  else
740  n= write(theFd, buf, size);
741  if(n == -1 && errno == EINTR){
742  continue;
743  }
744  if(n == -1){
745  if(use_gz)
746  request->error = my_errno;
747  else
748  request->error = errno;
749  return;
750  }
751  if(n == 0){
752  DEBUG(ndbout_c("append with n=0"));
753  abort();
754  }
755  size -= n;
756  buf += n;
757  }
758 
759  if(m_auto_sync_freq && m_write_wo_sync > m_auto_sync_freq){
760  syncReq(request);
761  }
762 }
763 
764 void PosixAsyncFile::removeReq(Request *request)
765 {
766  if (-1 == ::remove(theFileName.c_str())) {
767  request->error = errno;
768 
769  }
770 }
771 
772 void
773 PosixAsyncFile::rmrfReq(Request *request, const char * src, bool removePath)
774 {
775  if(!request->par.rmrf.directory)
776  {
777  // Remove file
778  if(unlink(src) != 0 && errno != ENOENT)
779  request->error = errno;
780  return;
781  }
782 
783  char path[PATH_MAX];
784  strcpy(path, src);
785  strcat(path, "/");
786 
787  DIR* dirp;
788  struct dirent * dp;
789 loop:
790  dirp = opendir(path);
791  if(dirp == 0)
792  {
793  if(errno != ENOENT)
794  request->error = errno;
795  return;
796  }
797 
798  while ((dp = readdir(dirp)) != NULL)
799  {
800  if ((strcmp(".", dp->d_name) != 0) && (strcmp("..", dp->d_name) != 0))
801  {
802  int len = strlen(path);
803  strcat(path, dp->d_name);
804  if (remove(path) == 0)
805  {
806  path[len] = 0;
807  continue;
808  }
809 
810  closedir(dirp);
811  strcat(path, "/");
812  goto loop;
813  }
814  }
815  closedir(dirp);
816  path[strlen(path)-1] = 0; // remove /
817  if (strcmp(src, path) != 0)
818  {
819  char * t = strrchr(path, '/');
820  t[1] = 0;
821  goto loop;
822  }
823 
824  if(removePath && rmdir(src) != 0)
825  {
826  request->error = errno;
827  }
828 }
829 
830 PosixAsyncFile::~PosixAsyncFile()
831 {
832  /* Free the read and write buffer memory used by ndbzio */
833  if (nzfBufferUnaligned)
834  ndbd_free(nzfBufferUnaligned,
835  ndbz_bufsize_read() +
836  ndbz_bufsize_write() +
837  NDB_O_DIRECT_WRITE_ALIGNMENT-1);
838  nzfBufferUnaligned = NULL;
839 
840  /* Free the inflate/deflate buffers for ndbzio */
841  if(nz_mempool.mem)
842  ndbd_free(nz_mempool.mem, nz_mempool.size);
843  nz_mempool.mem = NULL;
844 
845  destroy_mutex();
846 }
847 
848 void PosixAsyncFile::createDirectories()
849 {
850  char* tmp;
851  const char * name = theFileName.c_str();
852  const char * base = theFileName.get_base_name();
853  while((tmp = (char *)strstr(base, DIR_SEPARATOR)))
854  {
855  char t = tmp[0];
856  tmp[0] = 0;
857  mkdir(name, S_IRUSR | S_IWUSR | S_IXUSR | S_IXGRP | S_IRGRP);
858  tmp[0] = t;
859  base = tmp + sizeof(DIR_SEPARATOR);
860  }
861 }