OmniSciDB  340b00dbf6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
File_Namespace Namespace Reference

Classes

struct  readThreadDS
 
class  FileBuffer
 Represents/provides access to contiguous data stored in the file system. More...
 
struct  FileInfo
 
class  FileMgr
 
class  GlobalFileMgr
 
struct  Page
 A logical page (Page) belongs to a file on disk. More...
 
struct  MultiPage
 The MultiPage stores versions of the same logical page in a deque. More...
 
struct  HeaderInfo
 Stores Pair of ChunkKey and Page id and version, in a pair with a Page struct itself (File id and Page num) More...
 

Typedefs

using PageSizeFileMMap = std::multimap< size_t, int >
 Maps logical page sizes to files. More...
 
using Chunk = FileBuffer
 A Chunk is the fundamental unit of execution in Map-D. More...
 
using ChunkKeyToChunkMap = std::map< ChunkKey, FileBuffer * >
 Maps ChunkKeys (unique ids for Chunks) to Chunk objects. More...
 

Functions

static size_t readForThread (FileBuffer *fileBuffer, const readThreadDS threadDS)
 
bool headerCompare (const HeaderInfo &firstElem, const HeaderInfo &secondElem)
 
FILE * create (const std::string &basePath, const int fileId, const size_t pageSize, const size_t numPages)
 
FILE * create (const std::string &fullPath, const size_t requestedFileSize)
 
FILE * open (int fileId)
 Opens/creates the file with the given id; returns NULL on error. More...
 
FILE * open (const std::string &path)
 
void close (FILE *f)
 Closes the file pointed to by the FILE pointer. More...
 
bool removeFile (const std::string basePath, const std::string filename)
 Deletes the file pointed to by the FILE pointer. More...
 
size_t read (FILE *f, const size_t offset, const size_t size, int8_t *buf)
 Reads the specified number of bytes from the offset position in file f into buf. More...
 
size_t write (FILE *f, const size_t offset, const size_t size, int8_t *buf)
 Writes the specified number of bytes to the offset position in file f from buf. More...
 
size_t append (FILE *f, const size_t size, int8_t *buf)
 Appends the specified number of bytes to the end of the file f from buf. More...
 
size_t readPage (FILE *f, const size_t pageSize, const size_t pageNum, int8_t *buf)
 Reads the specified page from the file f into buf. More...
 
size_t readPartialPage (FILE *f, const size_t pageSize, const size_t offset, const size_t readSize, const size_t pageNum, int8_t *buf)
 
size_t writePage (FILE *f, const size_t pageSize, const size_t pageNum, int8_t *buf)
 Writes a page from buf to the file. More...
 
size_t writePartialPage (FILE *f, const size_t pageSize, const size_t offset, const size_t writeSize, const size_t pageNum, int8_t *buf)
 
size_t appendPage (FILE *f, const size_t pageSize, int8_t *buf)
 Appends a page from buf to the file. More...
 
size_t fileSize (FILE *f)
 Returns the size of the specified file. More...
 
void renameForDelete (const std::string directoryName)
 Renames a directory to DELETE_ME_<EPOCH>_<oldname>. More...
 

Typedef Documentation

A Chunk is the fundamental unit of execution in Map-D.

Chunk A chunk is composed of logical pages. These pages can exist across multiple files managed by the file manager.

The collection of pages is implemented as a FileBuffer object, which is composed of a vector of MultiPage objects, one for each logical page of the file buffer.

Definition at line 67 of file FileMgr.h.

Maps ChunkKeys (unique ids for Chunks) to Chunk objects.

ChunkKeyToChunkMap The file system can store multiple chunks across multiple files. With that in mind, the challenge is to be able to reconstruct the pages that compose a chunk upon request. A chunk key (ChunkKey) uniquely identifies a chunk, and so ChunkKeyToChunkMap maps chunk keys to Chunk types, which are vectors of MultiPage* pointers (logical pages).

Definition at line 79 of file FileMgr.h.

using File_Namespace::PageSizeFileMMap = typedef std::multimap<size_t, int>

Maps logical page sizes to files.

PageSizeFileMMap The file manager uses this type in order to quickly find files of a certain page size. A multimap is used to associate the key (page size) with values (file identifiers of files having the matching page size).

Definition at line 55 of file FileMgr.h.

Function Documentation

size_t File_Namespace::append ( FILE *  f,
const size_t  size,
int8_t *  buf 
)

Appends the specified number of bytes to the end of the file f from buf.

Parameters
fPointer to the FILE.
nThe number of bytes to append to the file.
bufThe source buffer containing the data to be appended.
errIf not NULL, will hold an error code should an error occur.
Returns
size_t The number of bytes written.

Definition at line 141 of file File.cpp.

References fileSize(), and write().

Referenced by concat(), concat_with(), com.mapd.utility.SQLImporter::createMapDTable(), ArrowResultSetConverter::getArrowBatch(), com.omnisci.jdbc.OmniSciPreparedStatement::getQuery(), com.mapd.parser.server.ExtensionFunctionSignatureParser::join(), run_benchmark::read_query_files(), run_benchmark_arrow::run_query(), run_benchmark::run_query(), com.omnisci.jdbc.OmniSciEscapeFunctions::singleArgumentFunctionCall(), com.mapd.parser.server.ExtensionFunction::toJson(), and com.omnisci.jdbc.OmniSciArray::toString().

141  {
142  return write(f, fileSize(f), size, buf);
143 }
size_t fileSize(FILE *f)
Returns the size of the specified file.
Definition: File.cpp:176
size_t write(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Writes the specified number of bytes to the offset position in file f from buf.
Definition: File.cpp:126

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

size_t File_Namespace::appendPage ( FILE *  f,
const size_t  pageSize,
int8_t *  buf 
)

Appends a page from buf to the file.

Parameters
fPointer to the FILE.
pageSizeThe logical page size of the file.
bufThe source buffer from where data is being read.
errIf not NULL, will hold an error code should an error occur.
Returns
size_t The number of bytes appended (should be equal to pageSize).

Definition at line 171 of file File.cpp.

References fileSize(), and write().

171  {
172  return write(f, fileSize(f), pageSize, buf);
173 }
size_t fileSize(FILE *f)
Returns the size of the specified file.
Definition: File.cpp:176
size_t write(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Writes the specified number of bytes to the offset position in file f from buf.
Definition: File.cpp:126

+ Here is the call graph for this function:

void File_Namespace::close ( FILE *  f)

Closes the file pointed to by the FILE pointer.

Parameters
fPointer to the FILE.

Definition at line 107 of file File.cpp.

References CHECK, and CHECK_EQ.

Referenced by File_Namespace::FileMgr::closeRemovePhysical(), File_Namespace::FileInfo::~FileInfo(), and File_Namespace::FileMgr::~FileMgr().

107  {
108  CHECK(f);
109  CHECK_EQ(fflush(f), 0);
110  CHECK_EQ(fclose(f), 0);
111 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205
#define CHECK(condition)
Definition: Logger.h:197

+ Here is the caller graph for this function:

FILE * File_Namespace::create ( const std::string &  basePath,
const int  fileId,
const size_t  pageSize,
const size_t  numPages 
)

Definition at line 40 of file File.cpp.

References logger::FATAL, fileSize(), omnisci::fopen(), LOG, MAPD_FILE_EXT, and to_string().

Referenced by File_Namespace::FileMgr::createDBMetaFile(), File_Namespace::FileMgr::createEpochFile(), File_Namespace::FileMgr::createFile(), kafka_insert(), and org.apache.calcite.sql2rel.SqlToRelConverter::SqlToRelConverter().

43  {
44  std::string path(basePath + "/" + std::to_string(fileId) + "." +
45  std::to_string(pageSize) +
46  std::string(MAPD_FILE_EXT)); // MAPD_FILE_EXT has preceding "."
47  if (numPages < 1 || pageSize < 1) {
48  LOG(FATAL) << "Error trying to create file '" << path
49  << "', Number of pages and page size must be positive integers. numPages "
50  << numPages << " pageSize " << pageSize;
51  }
52  FILE* f = omnisci::fopen(path.c_str(), "w+b");
53  if (f == nullptr) {
54  LOG(FATAL) << "Error trying to create file '" << path
55  << "', the error was: " << std::strerror(errno);
56  ;
57  }
58  fseek(f, static_cast<long>((pageSize * numPages) - 1), SEEK_SET);
59  fputc(EOF, f);
60  fseek(f, 0, SEEK_SET); // rewind
61  if (fileSize(f) != pageSize * numPages) {
62  LOG(FATAL) << "Error trying to create file '" << path << "', file size "
63  << fileSize(f) << " does not equal pageSize * numPages "
64  << pageSize * numPages;
65  }
66 
67  return f;
68 }
::FILE * fopen(const char *filename, const char *mode)
Definition: omnisci_fs.cpp:72
#define LOG(tag)
Definition: Logger.h:188
#define MAPD_FILE_EXT
Definition: File.h:25
std::string to_string(char const *&&v)
size_t fileSize(FILE *f)
Returns the size of the specified file.
Definition: File.cpp:176

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

FILE * File_Namespace::create ( const std::string &  fullPath,
const size_t  requestedFileSize 
)

Definition at line 70 of file File.cpp.

References logger::FATAL, fileSize(), omnisci::fopen(), and LOG.

70  {
71  FILE* f = omnisci::fopen(fullPath.c_str(), "w+b");
72  if (f == nullptr) {
73  LOG(FATAL) << "Error trying to create file '" << fullPath
74  << "', the error was: " << std::strerror(errno);
75  ;
76  }
77  fseek(f, static_cast<long>(requestedFileSize - 1), SEEK_SET);
78  fputc(EOF, f);
79  fseek(f, 0, SEEK_SET); // rewind
80  if (fileSize(f) != requestedFileSize) {
81  LOG(FATAL) << "Error trying to create file '" << fullPath << "', file size "
82  << fileSize(f) << " does not equal requestedFileSize "
83  << requestedFileSize;
84  }
85  return f;
86 }
::FILE * fopen(const char *filename, const char *mode)
Definition: omnisci_fs.cpp:72
#define LOG(tag)
Definition: Logger.h:188
size_t fileSize(FILE *f)
Returns the size of the specified file.
Definition: File.cpp:176

+ Here is the call graph for this function:

size_t File_Namespace::fileSize ( FILE *  f)

Returns the size of the specified file.

Todo:
There may be an issue casting to size_t from long.
Parameters
fA pointer to the file.
Returns
size_t The number of bytes of the file.

Definition at line 176 of file File.cpp.

Referenced by append(), appendPage(), create(), and File_Namespace::FileMgr::init().

176  {
177  fseek(f, 0, SEEK_END);
178  size_t size = (size_t)ftell(f);
179  fseek(f, 0, SEEK_SET);
180  return size;
181 }

+ Here is the caller graph for this function:

bool File_Namespace::headerCompare ( const HeaderInfo &  firstElem,
const HeaderInfo &  secondElem 
)

Definition at line 49 of file FileMgr.cpp.

References File_Namespace::HeaderInfo::chunkKey, File_Namespace::HeaderInfo::pageId, and File_Namespace::HeaderInfo::versionEpoch.

Referenced by File_Namespace::FileMgr::init().

49  {
50  // HeaderInfo.first is a pair of Chunk key with a vector containing
51  // pageId and version
52  if (firstElem.chunkKey != secondElem.chunkKey) {
53  return firstElem.chunkKey < secondElem.chunkKey;
54  }
55  if (firstElem.pageId != secondElem.pageId) {
56  return firstElem.pageId < secondElem.pageId;
57  }
58  return firstElem.versionEpoch < secondElem.versionEpoch;
59 
60  /*
61  if (firstElem.first.first != secondElem.first.first)
62  return firstElem.first.first < secondElem.first.first;
63  return firstElem.first.second < secondElem.first.second;
64  */
65 }

+ Here is the caller graph for this function:

FILE * File_Namespace::open ( int  fileId)

Opens/creates the file with the given id; returns NULL on error.

Parameters
fileIdThe id of the file to open.
Returns
FILE* A pointer to a FILE pointer, or NULL on error.

Definition at line 88 of file File.cpp.

References logger::FATAL, omnisci::fopen(), LOG, MAPD_FILE_EXT, and to_string().

Referenced by File_Namespace::FileMgr::openDBMetaFile(), File_Namespace::FileMgr::openEpochFile(), and File_Namespace::FileMgr::openExistingFile().

88  {
89  std::string s(std::to_string(fileId) + std::string(MAPD_FILE_EXT));
90  FILE* f = omnisci::fopen(s.c_str(), "r+b"); // opens existing file for updates
91  if (f == nullptr) {
92  LOG(FATAL) << "Error trying to open file '" << s
93  << "', the error was: " << std::strerror(errno);
94  }
95  return f;
96 }
::FILE * fopen(const char *filename, const char *mode)
Definition: omnisci_fs.cpp:72
#define LOG(tag)
Definition: Logger.h:188
#define MAPD_FILE_EXT
Definition: File.h:25
std::string to_string(char const *&&v)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

FILE * File_Namespace::open ( const std::string &  path)

Definition at line 98 of file File.cpp.

References logger::FATAL, omnisci::fopen(), and LOG.

98  {
99  FILE* f = omnisci::fopen(path.c_str(), "r+b"); // opens existing file for updates
100  if (f == nullptr) {
101  LOG(FATAL) << "Error trying to open file '" << path
102  << "', the errno was: " << std::strerror(errno);
103  }
104  return f;
105 }
::FILE * fopen(const char *filename, const char *mode)
Definition: omnisci_fs.cpp:72
#define LOG(tag)
Definition: Logger.h:188

+ Here is the call graph for this function:

size_t File_Namespace::read ( FILE *  f,
const size_t  offset,
const size_t  size,
int8_t *  buf 
)

Reads the specified number of bytes from the offset position in file f into buf.

Parameters
fPointer to the FILE.
offsetThe location within the file from which to read.
nThe number of bytes to be read.
bufThe destination buffer to where data is being read from the file.
errIf not NULL, will hold an error code should an error occur.
Returns
size_t The number of bytes read.

Definition at line 118 of file File.cpp.

References CHECK_EQ.

Referenced by File_Namespace::FileMgr::openDBMetaFile(), File_Namespace::FileMgr::openEpochFile(), File_Namespace::FileInfo::read(), readPage(), and readPartialPage().

118  {
119  // read "size" bytes from the offset location in the file into the buffer
120  CHECK_EQ(fseek(f, static_cast<long>(offset), SEEK_SET), 0);
121  size_t bytesRead = fread(buf, sizeof(int8_t), size, f);
122  CHECK_EQ(bytesRead, sizeof(int8_t) * size);
123  return bytesRead;
124 }
#define CHECK_EQ(x, y)
Definition: Logger.h:205

+ Here is the caller graph for this function:

static size_t File_Namespace::readForThread ( FileBuffer *  fileBuffer,
const readThreadDS  threadDS 
)
static

Definition at line 207 of file FileBuffer.cpp.

References CHECK, File_Namespace::FileMgr::getFileInfoForFileId(), File_Namespace::readThreadDS::multiPages, File_Namespace::FileBuffer::pageDataSize(), File_Namespace::FileBuffer::pageSize(), File_Namespace::FileInfo::read(), File_Namespace::FileBuffer::reservedHeaderSize(), File_Namespace::readThreadDS::t_bytesLeft, File_Namespace::readThreadDS::t_curPtr, File_Namespace::readThreadDS::t_endPage, File_Namespace::readThreadDS::t_fm, File_Namespace::readThreadDS::t_isFirstPage, File_Namespace::readThreadDS::t_startPage, and File_Namespace::readThreadDS::t_startPageOffset.

Referenced by File_Namespace::FileBuffer::read().

207  {
208  size_t startPage = threadDS.t_startPage; // start reading at startPage, including it
209  size_t endPage = threadDS.t_endPage; // stop reading at endPage, not including it
210  int8_t* curPtr = threadDS.t_curPtr;
211  size_t bytesLeft = threadDS.t_bytesLeft;
212  size_t totalBytesRead = 0;
213  bool isFirstPage = threadDS.t_isFirstPage;
214 
215  // Traverse the logical pages
216  for (size_t pageNum = startPage; pageNum < endPage; ++pageNum) {
217  CHECK(threadDS.multiPages[pageNum].pageSize == fileBuffer->pageSize());
218  Page page = threadDS.multiPages[pageNum].current();
219 
220  FileInfo* fileInfo = threadDS.t_fm->getFileInfoForFileId(page.fileId);
221  CHECK(fileInfo);
222 
223  // Read the page into the destination (dst) buffer at its
224  // current (cur) location
225  size_t bytesRead = 0;
226  if (isFirstPage) {
227  bytesRead = fileInfo->read(
228  page.pageNum * fileBuffer->pageSize() + threadDS.t_startPageOffset +
229  fileBuffer->reservedHeaderSize(),
230  min(fileBuffer->pageDataSize() - threadDS.t_startPageOffset, bytesLeft),
231  curPtr);
232  isFirstPage = false;
233  } else {
234  bytesRead = fileInfo->read(
235  page.pageNum * fileBuffer->pageSize() + fileBuffer->reservedHeaderSize(),
236  min(fileBuffer->pageDataSize(), bytesLeft),
237  curPtr);
238  }
239  curPtr += bytesRead;
240  bytesLeft -= bytesRead;
241  totalBytesRead += bytesRead;
242  }
243  CHECK(bytesLeft == 0);
244 
245  return (totalBytesRead);
246 }
#define CHECK(condition)
Definition: Logger.h:197

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

size_t File_Namespace::readPage ( FILE *  f,
const size_t  pageSize,
const size_t  pageNum,
int8_t *  buf 
)

Reads the specified page from the file f into buf.

Parameters
fPointer to the FILE.
pageSizeThe logical page size of the file.
pageNumThe page number from where data is being read.
bufThe destination buffer to where data is being written.
errIf not NULL, will hold an error code should an error occur.
Returns
size_t The number of bytes read (should be equal to pageSize).

Definition at line 145 of file File.cpp.

References read().

145  {
146  return read(f, pageNum * pageSize, pageSize, buf);
147 }
size_t read(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Reads the specified number of bytes from the offset position in file f into buf.
Definition: File.cpp:118

+ Here is the call graph for this function:

size_t File_Namespace::readPartialPage ( FILE *  f,
const size_t  pageSize,
const size_t  offset,
const size_t  readSize,
const size_t  pageNum,
int8_t *  buf 
)

Definition at line 149 of file File.cpp.

References read().

154  {
155  return read(f, pageNum * pageSize + offset, readSize, buf);
156 }
size_t read(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Reads the specified number of bytes from the offset position in file f into buf.
Definition: File.cpp:118

+ Here is the call graph for this function:

bool File_Namespace::removeFile ( const std::string  basePath,
const std::string  filename 
)

Deletes the file pointed to by the FILE pointer.

Parameters
basePathThe base path (directory) of the file.
fPointer to the FILE.
Returns
mapd_err_t Returns an error code when unable to close the file properly.

Definition at line 113 of file File.cpp.

References logger::filename().

113  {
114  const std::string filePath = basePath + filename;
115  return remove(filePath.c_str()) == 0;
116 }
std::string filename(char const *path)
Definition: Logger.cpp:62

+ Here is the call graph for this function:

void File_Namespace::renameForDelete ( const std::string  directoryName)

Renames a directory to DELETE_ME_<EPOCH>_<oldname>.

Parameters
directoryNamename of directory

Definition at line 188 of file File.cpp.

References logger::ERROR, logger::FATAL, LOG, and to_string().

Referenced by File_Namespace::FileMgr::closeRemovePhysical(), Catalog_Namespace::Catalog::delDictionary(), Catalog_Namespace::Catalog::doTruncateTable(), and Catalog_Namespace::Catalog::removeTableFromMap().

188  {
189  boost::system::error_code ec;
190  boost::filesystem::path directoryPath(directoryName);
191  using namespace std::chrono;
192  milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
193 
194  if (boost::filesystem::exists(directoryPath) &&
195  boost::filesystem::is_directory(directoryPath)) {
196  boost::filesystem::path newDirectoryPath(directoryName + "_" +
197  std::to_string(ms.count()) + "_DELETE_ME");
198  boost::filesystem::rename(directoryPath, newDirectoryPath, ec);
199 
200  if (ec.value() == boost::system::errc::success) {
201  std::thread th([newDirectoryPath]() {
202  boost::system::error_code ec;
203  boost::filesystem::remove_all(newDirectoryPath, ec);
204  if (ec.value() != boost::system::errc::success) {
205  LOG(ERROR) << "Failed to remove directory " << newDirectoryPath << " error was "
206  << ec;
207  }
208  });
209  // let it run free so we can return
210  // if it fails the file_delete_thread in DBHandler will clean up
211  th.detach();
212 
213  return;
214  }
215 
216  LOG(FATAL) << "Failed to rename file " << directoryName << " to "
217  << directoryName + "_" + std::to_string(ms.count()) + "_DELETE_ME Error: "
218  << ec;
219  }
220 }
#define LOG(tag)
Definition: Logger.h:188
std::string to_string(char const *&&v)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

size_t File_Namespace::write ( FILE *  f,
const size_t  offset,
const size_t  size,
int8_t *  buf 
)

Writes the specified number of bytes to the offset position in file f from buf.

Parameters
fPointer to the FILE.
offsetThe location within the file where data is being written.
sizeThe number of bytes to write to the file.
bufThe source buffer containing the data to be written.
errIf not NULL, will hold an error code should an error occur.
Returns
size_t The number of bytes written.

Definition at line 126 of file File.cpp.

References logger::FATAL, and LOG.

Referenced by StringDictionary::addStorageCapacity(), append(), appendPage(), File_Namespace::FileMgr::createDBMetaFile(), File_Namespace::FileInfo::freePage(), import_export::DataStreamSink::import_compressed(), File_Namespace::FileInfo::initNewFile(), File_Namespace::FileInfo::openExistingFile(), CommandLineOptions::validate(), File_Namespace::FileInfo::write(), File_Namespace::FileMgr::writeAndSyncDBMetaToDisk(), File_Namespace::FileMgr::writeAndSyncEpochToDisk(), writePage(), and writePartialPage().

126  {
127  // write size bytes from the buffer to the offset location in the file
128  if (fseek(f, static_cast<long>(offset), SEEK_SET) != 0) {
129  LOG(FATAL)
130  << "Error trying to write to file (during positioning seek) the error was: "
131  << std::strerror(errno);
132  }
133  size_t bytesWritten = fwrite(buf, sizeof(int8_t), size, f);
134  if (bytesWritten != sizeof(int8_t) * size) {
135  LOG(FATAL) << "Error trying to write to file (during fwrite) the error was: "
136  << std::strerror(errno);
137  }
138  return bytesWritten;
139 }
#define LOG(tag)
Definition: Logger.h:188

+ Here is the caller graph for this function:

size_t File_Namespace::writePage ( FILE *  f,
const size_t  pageSize,
const size_t  pageNum,
int8_t *  buf 
)

Writes a page from buf to the file.

Parameters
fPointer to the FILE.
pageSizeThe logical page size of the file.
pageNumThe page number to where data is being written.
bufThe source buffer from where data is being read.
errIf not NULL, will hold an error code should an error occur.
Returns
size_t The number of bytes written (should be equal to pageSize).

Definition at line 158 of file File.cpp.

References write().

158  {
159  return write(f, pageNum * pageSize, pageSize, buf);
160 }
size_t write(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Writes the specified number of bytes to the offset position in file f from buf.
Definition: File.cpp:126

+ Here is the call graph for this function:

size_t File_Namespace::writePartialPage ( FILE *  f,
const size_t  pageSize,
const size_t  offset,
const size_t  writeSize,
const size_t  pageNum,
int8_t *  buf 
)

Definition at line 162 of file File.cpp.

References write().

167  {
168  return write(f, pageNum * pageSize + offset, writeSize, buf);
169 }
size_t write(FILE *f, const size_t offset, const size_t size, int8_t *buf)
Writes the specified number of bytes to the offset position in file f from buf.
Definition: File.cpp:126

+ Here is the call graph for this function: