You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			280 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			280 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2014 InfiniDB, Inc.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License
 | 
						|
   as published by the Free Software Foundation; version 2 of
 | 
						|
   the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
						|
   MA 02110-1301, USA. */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <sstream>
 | 
						|
#include <iostream>
 | 
						|
#include "utility.h"
 | 
						|
#include "BufferedFile.h"
 | 
						|
#include "IDBLogger.h"
 | 
						|
using namespace std;
 | 
						|
 | 
						|
namespace idbdatafile
 | 
						|
{
 | 
						|
BufferedFile::BufferedFile(const char* fname, const char* mode, unsigned opts)
 | 
						|
 : IDBDataFile(fname), m_fp(0), m_buffer(0)
 | 
						|
{
 | 
						|
  m_fp = fopen(fname, mode);
 | 
						|
  int err = errno;
 | 
						|
 | 
						|
  if (m_fp == NULL)
 | 
						|
  {
 | 
						|
    static string message = "unable to open file: ";
 | 
						|
 | 
						|
    throw std::runtime_error(message + fname + ", exception: " + strerror(err));
 | 
						|
  }
 | 
						|
 | 
						|
  applyOptions(opts);
 | 
						|
}
 | 
						|
 | 
						|
void BufferedFile::applyOptions(unsigned opts)
 | 
						|
{
 | 
						|
  if (opts & IDBDataFile::USE_VBUF)
 | 
						|
  {
 | 
						|
    const int DEFAULT_BUFSIZ = 1 * 1024 * 1024;
 | 
						|
    m_buffer = new char[DEFAULT_BUFSIZ];
 | 
						|
    setvbuf(m_fp, m_buffer, _IOFBF, DEFAULT_BUFSIZ);
 | 
						|
  }
 | 
						|
  else if (opts & IDBDataFile::USE_NOVBUF)
 | 
						|
  {
 | 
						|
    setvbuf(m_fp, NULL, _IONBF, 0);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
BufferedFile::~BufferedFile()
 | 
						|
{
 | 
						|
  close();
 | 
						|
  m_fp = 0;
 | 
						|
  delete[] m_buffer;
 | 
						|
}
 | 
						|
 | 
						|
ssize_t BufferedFile::pread(void* ptr, off64_t offset, size_t count)
 | 
						|
{
 | 
						|
  ssize_t ret = 0;
 | 
						|
  int savedErrno;
 | 
						|
  ssize_t curpos = tell();
 | 
						|
 | 
						|
  seek(offset, SEEK_SET);
 | 
						|
  ret = read(ptr, count);
 | 
						|
  savedErrno = errno;
 | 
						|
  seek(curpos, SEEK_SET);
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
    IDBLogger::logRW("pread", m_fname, this, offset, count, ret);
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
ssize_t BufferedFile::read(void* ptr, size_t count)
 | 
						|
{
 | 
						|
  ssize_t ret = 0;
 | 
						|
  ssize_t offset = tell();
 | 
						|
  int savedErrno = -1;
 | 
						|
  size_t progress = 0;
 | 
						|
  uint8_t* ptr8 = (uint8_t*)ptr;
 | 
						|
 | 
						|
  while (progress < count)
 | 
						|
  {
 | 
						|
    ret = fread(ptr8 + progress, 1, count - progress, m_fp);
 | 
						|
    savedErrno = errno;
 | 
						|
 | 
						|
    if (ret <= 0)
 | 
						|
    {
 | 
						|
      if (ferror(m_fp))
 | 
						|
      {
 | 
						|
        errno = savedErrno;
 | 
						|
        return -1;
 | 
						|
      }
 | 
						|
      else if (feof(m_fp))
 | 
						|
        return progress;
 | 
						|
    }
 | 
						|
 | 
						|
    progress += ret;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
    IDBLogger::logRW("read", m_fname, this, offset, count, progress);
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return progress;
 | 
						|
}
 | 
						|
 | 
						|
ssize_t BufferedFile::write(const void* ptr, size_t count)
 | 
						|
{
 | 
						|
  ssize_t ret = 0;
 | 
						|
  off64_t offset = tell();
 | 
						|
  int savedErrno = 0;
 | 
						|
  size_t progress = 0;
 | 
						|
  uint8_t* ptr8 = (uint8_t*)ptr;
 | 
						|
 | 
						|
  while (progress < count)
 | 
						|
  {
 | 
						|
    ret = fwrite(ptr8 + progress, 1, count - progress, m_fp);
 | 
						|
    savedErrno = errno;
 | 
						|
 | 
						|
    if (ret <= 0 && ferror(m_fp))
 | 
						|
    {
 | 
						|
      errno = savedErrno;
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
    else if (ret > 0)
 | 
						|
      progress += ret;
 | 
						|
 | 
						|
    // can fwrite() continually return 0 with no error?
 | 
						|
  }
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
    IDBLogger::logRW("write", m_fname, this, offset, count, progress);
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return progress;
 | 
						|
}
 | 
						|
 | 
						|
int BufferedFile::seek(off64_t offset, int whence)
 | 
						|
{
 | 
						|
  int ret = 0;
 | 
						|
  int savedErrno;
 | 
						|
  ret = fseek(m_fp, offset, whence);
 | 
						|
  savedErrno = errno;
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
    IDBLogger::logSeek(m_fname, this, offset, whence, ret);
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int BufferedFile::truncate(off64_t length)
 | 
						|
{
 | 
						|
  int ret = 0;
 | 
						|
  int savedErrno;
 | 
						|
 | 
						|
  ret = ftruncate(fileno(m_fp), length);
 | 
						|
  savedErrno = errno;
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
    IDBLogger::logTruncate(m_fname, this, length, ret);
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
off64_t BufferedFile::size()
 | 
						|
{
 | 
						|
  // going to calculate size 2 ways - first, via seek
 | 
						|
  off64_t length = -1;
 | 
						|
  off64_t here;
 | 
						|
 | 
						|
  flockfile(m_fp);
 | 
						|
 | 
						|
  try
 | 
						|
  {
 | 
						|
    if ((here = ftell(m_fp)) > -1)
 | 
						|
    {
 | 
						|
      if (fseek(m_fp, 0, SEEK_END) > -1)
 | 
						|
      {
 | 
						|
        length = ftell(m_fp);
 | 
						|
        fseek(m_fp, here, SEEK_SET);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    funlockfile(m_fp);
 | 
						|
  }
 | 
						|
  catch (...)
 | 
						|
  {
 | 
						|
    funlockfile(m_fp);
 | 
						|
  }
 | 
						|
 | 
						|
  return length;
 | 
						|
}
 | 
						|
 | 
						|
off64_t BufferedFile::tell()
 | 
						|
{
 | 
						|
  return ftell(m_fp);
 | 
						|
}
 | 
						|
 | 
						|
int BufferedFile::flush()
 | 
						|
{
 | 
						|
  int rc = fflush(m_fp);
 | 
						|
  int savedErrno = errno;
 | 
						|
 | 
						|
  if (rc == 0)
 | 
						|
  {
 | 
						|
    rc = fsync(fileno(m_fp));
 | 
						|
    savedErrno = errno;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
    IDBLogger::logNoArg(m_fname, this, "flush", rc);
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
time_t BufferedFile::mtime()
 | 
						|
{
 | 
						|
  time_t ret = 0;
 | 
						|
  struct stat statbuf;
 | 
						|
 | 
						|
  if (::fstat(fileno(m_fp), &statbuf) == 0)
 | 
						|
    ret = statbuf.st_mtime;
 | 
						|
  else
 | 
						|
    ret = (time_t)-1;
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int BufferedFile::close()
 | 
						|
{
 | 
						|
  int ret = fclose(m_fp);
 | 
						|
  int savedErrno = errno;
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
    IDBLogger::logNoArg(m_fname, this, "close", ret);
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
     @brief
 | 
						|
    The wrapper for fallocate function.
 | 
						|
     @see
 | 
						|
    This one is used in shared/we_fileop.cpp to skip expensive file preallocation.
 | 
						|
*/
 | 
						|
int BufferedFile::fallocate(int mode, off64_t offset, off64_t length)
 | 
						|
{
 | 
						|
  int ret = 0;
 | 
						|
  int savedErrno = 0;
 | 
						|
 | 
						|
  ret = ::fallocate(fileno(m_fp), mode, offset, length);
 | 
						|
  savedErrno = errno;
 | 
						|
 | 
						|
  if (IDBLogger::isEnabled())
 | 
						|
  {
 | 
						|
    IDBLogger::logNoArg(m_fname, this, "fallocate", errno);
 | 
						|
  }
 | 
						|
 | 
						|
  errno = savedErrno;
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace idbdatafile
 |