mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 06:43:04 +01:00
1) Reworked memory management in SORT. Now we're pools aware there.
2) Reworked error handling in SORT and its callers. 3) Replaced DLS+SortMem with the generic TempSpace class. 4) Replaced GDS temp file management with the TempFile class. 5) Various cleanup.
This commit is contained in:
parent
52c314d7e2
commit
7cc12e8489
@ -187,6 +187,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\TempFile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\timestamp.cpp">
|
||||
</File>
|
||||
@ -236,6 +239,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\MetaName.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\TempFile.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\timestamp.h">
|
||||
</File>
|
||||
|
@ -186,6 +186,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\TempFile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\timestamp.cpp">
|
||||
</File>
|
||||
@ -232,6 +235,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\MetaName.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\TempFile.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\common\classes\timestamp.h">
|
||||
</File>
|
||||
|
@ -168,9 +168,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\divorce.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dls.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\gen\jrd\dpm.cpp">
|
||||
</File>
|
||||
@ -351,9 +348,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sort.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sort_mem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sqz.cpp">
|
||||
</File>
|
||||
@ -366,6 +360,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sym.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\TempSpace.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\thd.cpp">
|
||||
</File>
|
||||
@ -499,9 +496,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\divorce.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dls_proto.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dmp_proto.h">
|
||||
</File>
|
||||
@ -958,6 +952,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sym_proto.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\TempSpace.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\termtype.h">
|
||||
</File>
|
||||
|
@ -168,9 +168,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\divorce.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dls.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\gen\jrd\dpm.cpp">
|
||||
</File>
|
||||
@ -351,9 +348,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sort.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sort_mem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sqz.cpp">
|
||||
</File>
|
||||
@ -366,6 +360,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sym.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\TempSpace.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\thd.cpp">
|
||||
</File>
|
||||
@ -499,9 +496,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\divorce.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dls_proto.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dmp_proto.h">
|
||||
</File>
|
||||
@ -958,6 +952,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sym_proto.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\TempSpace.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\termtype.h">
|
||||
</File>
|
||||
|
@ -172,9 +172,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\divorce.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dls.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\gen\jrd\dpm.cpp">
|
||||
</File>
|
||||
@ -355,9 +352,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sort.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sort_mem.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sqz.cpp">
|
||||
</File>
|
||||
@ -370,6 +364,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sym.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\TempSpace.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\thd.cpp">
|
||||
</File>
|
||||
@ -500,9 +497,6 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\divorce.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dls_proto.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\dmp_proto.h">
|
||||
</File>
|
||||
@ -959,6 +953,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\sym_proto.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\TempSpace.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\jrd\termtype.h">
|
||||
</File>
|
||||
|
42
src/common/classes/File.h
Normal file
42
src/common/classes/File.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Dmitry Yemanov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2006 Dmitry Yemanov <dimitr@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef FILE_H
|
||||
#define FILE_H
|
||||
|
||||
typedef UINT64 offset_t;
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
class File {
|
||||
public:
|
||||
virtual size_t read(offset_t, void*, size_t) = 0;
|
||||
virtual size_t write(offset_t, void*, size_t) = 0;
|
||||
|
||||
virtual void unlink() = 0;
|
||||
|
||||
virtual offset_t getSize() const = 0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // FILE_H
|
338
src/common/classes/TempFile.cpp
Normal file
338
src/common/classes/TempFile.cpp
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Dmitry Yemanov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2006 Dmitry Yemanov <dimitr@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(WIN_NT)
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#include <share.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../jrd/os/path_utils.h"
|
||||
|
||||
#include "../common/classes/TempFile.h"
|
||||
|
||||
// Const definitions
|
||||
|
||||
static const char* ENV_VAR = "FIREBIRD_TMP";
|
||||
static const char* DEFAULT_PATH =
|
||||
#if defined(UNIX)
|
||||
"/tmp/";
|
||||
#elif defined(WIN_NT)
|
||||
"c:\\temp\\";
|
||||
#elif defined(VMS)
|
||||
"SYS$SCRATCH:";
|
||||
#else
|
||||
NULL;
|
||||
#endif
|
||||
|
||||
static const char* const NAME_PATTERN = "XXXXXX";
|
||||
static const char* const NAME_LETTERS = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static const size_t MAX_TRIES = 256;
|
||||
|
||||
//
|
||||
// TempFile::getTempPath
|
||||
//
|
||||
// Returns a pathname to the system temporary directory
|
||||
//
|
||||
|
||||
Firebird::PathName TempFile::getTempPath()
|
||||
{
|
||||
const char* env_temp = getenv(ENV_VAR);
|
||||
Firebird::PathName path = env_temp ? env_temp : "";
|
||||
if (path.empty())
|
||||
{
|
||||
#if defined(WIN_NT)
|
||||
char temp_dir[MAXPATHLEN];
|
||||
// this checks "TEMP" and "TMP" environment variables
|
||||
const int len = GetTempPath(sizeof(temp_dir), temp_dir);
|
||||
if (len && len < sizeof(temp_dir))
|
||||
{
|
||||
path = temp_dir;
|
||||
}
|
||||
#else
|
||||
path = getenv("TMP");
|
||||
#endif
|
||||
}
|
||||
if (path.empty())
|
||||
{
|
||||
path = DEFAULT_PATH;
|
||||
}
|
||||
|
||||
fb_assert(path.length());
|
||||
return path;
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::create
|
||||
//
|
||||
// Creates a temporary file and returns its name
|
||||
//
|
||||
|
||||
Firebird::PathName TempFile::create(const Firebird::PathName& prefix)
|
||||
{
|
||||
Firebird::PathName filename;
|
||||
|
||||
try {
|
||||
TempFile file(prefix, false);
|
||||
filename = file.getName();
|
||||
}
|
||||
catch (const Firebird::Exception&) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::init
|
||||
//
|
||||
// Creates temporary file with a unique filename
|
||||
//
|
||||
|
||||
void TempFile::init(const Firebird::PathName& directory,
|
||||
const Firebird::PathName& prefix)
|
||||
{
|
||||
// set up temporary directory, if not specified
|
||||
filename = directory;
|
||||
if (filename.empty())
|
||||
{
|
||||
filename = getTempPath();
|
||||
}
|
||||
|
||||
#if defined(WIN_NT)
|
||||
_timeb t;
|
||||
_ftime(&t);
|
||||
__int64 randomness = t.time;
|
||||
randomness *= 1000;
|
||||
randomness += t.millitm;
|
||||
Firebird::PathName suffix = NAME_PATTERN;
|
||||
for (int tries = 0; tries < MAX_TRIES; tries++)
|
||||
{
|
||||
Firebird::PathName name = filename + prefix;
|
||||
__int64 temp = randomness;
|
||||
for (int i = 0; i < suffix.length(); i++)
|
||||
{
|
||||
suffix[i] = NAME_LETTERS[temp % (strlen(NAME_LETTERS))];
|
||||
temp /= strlen(NAME_LETTERS);
|
||||
}
|
||||
name += suffix;
|
||||
DWORD attributes = FILE_ATTRIBUTE_NORMAL |
|
||||
FILE_ATTRIBUTE_TEMPORARY |
|
||||
FILE_FLAG_RANDOM_ACCESS;
|
||||
if (doUnlink)
|
||||
{
|
||||
attributes |= FILE_FLAG_DELETE_ON_CLOSE;
|
||||
}
|
||||
handle = CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_NEW, attributes, NULL);
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
filename = name;
|
||||
break;
|
||||
}
|
||||
randomness++;
|
||||
}
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Firebird::system_call_failed::raise("CreateFile");
|
||||
}
|
||||
#else
|
||||
filename += prefix;
|
||||
filename += NAME_PATTERN;
|
||||
|
||||
#ifdef HAVE_MKSTEMP
|
||||
handle = (IPTR) mkstemp(filename.begin());
|
||||
#else
|
||||
if (!mktemp(filename.begin()))
|
||||
{
|
||||
Firebird::system_call_failed::raise("mktemp");
|
||||
}
|
||||
|
||||
do {
|
||||
handle = open(filename.c_str(), O_RDWR | O_EXCL | O_CREAT);
|
||||
} while (handle == -1 && errno == EINTR);
|
||||
#endif
|
||||
|
||||
if (handle == -1)
|
||||
{
|
||||
Firebird::system_call_failed::raise("open");
|
||||
}
|
||||
|
||||
if (doUnlink)
|
||||
{
|
||||
::unlink(filename.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
doUnlink = false;
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::~TempFile
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
|
||||
TempFile::~TempFile()
|
||||
{
|
||||
#if defined(WIN_NT)
|
||||
if (!CloseHandle(handle))
|
||||
{
|
||||
Firebird::system_call_failed::raise("CloseHandle");
|
||||
}
|
||||
#else
|
||||
if (::close(handle) == -1)
|
||||
{
|
||||
Firebird::system_call_failed::raise("close");
|
||||
}
|
||||
#endif
|
||||
if (doUnlink)
|
||||
{
|
||||
::unlink(filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::seek
|
||||
//
|
||||
// Performs a positioning operation
|
||||
//
|
||||
|
||||
void TempFile::seek(offset_t offset)
|
||||
{
|
||||
fb_assert(offset < MAX_SLONG);
|
||||
if (position == offset)
|
||||
return;
|
||||
#if defined(WIN_NT)
|
||||
position = SetFilePointer(handle, offset, NULL, FILE_BEGIN);
|
||||
if (position != offset)
|
||||
{
|
||||
Firebird::system_call_failed::raise("SetFilePointer");
|
||||
}
|
||||
#else
|
||||
position = ::lseek(handle, offset, SEEK_SET);
|
||||
if (position != offset)
|
||||
{
|
||||
Firebird::system_call_failed::raise("lseek");
|
||||
}
|
||||
#endif
|
||||
if (position > size)
|
||||
size = position;
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::extend
|
||||
//
|
||||
// Increases the file size
|
||||
//
|
||||
|
||||
void TempFile::extend(size_t delta)
|
||||
{
|
||||
seek(size + delta);
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::read
|
||||
//
|
||||
// Reads bytes from file
|
||||
//
|
||||
|
||||
size_t TempFile::read(offset_t offset, void* buffer, size_t length)
|
||||
{
|
||||
fb_assert(offset + length <= size);
|
||||
seek(offset);
|
||||
#if defined(WIN_NT)
|
||||
DWORD bytes = 0;
|
||||
if (!ReadFile(handle, buffer, length, &bytes, NULL) ||
|
||||
bytes != length)
|
||||
{
|
||||
Firebird::system_call_failed::raise("ReadFile");
|
||||
}
|
||||
#else
|
||||
const int bytes = ::read(handle, buffer, length);
|
||||
if (bytes != length)
|
||||
{
|
||||
Firebird::system_call_failed::raise("read");
|
||||
}
|
||||
#endif
|
||||
position += bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::write
|
||||
//
|
||||
// Writes bytes to file
|
||||
//
|
||||
|
||||
size_t TempFile::write(offset_t offset, void* buffer, size_t length)
|
||||
{
|
||||
fb_assert(offset <= size);
|
||||
seek(offset);
|
||||
#if defined(WIN_NT)
|
||||
DWORD bytes = 0;
|
||||
if (!WriteFile(handle, buffer, length, &bytes, NULL) ||
|
||||
bytes != length)
|
||||
{
|
||||
Firebird::system_call_failed::raise("WriteFile");
|
||||
}
|
||||
#else
|
||||
const int bytes = ::write(handle, buffer, length);
|
||||
if (bytes != length)
|
||||
{
|
||||
Firebird::system_call_failed::raise("write");
|
||||
}
|
||||
#endif
|
||||
position += bytes;
|
||||
if (position > size)
|
||||
size = position;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
//
|
||||
// TempFile::unlink
|
||||
//
|
||||
// Unlinks the file
|
||||
//
|
||||
|
||||
void TempFile::unlink()
|
||||
{
|
||||
#if defined(WIN_NT)
|
||||
doUnlink = true;
|
||||
#else
|
||||
::unlink(filename.c_str());
|
||||
#endif
|
||||
}
|
86
src/common/classes/TempFile.h
Normal file
86
src/common/classes/TempFile.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Dmitry Yemanov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2006 Dmitry Yemanov <dimitr@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef TEMP_FILE_H
|
||||
#define TEMP_FILE_H
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../common/classes/File.h"
|
||||
|
||||
class TempFile : public Firebird::File {
|
||||
public:
|
||||
TempFile(MemoryPool& pool,
|
||||
const Firebird::PathName& prefix,
|
||||
const Firebird::PathName& directory,
|
||||
bool unlink = true)
|
||||
: filename(pool), position(0), size(0), doUnlink(unlink)
|
||||
{
|
||||
init(directory, prefix);
|
||||
}
|
||||
|
||||
TempFile(const Firebird::PathName& prefix,
|
||||
bool unlink = true)
|
||||
: position(0), size(0), doUnlink(unlink)
|
||||
{
|
||||
init("", prefix);
|
||||
}
|
||||
|
||||
~TempFile();
|
||||
|
||||
size_t read(offset_t, void*, size_t);
|
||||
size_t write(offset_t, void*, size_t);
|
||||
|
||||
void unlink();
|
||||
|
||||
offset_t getSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
void extend(size_t);
|
||||
|
||||
const Firebird::PathName& getName() const
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
static Firebird::PathName getTempPath();
|
||||
static Firebird::PathName create(const Firebird::PathName&);
|
||||
|
||||
private:
|
||||
void init(const Firebird::PathName&, const Firebird::PathName&);
|
||||
void seek(offset_t);
|
||||
|
||||
#if defined(WIN_NT)
|
||||
HANDLE handle;
|
||||
#else
|
||||
int handle;
|
||||
#endif
|
||||
|
||||
Firebird::PathName filename;
|
||||
int position;
|
||||
size_t size;
|
||||
bool doUnlink;
|
||||
};
|
||||
|
||||
#endif // TEMP_FILE_H
|
@ -52,13 +52,13 @@ const char* GCPolicyDefault = GCPolicyCooperative;
|
||||
const ConfigImpl::ConfigEntry ConfigImpl::entries[] =
|
||||
{
|
||||
{TYPE_STRING, "RootDirectory", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "SortMemBlockSize", (ConfigValue) 1048576}, // bytes
|
||||
{TYPE_INTEGER, "TempBlockSize", (ConfigValue) 1048576}, // bytes
|
||||
#ifdef SUPERSERVER
|
||||
{TYPE_INTEGER, "SortMemUpperLimit", (ConfigValue) 67108864}, // bytes
|
||||
{TYPE_INTEGER, "TempCacheLimit", (ConfigValue) 67108864}, // bytes
|
||||
#elif defined(WIN_NT) // win32 CS
|
||||
{TYPE_INTEGER, "SortMemUpperLimit", (ConfigValue) 8388608}, // bytes
|
||||
{TYPE_INTEGER, "TempCacheLimit", (ConfigValue) 8388608}, // bytes
|
||||
#else // non-win32 CS
|
||||
{TYPE_INTEGER, "SortMemUpperLimit", (ConfigValue) 0}, // bytes
|
||||
{TYPE_INTEGER, "TempCacheLimit", (ConfigValue) 0}, // bytes
|
||||
#endif
|
||||
{TYPE_BOOLEAN, "RemoteFileOpenAbility", (ConfigValue) false},
|
||||
{TYPE_INTEGER, "GuardianOption", (ConfigValue) 1},
|
||||
@ -279,14 +279,14 @@ const char* Config::getRootDirectory()
|
||||
return result ? result : sysConfig.root_dir;
|
||||
}
|
||||
|
||||
int Config::getSortMemBlockSize()
|
||||
int Config::getTempBlockSize()
|
||||
{
|
||||
return (int) sysConfig.values[KEY_SORT_MEM_BLOCK_SIZE];
|
||||
return (int) sysConfig.values[KEY_TEMP_BLOCK_SIZE];
|
||||
}
|
||||
|
||||
int Config::getSortMemUpperLimit()
|
||||
int Config::getTempCacheLimit()
|
||||
{
|
||||
return (int) sysConfig.values[KEY_SORT_MEM_UPPER_LIMIT];
|
||||
return (int) sysConfig.values[KEY_TEMP_CACHE_LIMIT];
|
||||
}
|
||||
|
||||
bool Config::getRemoteFileOpenAbility()
|
||||
|
@ -67,8 +67,8 @@ class Config
|
||||
enum ConfigKey
|
||||
{
|
||||
KEY_ROOT_DIRECTORY, // 0
|
||||
KEY_SORT_MEM_BLOCK_SIZE, // 1
|
||||
KEY_SORT_MEM_UPPER_LIMIT, // 2
|
||||
KEY_TEMP_BLOCK_SIZE, // 1
|
||||
KEY_TEMP_CACHE_LIMIT, // 2
|
||||
KEY_REMOTE_FILE_OPEN_ABILITY, // 3
|
||||
KEY_GUARDIAN_OPTION, // 4
|
||||
KEY_CPU_AFFINITY_MASK, // 5
|
||||
@ -127,14 +127,14 @@ public:
|
||||
static const char* getRootDirectory();
|
||||
|
||||
/*
|
||||
Block size for the sorting manager
|
||||
Allocation chunk for the temporary spaces
|
||||
*/
|
||||
static int getSortMemBlockSize();
|
||||
static int getTempBlockSize();
|
||||
|
||||
/*
|
||||
Memory usage limit for the sorting manager
|
||||
Caching limit for the temporary data
|
||||
*/
|
||||
static int getSortMemUpperLimit();
|
||||
static int getTempCacheLimit();
|
||||
|
||||
/*
|
||||
Whether remote (NFS) files can be opened
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "../common/config/dir_list.h"
|
||||
#include "../jrd/os/path_utils.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../jrd/TempSpace.h"
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
@ -270,13 +271,11 @@ void TempDirectoryList::initTemp()
|
||||
|
||||
const PathName TempDirectoryList::getConfigString() const
|
||||
{
|
||||
char tmp_buf[MAXPATHLEN];
|
||||
const char* value = Config::getTempDirectories();
|
||||
if (!value) {
|
||||
// Temporary directory configuration has not been defined.
|
||||
// Let's make default configuration.
|
||||
gds__temp_dir(tmp_buf);
|
||||
value = tmp_buf;
|
||||
return TempFile::getTempPath();
|
||||
}
|
||||
return PathName(value);
|
||||
}
|
||||
|
@ -36,17 +36,13 @@
|
||||
#include "../dudley/ddl_proto.h"
|
||||
#include "../dudley/hsh_proto.h"
|
||||
#include "../dudley/lex_proto.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../common/classes/TempFile.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef SMALL_FILE_NAMES
|
||||
const char* SCRATCH = "fb_q";
|
||||
#else
|
||||
const char* SCRATCH = "fb_query_";
|
||||
#endif
|
||||
|
||||
static int nextchar(void);
|
||||
static void retchar(SSHORT);
|
||||
@ -54,7 +50,7 @@ static int skip_white(void);
|
||||
|
||||
/* Input line control */
|
||||
|
||||
static FILE *input_file, *trace_file;
|
||||
static FILE *input_file, *trace_file = NULL;
|
||||
static TEXT *DDL_char, DDL_buffer[256], trace_file_name[MAXPATHLEN];
|
||||
|
||||
enum chr_types {
|
||||
@ -152,10 +148,10 @@ void LEX_fini(void)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
if (trace_file != NULL)
|
||||
if (trace_file != NULL) {
|
||||
fclose(trace_file);
|
||||
if (trace_file_name[0])
|
||||
unlink(trace_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -202,7 +198,7 @@ void LEX_get_text(UCHAR * buffer, TXT text)
|
||||
length = text->txt_length;
|
||||
|
||||
if (fseek(trace_file, start, 0)) {
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
DDL_err(275, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 275: fseek failed */
|
||||
}
|
||||
@ -211,7 +207,7 @@ void LEX_get_text(UCHAR * buffer, TXT text)
|
||||
while (length--)
|
||||
*p++ = getc(trace_file);
|
||||
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
}
|
||||
|
||||
|
||||
@ -228,13 +224,10 @@ void LEX_init( void *file)
|
||||
* scratch trace file to keep all input.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
#if !(defined WIN_NT)
|
||||
trace_file = (FILE*) gds__temp_file(TRUE, SCRATCH, 0);
|
||||
#else
|
||||
trace_file = (FILE*) gds__temp_file(TRUE, SCRATCH, trace_file_name);
|
||||
#endif
|
||||
if (trace_file == (FILE*) - 1)
|
||||
const Firebird::PathName filename = TempFile::create(SCRATCH);
|
||||
strcpy(trace_file_name, filename.c_str());
|
||||
trace_file = fopen(trace_file_name, "w+b");
|
||||
if (trace_file == (FILE*) -1)
|
||||
DDL_err(276, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 276: couldn't open scratch file */
|
||||
|
||||
@ -268,7 +261,7 @@ void LEX_put_text (FB_API_HANDLE blob, TXT text)
|
||||
length = text->txt_length;
|
||||
|
||||
if (fseek(trace_file, start, 0)) {
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
DDL_err(275, NULL, NULL, NULL, NULL, NULL);
|
||||
/* msg 275: fseek failed */
|
||||
}
|
||||
@ -287,7 +280,7 @@ void LEX_put_text (FB_API_HANDLE blob, TXT text)
|
||||
/* msg 277: isc_put_segment failed */
|
||||
}
|
||||
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,9 +57,9 @@
|
||||
#include "../gpre/gpre_meta.h"
|
||||
#include "../gpre/msc_proto.h"
|
||||
#include "../gpre/par_proto.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../gpre/gpreswi.h"
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../common/classes/TempFile.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@ -75,14 +75,10 @@ extern "C" {
|
||||
// Globals
|
||||
GpreGlobals gpreGlob;
|
||||
|
||||
#ifdef SMALL_FILE_NAMES
|
||||
const char* const SCRATCH = "fb_q";
|
||||
#else
|
||||
const char* const SCRATCH = "fb_query_";
|
||||
#endif
|
||||
const char* const SCRATCH = "fb_query_";
|
||||
|
||||
const char* const FOPEN_READ_TYPE = "r";
|
||||
const char* const FOPEN_WRITE_TYPE = "w";
|
||||
const char* const FOPEN_READ_TYPE = "r";
|
||||
const char* const FOPEN_WRITE_TYPE = "w";
|
||||
|
||||
static bool all_digits(const char*);
|
||||
static bool arg_is_string(SLONG, TEXT**, const TEXT*);
|
||||
@ -1387,16 +1383,11 @@ static SLONG compile_module( SLONG start_position, const TEXT* base_directory)
|
||||
fseek(input_file, start_position, 0);
|
||||
input_char = input_buffer;
|
||||
|
||||
#if !(defined WIN_NT)
|
||||
trace_file = (FILE *) gds__temp_file(TRUE, SCRATCH, 0);
|
||||
#else
|
||||
// PC-like platforms can't delete a file that is open. Therefore
|
||||
// we will save the name of the temp file for later deletion.
|
||||
Firebird::PathName filename = TempFile::create(SCRATCH);
|
||||
strcpy(trace_file_name, filename.c_str());
|
||||
trace_file = fopen(trace_file_name, "w+b");
|
||||
|
||||
trace_file = (FILE *) gds__temp_file(TRUE, SCRATCH, trace_file_name);
|
||||
#endif
|
||||
|
||||
if (trace_file == (FILE *) - 1) {
|
||||
if (trace_file == (FILE *) -1) {
|
||||
trace_file = NULL;
|
||||
CPR_error("Couldn't open scratch file");
|
||||
return 0;
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include <errno.h>
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../common/classes/ClumpletWriter.h"
|
||||
#include "../common/classes/TempFile.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@ -505,21 +506,6 @@ static const ri_actions ri_actions_all[] =
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
// We statically link ISQL against CLIB in MSVC6 and
|
||||
// hence we've got problems sharing file handles with FBCLIENT.
|
||||
// Since temp files are deleted by ISQL, let's create them here as well.
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
|
||||
static FILE* create_temp_file(const TEXT* string, TEXT* expanded_string)
|
||||
{
|
||||
gds__temp_dir(expanded_string);
|
||||
strcat(expanded_string, string);
|
||||
strcat(expanded_string, TEMP_PATTERN);
|
||||
mktemp(expanded_string);
|
||||
return fopen(expanded_string, "w+b");
|
||||
}
|
||||
#define gds__temp_file(flag, string, expanded_string) create_temp_file(string, expanded_string)
|
||||
#endif
|
||||
|
||||
|
||||
int CLIB_ROUTINE main(int argc,
|
||||
char* argv[])
|
||||
@ -2753,12 +2739,12 @@ static processing_state copy_table(TEXT* source,
|
||||
// If there is an alternate database, extract the domains
|
||||
const bool domain_flag = otherdb[0];
|
||||
|
||||
TEXT ftmp[MAXPATHLEN];
|
||||
isqlGlob.Out = (FILE*) gds__temp_file(TRUE, SCRATCH, ftmp);
|
||||
if (isqlGlob.Out == (FILE*) - 1) {
|
||||
Firebird::PathName ftmp = TempFile::create(SCRATCH);
|
||||
isqlGlob.Out = fopen(ftmp.c_str(), "w+b");
|
||||
if (isqlGlob.Out == (FILE*) -1) {
|
||||
// If we can't open a temp file then bail
|
||||
|
||||
ISQL_msg_get(FILE_OPEN_ERR, errbuf, ftmp);
|
||||
ISQL_msg_get(FILE_OPEN_ERR, errbuf, ftmp.c_str());
|
||||
STDERROUT(errbuf);
|
||||
Exit_value = FINI_ERROR;
|
||||
isqlGlob.Out = holdout;
|
||||
@ -2817,7 +2803,7 @@ static processing_state copy_table(TEXT* source,
|
||||
}
|
||||
}
|
||||
|
||||
unlink(ftmp);
|
||||
unlink(ftmp.c_str());
|
||||
isqlGlob.Out = holdout;
|
||||
|
||||
return (SKIP);
|
||||
@ -3097,8 +3083,10 @@ static void do_isql()
|
||||
|
||||
// File used to edit sessions
|
||||
|
||||
Ofp = (FILE*) gds__temp_file(TRUE, SCRATCH, Tmpfile);
|
||||
if (Ofp == (FILE*) - 1)
|
||||
const Firebird::PathName filename = TempFile::create(SCRATCH);
|
||||
strcpy(Tmpfile, filename.c_str());
|
||||
Ofp = fopen(Tmpfile, "w+b");
|
||||
if (Ofp == (FILE*) -1)
|
||||
{
|
||||
// If we can't open a temp file then bail
|
||||
|
||||
|
405
src/jrd/TempSpace.cpp
Normal file
405
src/jrd/TempSpace.cpp
Normal file
@ -0,0 +1,405 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Dmitry Yemanov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2006 Dmitry Yemanov <dimitr@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/config/dir_list.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/os/path_utils.h"
|
||||
|
||||
#include "../jrd/TempSpace.h"
|
||||
|
||||
// Const definitions
|
||||
|
||||
static const size_t MAX_FILE_SIZE = 1073741824; // 1GB
|
||||
|
||||
// Static definitions/initializations
|
||||
|
||||
Firebird::Mutex TempSpace::initMutex;
|
||||
Firebird::TempDirectoryList* TempSpace::tempDirs = NULL;
|
||||
size_t TempSpace::minBlockSize = 0;
|
||||
offset_t TempSpace::globalCacheUsage = 0;
|
||||
|
||||
//
|
||||
// Generic space block class
|
||||
//
|
||||
|
||||
TempSpace::Block::Block(Block* tail, size_t length)
|
||||
: next(NULL), size(length)
|
||||
{
|
||||
if (tail)
|
||||
{
|
||||
tail->next = this;
|
||||
}
|
||||
prev = tail;
|
||||
}
|
||||
|
||||
//
|
||||
// In-memory block class
|
||||
//
|
||||
|
||||
TempSpace::MemoryBlock::MemoryBlock(MemoryPool& pool, Block* tail, size_t length)
|
||||
: Block(tail, length)
|
||||
{
|
||||
ptr = FB_NEW(pool) char[length];
|
||||
}
|
||||
|
||||
TempSpace::MemoryBlock::~MemoryBlock()
|
||||
{
|
||||
delete[] ptr;
|
||||
}
|
||||
|
||||
size_t TempSpace::MemoryBlock::read(size_t offset, void* buffer, size_t length)
|
||||
{
|
||||
if (offset + length > size)
|
||||
{
|
||||
length = size - offset;
|
||||
}
|
||||
memcpy(buffer, (char*) ptr + offset, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
size_t TempSpace::MemoryBlock::write(size_t offset, void* buffer, size_t length)
|
||||
{
|
||||
if (offset + length > size)
|
||||
{
|
||||
length = size - offset;
|
||||
}
|
||||
memcpy((char*) ptr + offset, buffer, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
//
|
||||
// On-disk block class
|
||||
//
|
||||
|
||||
TempSpace::FileBlock::FileBlock(TempFile* f, Block* tail, size_t length)
|
||||
: Block(tail, length), file(f)
|
||||
{
|
||||
fb_assert(file);
|
||||
seek = file->getSize();
|
||||
}
|
||||
|
||||
TempSpace::FileBlock::~FileBlock()
|
||||
{
|
||||
}
|
||||
|
||||
size_t TempSpace::FileBlock::read(size_t offset, void* buffer, size_t length)
|
||||
{
|
||||
if (offset + length > size)
|
||||
{
|
||||
length = size - offset;
|
||||
}
|
||||
offset += seek;
|
||||
return file->read(offset, buffer, length);
|
||||
}
|
||||
|
||||
size_t TempSpace::FileBlock::write(size_t offset, void* buffer, size_t length)
|
||||
{
|
||||
if (offset + length > size)
|
||||
{
|
||||
length = size - offset;
|
||||
}
|
||||
offset += seek;
|
||||
return file->write(offset, buffer, length);
|
||||
}
|
||||
|
||||
//
|
||||
// TempSpace::TempSpace
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
|
||||
TempSpace::TempSpace(MemoryPool& p, const Firebird::PathName& prefix)
|
||||
: pool(p), tempFiles(p),
|
||||
head(NULL), tail(NULL), filePrefix(p, prefix),
|
||||
logicalSize(0), physicalSize(0), localCacheUsage(0)
|
||||
{
|
||||
if (!tempDirs)
|
||||
{
|
||||
Firebird::MutexLockGuard guard(initMutex);
|
||||
if (!tempDirs)
|
||||
{
|
||||
MemoryPool& p = *getDefaultMemoryPool();
|
||||
tempDirs = FB_NEW(p) Firebird::TempDirectoryList(p);
|
||||
minBlockSize = Config::getTempBlockSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TempSpace::~TempSpace
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
|
||||
TempSpace::~TempSpace()
|
||||
{
|
||||
while (head)
|
||||
{
|
||||
Block* temp = head->next;
|
||||
delete head;
|
||||
head = temp;
|
||||
}
|
||||
|
||||
globalCacheUsage -= localCacheUsage;
|
||||
|
||||
while (tempFiles.getCount())
|
||||
{
|
||||
delete tempFiles.pop();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TempSpace::read
|
||||
//
|
||||
// Reads bytes from the temporary space
|
||||
//
|
||||
|
||||
size_t TempSpace::read(offset_t offset, void* buffer, size_t length)
|
||||
{
|
||||
fb_assert(offset + length <= logicalSize);
|
||||
|
||||
if (length)
|
||||
{
|
||||
// search for the first needed block
|
||||
Block* block = findBlock(offset);
|
||||
|
||||
char* p = static_cast<char*>(buffer);
|
||||
size_t l = length;
|
||||
|
||||
// read data from the block chain
|
||||
for (Block* itr = block; itr && l;
|
||||
itr = itr->next, offset = 0)
|
||||
{
|
||||
const size_t n = itr->read(offset, p, l);
|
||||
p += n;
|
||||
l -= n;
|
||||
}
|
||||
|
||||
fb_assert(!l);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
//
|
||||
// TempSpace::write
|
||||
//
|
||||
// Writes bytes to the temporary space
|
||||
//
|
||||
|
||||
size_t TempSpace::write(offset_t offset, void* buffer, size_t length)
|
||||
{
|
||||
fb_assert(offset <= logicalSize);
|
||||
|
||||
if (offset + length > logicalSize)
|
||||
{
|
||||
// not enough space, allocate one more block
|
||||
extend(offset + length - logicalSize);
|
||||
}
|
||||
|
||||
if (length)
|
||||
{
|
||||
// search for the first needed block
|
||||
Block* block = findBlock(offset);
|
||||
|
||||
char* p = static_cast<char*>(buffer);
|
||||
size_t l = length;
|
||||
|
||||
// write data to as many blocks as necessary
|
||||
for (Block* itr = block; itr && l;
|
||||
itr = itr->next, offset = 0)
|
||||
{
|
||||
const size_t n = itr->write(offset, p, l);
|
||||
p += n;
|
||||
l -= n;
|
||||
}
|
||||
|
||||
fb_assert(!l);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
//
|
||||
// TempSpace::extend
|
||||
//
|
||||
// Increases size of the temporary space
|
||||
//
|
||||
|
||||
void TempSpace::extend(size_t size)
|
||||
{
|
||||
logicalSize += size;
|
||||
|
||||
if (logicalSize > physicalSize)
|
||||
{
|
||||
size = FB_ALIGN(size, minBlockSize);
|
||||
physicalSize += size;
|
||||
|
||||
Block* block = NULL;
|
||||
|
||||
if (globalCacheUsage + size <= Config::getTempCacheLimit())
|
||||
{
|
||||
try
|
||||
{
|
||||
// allocate block in virtual memory
|
||||
block = FB_NEW(pool) MemoryBlock(pool, tail, size);
|
||||
localCacheUsage += size;
|
||||
globalCacheUsage += size;
|
||||
}
|
||||
catch (const Firebird::BadAlloc&)
|
||||
{
|
||||
// not enough memory
|
||||
}
|
||||
}
|
||||
|
||||
if (!block)
|
||||
{
|
||||
// allocate block in the temp file
|
||||
TempFile* file = setupFile(size);
|
||||
block = FB_NEW(pool) FileBlock(file, tail, size);
|
||||
}
|
||||
|
||||
// append new block to the chain
|
||||
if (!head)
|
||||
{
|
||||
head = block;
|
||||
}
|
||||
tail = block;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TempSpace::findBlock
|
||||
//
|
||||
// Locates the space block corresponding to the given global offset
|
||||
//
|
||||
|
||||
TempSpace::Block* TempSpace::findBlock(offset_t& offset)
|
||||
{
|
||||
fb_assert(offset <= logicalSize);
|
||||
|
||||
Block* block = NULL;
|
||||
|
||||
if (offset < physicalSize / 2)
|
||||
{
|
||||
// walk forward
|
||||
block = head;
|
||||
while (block && offset >= block->size)
|
||||
{
|
||||
offset -= block->size;
|
||||
block = block->next;
|
||||
}
|
||||
fb_assert(block);
|
||||
}
|
||||
else
|
||||
{
|
||||
// walk backward
|
||||
block = tail;
|
||||
while (block && physicalSize - offset > block->size)
|
||||
{
|
||||
offset += block->size;
|
||||
block = block->prev;
|
||||
}
|
||||
fb_assert(block);
|
||||
offset -= physicalSize - block->size;
|
||||
}
|
||||
|
||||
fb_assert(offset <= block->size);
|
||||
return block;
|
||||
}
|
||||
|
||||
//
|
||||
// TempSpace::setupFile
|
||||
//
|
||||
// Allocates the required space in some temporary file
|
||||
//
|
||||
|
||||
TempFile* TempSpace::setupFile(size_t size)
|
||||
{
|
||||
TempFile* file = NULL;
|
||||
|
||||
for (size_t i = 0; i < tempDirs->getCount(); i++)
|
||||
{
|
||||
Firebird::PathName directory = (*tempDirs)[i];
|
||||
PathUtils::concatPath(directory, directory, PathUtils::dir_sep);
|
||||
|
||||
for (size_t j = 0; j < tempFiles.getCount(); j++)
|
||||
{
|
||||
Firebird::PathName dirname, filename;
|
||||
PathUtils::splitLastComponent(dirname, filename,
|
||||
tempFiles[j]->getName());
|
||||
PathUtils::concatPath(dirname, dirname, PathUtils::dir_sep);
|
||||
if (!directory.compare(dirname) &&
|
||||
tempFiles[j]->getSize() + size <= MAX_FILE_SIZE)
|
||||
{
|
||||
file = tempFiles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file)
|
||||
{
|
||||
fb_assert(size <= MAX_FILE_SIZE);
|
||||
file = FB_NEW(pool) TempFile(pool, filePrefix, directory);
|
||||
tempFiles.add(file);
|
||||
}
|
||||
|
||||
fb_assert(file);
|
||||
|
||||
try
|
||||
{
|
||||
file->extend(size);
|
||||
}
|
||||
catch (const Firebird::system_call_failed&)
|
||||
{
|
||||
if (i < tempDirs->getCount() - 1)
|
||||
{
|
||||
// no room, let's try another directory
|
||||
Firebird::string text;
|
||||
text.printf("Temporary directory %s has no free space, "
|
||||
"attempting to switch to the next configured one",
|
||||
directory.c_str());
|
||||
gds__log(text.c_str());
|
||||
file = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no room in all directories
|
||||
gds__log("No free space found in temporary directories");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if (file)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fb_assert(file);
|
||||
return file;
|
||||
}
|
113
src/jrd/TempSpace.h
Normal file
113
src/jrd/TempSpace.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Dmitry Yemanov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2006 Dmitry Yemanov <dimitr@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef TEMP_SPACE_H
|
||||
#define TEMP_SPACE_H
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../common/classes/TempFile.h"
|
||||
#include "../common/config/dir_list.h"
|
||||
|
||||
class TempSpace : public Firebird::File {
|
||||
public:
|
||||
TempSpace(MemoryPool&, const Firebird::PathName&);
|
||||
virtual ~TempSpace();
|
||||
|
||||
size_t read(offset_t, void*, size_t);
|
||||
size_t write(offset_t, void*, size_t);
|
||||
|
||||
void unlink() {}
|
||||
|
||||
offset_t getSize() const
|
||||
{
|
||||
return logicalSize;
|
||||
}
|
||||
|
||||
void extend(size_t);
|
||||
|
||||
private:
|
||||
|
||||
// Generic space block
|
||||
class Block {
|
||||
public:
|
||||
Block(Block*, size_t);
|
||||
virtual ~Block() {}
|
||||
|
||||
virtual size_t read(size_t, void*, size_t) = 0;
|
||||
virtual size_t write(size_t, void*, size_t) = 0;
|
||||
|
||||
Block *prev;
|
||||
Block *next;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
class MemoryBlock : public Block {
|
||||
public:
|
||||
MemoryBlock(MemoryPool&, Block*, size_t);
|
||||
~MemoryBlock();
|
||||
|
||||
size_t read(size_t, void*, size_t);
|
||||
size_t write(size_t, void*, size_t);
|
||||
|
||||
private:
|
||||
void* ptr;
|
||||
};
|
||||
|
||||
class FileBlock : public Block {
|
||||
public:
|
||||
FileBlock(TempFile*, Block*, size_t);
|
||||
~FileBlock();
|
||||
|
||||
size_t read(size_t, void*, size_t);
|
||||
size_t write(size_t, void*, size_t);
|
||||
|
||||
private:
|
||||
TempFile* file;
|
||||
size_t seek;
|
||||
};
|
||||
|
||||
Block* findBlock(offset_t&);
|
||||
TempFile* setupFile(size_t);
|
||||
|
||||
virtual bool adjustCacheSize(long) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryPool& pool;
|
||||
Firebird::PathName filePrefix;
|
||||
offset_t logicalSize;
|
||||
offset_t physicalSize;
|
||||
offset_t localCacheUsage;
|
||||
Block* head;
|
||||
Block* tail;
|
||||
Firebird::Array<TempFile*> tempFiles;
|
||||
|
||||
static Firebird::Mutex initMutex;
|
||||
static Firebird::TempDirectoryList* tempDirs;
|
||||
static size_t minBlockSize;
|
||||
static offset_t globalCacheUsage;
|
||||
};
|
||||
|
||||
#endif // TEMP_SPACE_H
|
199
src/jrd/dls.cpp
199
src/jrd/dls.cpp
@ -1,199 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: dls.cpp
|
||||
* DESCRIPTION: Temporary file management
|
||||
* The file contains set of functions that
|
||||
* are used to manage directory list.
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Inprise Corporation
|
||||
* and its predecessors. Portions created by Inprise Corporation are
|
||||
* Copyright (C) Inprise Corporation.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* 26-Sept-2001 Paul Beach - External File Directory Config. Parameter
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "../jrd/sort.h"
|
||||
#include "../jrd/dls_proto.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../jrd/file_params.h"
|
||||
#include "../common/config/dir_list.h"
|
||||
|
||||
using namespace Jrd;
|
||||
|
||||
static mutexed_dir_list DLS_cfg_tmpdir; /* directory list object */
|
||||
|
||||
/* Note that the only kind of writing permitted on the function_dir_list is
|
||||
* appending a new entry to the existing (possibly empty) list.
|
||||
* Therefore, we only need a write-lock to protect against
|
||||
* simultaneous updates: readers don't need a lock because they'll
|
||||
* always see either the old or the new state of the list, never an
|
||||
* in-between state.
|
||||
*
|
||||
* Also note that for this argument to be correct, it is necessary
|
||||
* that updaters NULL out the "next" pointer of a new element
|
||||
* *before*, not after, they append the element to the list, so that
|
||||
* the list is at all times terminated by a NULL pointer.
|
||||
*/
|
||||
|
||||
|
||||
bool DLS_get_temp_space(ULONG size, sort_work_file* sfb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* D L S _ g e t _ t e m p _ s p a c e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Allocate disk space with required size
|
||||
*
|
||||
**************************************/
|
||||
|
||||
bool result = false;
|
||||
|
||||
fb_assert(size > (ULONG) 0);
|
||||
fb_assert(sfb);
|
||||
|
||||
mutexed_dir_list* ptr = DLS_get_access();
|
||||
|
||||
Firebird::MutexLockGuard guard(ptr->mdls_mutex);
|
||||
|
||||
if (!sfb->sfb_dls) {
|
||||
/* allocate temp. space starting search from the begining of the dir_list */
|
||||
for (sfb->sfb_dls = ptr->mdls_dls;
|
||||
sfb->sfb_dls;
|
||||
sfb->sfb_dls = sfb->sfb_dls->dls_next)
|
||||
{
|
||||
if (size <= (sfb->sfb_dls->dls_size - sfb->sfb_dls->dls_inuse)) {
|
||||
sfb->sfb_dls->dls_inuse += size;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* allocate temp. space from the current dir_list entry */
|
||||
if (size <= (sfb->sfb_dls->dls_size - sfb->sfb_dls->dls_inuse)) {
|
||||
sfb->sfb_dls->dls_inuse += size;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void DLS_put_temp_space(sort_work_file* sfb)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* D L S _ p u t _ t e m p _ s p a c e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Release disk space occupied by sort file
|
||||
*
|
||||
**************************************/
|
||||
if (sfb && sfb->sfb_dls) {
|
||||
mutexed_dir_list* ptr = DLS_get_access();
|
||||
Firebird::MutexLockGuard guard(ptr->mdls_mutex);
|
||||
fb_assert(sfb->sfb_dls->dls_inuse >= sfb->sfb_file_size);
|
||||
if (sfb->sfb_dls->dls_inuse > sfb->sfb_file_size)
|
||||
sfb->sfb_dls->dls_inuse -= sfb->sfb_file_size;
|
||||
else
|
||||
sfb->sfb_dls->dls_inuse = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DLS_add_dir(ULONG size, const TEXT* dir_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* D L S _ a d d _ d i r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Add new entry to the temporary directory list.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
/* allocate dir_list structure */
|
||||
|
||||
dir_list* new_dls = (dir_list*) gds__alloc((SLONG) (sizeof(dir_list) +
|
||||
sizeof(TEXT) * strlen(dir_name)));
|
||||
if (!new_dls)
|
||||
return false;
|
||||
|
||||
strcpy(new_dls->dls_directory, dir_name);
|
||||
new_dls->dls_size = size;
|
||||
new_dls->dls_inuse = 0;
|
||||
new_dls->dls_next = NULL;
|
||||
|
||||
/* get access to directory list object */
|
||||
|
||||
mutexed_dir_list* mdls = DLS_get_access();
|
||||
|
||||
Firebird::MutexLockGuard guard(mdls->mdls_mutex);
|
||||
|
||||
/* add new entry to the end of list */
|
||||
|
||||
if (!mdls->mdls_dls) {
|
||||
mdls->mdls_dls = new_dls;
|
||||
}
|
||||
else {
|
||||
dir_list* dls_iterator = mdls->mdls_dls;
|
||||
while (dls_iterator->dls_next)
|
||||
dls_iterator = dls_iterator->dls_next;
|
||||
dls_iterator->dls_next = new_dls;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
mutexed_dir_list* DLS_get_access(void)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* D L S _ g e t _ a c c e s s
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Return pointer to the temporary file configuration
|
||||
*
|
||||
**************************************/
|
||||
|
||||
static bool is_initialized = false;
|
||||
if (!is_initialized) {
|
||||
is_initialized = true;
|
||||
Firebird::TempDirectoryList dir_list(*getDefaultMemoryPool());
|
||||
for (int i = 0; i < dir_list.getCount(); i++) {
|
||||
const Firebird::PathName& path = dir_list[i];
|
||||
DLS_add_dir(ALLROOM, path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return (&DLS_cfg_tmpdir);
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* PROGRAM: JRD Access Method
|
||||
* MODULE: dls_proto.h
|
||||
* DESCRIPTION: Temporary file management
|
||||
*
|
||||
* The contents of this file are subject to the Interbase Public
|
||||
* License Version 1.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.Inprise.com/IPL.html
|
||||
*
|
||||
* Software distributed under the License is distributed on an
|
||||
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Inprise Corporation
|
||||
* and its predecessors. Portions created by Inprise Corporation are
|
||||
* Copyright (C) Inprise Corporation.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*
|
||||
* 26-Sept-2001 Paul Beach - External File Directory Config. Parameter
|
||||
*/
|
||||
|
||||
#ifndef JRD_DLS_PROTO_H
|
||||
#define JRD_DLS_PROTO_H
|
||||
|
||||
#include "../jrd/sort.h"
|
||||
|
||||
bool DLS_get_temp_space(ULONG, Jrd::sort_work_file*);
|
||||
void DLS_put_temp_space(Jrd::sort_work_file*);
|
||||
bool DLS_add_dir(ULONG, const TEXT*);
|
||||
mutexed_dir_list* DLS_get_access(void);
|
||||
|
||||
#endif // JRD_DLS_PROTO_H
|
||||
|
@ -2801,10 +2801,7 @@ static void compute_agg_distinct(thread_db* tdbb, jrd_nod* node)
|
||||
|
||||
/* Sort the values already "put" to sort */
|
||||
|
||||
if (!SORT_sort(tdbb->tdbb_status_vector, asb_impure->iasb_sort_handle))
|
||||
{
|
||||
ERR_punt();
|
||||
}
|
||||
SORT_sort(tdbb->tdbb_status_vector, asb_impure->iasb_sort_handle);
|
||||
|
||||
/* Now get the sorted/projected values and compute the aggregate */
|
||||
|
||||
@ -3523,14 +3520,9 @@ static void init_agg_distinct(thread_db* tdbb, const jrd_nod* node)
|
||||
impure_agg_sort* asb_impure = (impure_agg_sort*) ((char*) request + asb->nod_impure);
|
||||
const sort_key_def* sort_key = asb->asb_key_desc;
|
||||
|
||||
sort_context* handle =
|
||||
SORT_init(tdbb->tdbb_status_vector,
|
||||
ROUNDUP_LONG(sort_key->skd_length), 1, 1, sort_key,
|
||||
reject_duplicate, 0,
|
||||
tdbb->tdbb_attachment, 0);
|
||||
|
||||
if (!(asb_impure->iasb_sort_handle = handle))
|
||||
ERR_punt();
|
||||
asb_impure->iasb_sort_handle =
|
||||
SORT_init(tdbb, ROUNDUP_LONG(sort_key->skd_length),
|
||||
1, 1, sort_key, reject_duplicate, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
127
src/jrd/gds.cpp
127
src/jrd/gds.cpp
@ -2350,133 +2350,6 @@ void API_ROUTINE gds__sqlcode_s(const ISC_STATUS* status_vector, ULONG* sqlcode)
|
||||
}
|
||||
|
||||
|
||||
void API_ROUTINE gds__temp_dir(TEXT* buffer)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g d s _ _ t e m p _ d i r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Return temporary directory.
|
||||
*
|
||||
**************************************/
|
||||
buffer[0] = 0;
|
||||
|
||||
gdsPrefixInit();
|
||||
|
||||
strcpy(buffer, fbTempDir); // safe - no BO
|
||||
}
|
||||
|
||||
|
||||
void* API_ROUTINE gds__temp_file(
|
||||
BOOLEAN stdio_flag, const TEXT* string,
|
||||
TEXT* expanded_string, TEXT* dir, BOOLEAN unlink_flag)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* g d s _ _ t e m p _ f i l e
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Create and open a temp file with a given location.
|
||||
* Unless the address of a buffer for the expanded file name string is
|
||||
* given, make up the file "pre-deleted". Return -1 on failure.
|
||||
* If unlink_flag is TRUE than file is marked as pre-deleted even if
|
||||
* expanded_string is not NULL.
|
||||
* NOTE
|
||||
* Function returns untyped handle that needs to be casted to either FILE
|
||||
* or used as file descriptor. This is ugly and needs to be fixed probably
|
||||
* via introducing two functions with different return types.
|
||||
*
|
||||
**************************************/
|
||||
TEXT temp_dir[MAXPATHLEN];
|
||||
|
||||
const TEXT* directory = dir;
|
||||
if (!directory) {
|
||||
gds__temp_dir(temp_dir);
|
||||
directory = temp_dir;
|
||||
}
|
||||
if (strlen(directory) >= MAXPATHLEN - strlen(string) - strlen(TEMP_PATTERN) - 2)
|
||||
return (void *)-1;
|
||||
|
||||
void* result;
|
||||
|
||||
#ifdef WIN_NT
|
||||
/* These are the characters used in temporary filenames. */
|
||||
static const char letters[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
_timeb t;
|
||||
_ftime(&t);
|
||||
__int64 randomness = t.time;
|
||||
randomness *= 1000;
|
||||
randomness += t.millitm;
|
||||
for (int tryCount = 0; tryCount < MAX_TMPFILE_TRIES; tryCount++) {
|
||||
char file_name[MAXPATHLEN];
|
||||
strcpy(file_name, directory);
|
||||
if (file_name[strlen(file_name) - 1] != '\\')
|
||||
strcat(file_name, "\\");
|
||||
strcat(file_name, string);
|
||||
char suffix[] = TEMP_PATTERN;
|
||||
__int64 temp = randomness;
|
||||
for (size_t i = 0; i < sizeof(suffix) - 1; i++) {
|
||||
suffix[i] = letters[temp % (sizeof(letters) - 1)];
|
||||
temp /= sizeof(letters) - 1;
|
||||
}
|
||||
strcat(file_name, suffix);
|
||||
if (expanded_string)
|
||||
strcpy(expanded_string, file_name);
|
||||
result = (void*)_sopen(file_name, _O_CREAT | _O_TRUNC | _O_RDWR |
|
||||
_O_BINARY | _O_SHORT_LIVED | _O_NOINHERIT | _O_EXCL |
|
||||
(expanded_string && !unlink_flag ? 0 : _O_TEMPORARY),
|
||||
_SH_DENYRW, _S_IREAD | _S_IWRITE);
|
||||
if ((int)result != -1 || (errno != EACCES && errno != EEXIST))
|
||||
break;
|
||||
randomness++;
|
||||
}
|
||||
if ((int)result == -1) return result;
|
||||
if (stdio_flag) {
|
||||
if (!(result = fdopen((int) result, "w+b")))
|
||||
return (void *)-1;
|
||||
}
|
||||
#else
|
||||
TEXT file_name[MAXPATHLEN];
|
||||
strcpy(file_name, directory);
|
||||
if (file_name[strlen(file_name) - 1] != '/')
|
||||
strcat(file_name, "/");
|
||||
strcat(file_name, string);
|
||||
strcat(file_name, TEMP_PATTERN);
|
||||
|
||||
#ifdef HAVE_MKSTEMP
|
||||
result = (void *)(IPTR)mkstemp(file_name);
|
||||
#else
|
||||
if (mktemp(file_name) == (char *)0)
|
||||
return (void *)-1;
|
||||
|
||||
do {
|
||||
result = (void *)open(file_name, O_RDWR | O_EXCL | O_CREAT);
|
||||
} while (result == (void *)-1 && errno == EINTR);
|
||||
#endif
|
||||
if (result == (void *)-1)
|
||||
return result;
|
||||
|
||||
if (stdio_flag)
|
||||
if (!(result = fdopen((int)(IPTR)result, "w+")))
|
||||
return (void *)-1;
|
||||
|
||||
if (expanded_string)
|
||||
strcpy(expanded_string, file_name);
|
||||
|
||||
if (!expanded_string || unlink_flag)
|
||||
unlink(file_name);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void API_ROUTINE gds__unregister_cleanup(FPTR_VOID_PTR routine, void *arg)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -118,9 +118,6 @@ void API_ROUTINE gds__qtoq(const void*, void*);
|
||||
void API_ROUTINE gds__register_cleanup(FPTR_VOID_PTR, void*);
|
||||
SLONG API_ROUTINE gds__sqlcode(const ISC_STATUS*);
|
||||
void API_ROUTINE gds__sqlcode_s(const ISC_STATUS*, ULONG*);
|
||||
void API_ROUTINE gds__temp_dir(TEXT*);
|
||||
void* API_ROUTINE gds__temp_file(BOOLEAN, const TEXT*, TEXT*, TEXT* = NULL,
|
||||
BOOLEAN = FALSE);
|
||||
void API_ROUTINE gds__unregister_cleanup(FPTR_VOID_PTR, void*);
|
||||
BOOLEAN API_ROUTINE gds__validate_lib_path(const TEXT*, const TEXT*, TEXT*,
|
||||
SLONG);
|
||||
|
@ -295,13 +295,11 @@ void IDX_create_index(
|
||||
void* callback_arg =
|
||||
(idx->idx_flags & idx_unique) ? &ifl_data : NULL;
|
||||
|
||||
sort_context* sort_handle = SORT_init(tdbb->tdbb_status_vector,
|
||||
key_length + sizeof(index_sort_record),
|
||||
2, 1, key_desc, callback, callback_arg,
|
||||
tdbb->tdbb_attachment, 0);
|
||||
sort_context* sort_handle =
|
||||
SORT_init(tdbb, key_length + sizeof(index_sort_record),
|
||||
2, 1, key_desc, callback, callback_arg, 0);
|
||||
|
||||
if (!sort_handle)
|
||||
ERR_punt();
|
||||
try {
|
||||
|
||||
jrd_rel* partner_relation = 0;
|
||||
USHORT partner_index_id = 0;
|
||||
@ -335,9 +333,8 @@ void IDX_create_index(
|
||||
|
||||
/* Loop thru the relation computing index keys. If there are old versions,
|
||||
find them, too. */
|
||||
bool cancel = false;
|
||||
temporary_key key;
|
||||
while (!cancel && DPM_next(tdbb, &primary, LCK_read, false, false)) {
|
||||
while (DPM_next(tdbb, &primary, LCK_read, false, false)) {
|
||||
if (transaction && !VIO_garbage_collect(tdbb, &primary, transaction))
|
||||
continue;
|
||||
if (primary.rpb_flags & rpb_deleted)
|
||||
@ -475,7 +472,7 @@ void IDX_create_index(
|
||||
|
||||
#ifdef SUPERSERVER
|
||||
if (--tdbb->tdbb_quantum < 0)
|
||||
cancel = JRD_reschedule(tdbb, 0, false);
|
||||
JRD_reschedule(tdbb, 0, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -483,17 +480,20 @@ void IDX_create_index(
|
||||
if (primary.getWindow(tdbb).win_flags & WIN_large_scan)
|
||||
--relation->rel_scan_count;
|
||||
|
||||
if (cancel || !SORT_sort(tdbb->tdbb_status_vector, sort_handle)) {
|
||||
SORT_fini(sort_handle, tdbb->tdbb_attachment);
|
||||
ERR_punt();
|
||||
}
|
||||
SORT_sort(tdbb->tdbb_status_vector, sort_handle);
|
||||
|
||||
if (ifl_data.ifl_duplicates > 0) {
|
||||
SORT_fini(sort_handle, tdbb->tdbb_attachment);
|
||||
ERR_post(isc_no_dup, isc_arg_string,
|
||||
ERR_cstring(index_name), 0);
|
||||
}
|
||||
|
||||
}
|
||||
catch (const Firebird::Exception& ex) {
|
||||
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
||||
SORT_fini(sort_handle, tdbb->tdbb_attachment);
|
||||
ERR_punt();
|
||||
}
|
||||
|
||||
BTR_create(tdbb, relation, idx, key_length, sort_handle, selectivity);
|
||||
|
||||
if (ifl_data.ifl_duplicates > 0) {
|
||||
|
@ -85,7 +85,6 @@
|
||||
#include "../jrd/cch_proto.h"
|
||||
#include "../jrd/cmp_proto.h"
|
||||
#include "../jrd/dbg_proto.h"
|
||||
#include "../jrd/dls_proto.h"
|
||||
#include "../jrd/dyn_proto.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/exe_proto.h"
|
||||
@ -123,6 +122,7 @@
|
||||
#include "../jrd/flags.h"
|
||||
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/config/dir_list.h"
|
||||
#include "../jrd/plugin_manager.h"
|
||||
#include "../jrd/db_alias.h"
|
||||
#include "../jrd/IntlManager.h"
|
||||
@ -762,7 +762,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
pageSpace->file =
|
||||
PIO_open(dbb, expanded_name, options.dpb_trace != 0, NULL, file_name);
|
||||
PIO_open(dbb, expanded_name, options.dpb_trace != 0, file_name);
|
||||
SHUT_init(dbb);
|
||||
PAG_header(file_name.c_str(), file_name.length(), false);
|
||||
INI_init2();
|
||||
@ -6075,24 +6075,10 @@ TEXT* JRD_num_attachments(TEXT* const buf, USHORT buf_len, USHORT flag,
|
||||
/* Get drive letters for temp directories */
|
||||
|
||||
if (flag == JRD_info_drivemask) {
|
||||
mutexed_dir_list* ptr = DLS_get_access();
|
||||
for (dir_list* dirs = ptr->mdls_dls; dirs; dirs = dirs->dls_next) {
|
||||
ExtractDriveLetter(dirs->dls_directory, &drive_mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get drive letters for sort files */
|
||||
|
||||
if (flag == JRD_info_drivemask)
|
||||
{
|
||||
for (const sort_context* scb = attach->att_active_sorts; scb;
|
||||
scb = scb->scb_next)
|
||||
{
|
||||
for (const sort_work_file* sfb = scb->scb_sfb; sfb;
|
||||
sfb = sfb->sfb_next)
|
||||
{
|
||||
ExtractDriveLetter(sfb->sfb_file_name, &drive_mask);
|
||||
}
|
||||
const Firebird::TempDirectoryList dirList;
|
||||
for (size_t i = 0; i < dirList.getCount(); i++) {
|
||||
const Firebird::PathName& path = dirList[i];
|
||||
ExtractDriveLetter(path.c_str(), &drive_mask);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1206,7 +1206,7 @@ bool BackupManager::actualize_state(thread_db* tdbb) throw()
|
||||
#endif
|
||||
try {
|
||||
NBAK_TRACE(("Open difference file"));
|
||||
diff_file = PIO_open(database, diff_name, false, NULL, diff_name);
|
||||
diff_file = PIO_open(database, diff_name, false, diff_name);
|
||||
}
|
||||
catch (const Firebird::Exception& ex) {
|
||||
#ifdef SUPERSERVER
|
||||
|
@ -37,7 +37,6 @@ struct blk;
|
||||
int PIO_add_file(Jrd::Database*, Jrd::jrd_file*, const Firebird::PathName&, SLONG);
|
||||
void PIO_close(Jrd::jrd_file*);
|
||||
Jrd::jrd_file* PIO_create(Jrd::Database*, const Firebird::PathName&, bool, bool);
|
||||
int PIO_connection(const Firebird::PathName&);
|
||||
int PIO_expand(const TEXT*, USHORT, TEXT*, size_t);
|
||||
void PIO_flush(Jrd::jrd_file*);
|
||||
void PIO_force_write(Jrd::jrd_file*, bool);
|
||||
@ -45,7 +44,7 @@ void PIO_header(Jrd::Database*, SCHAR*, int);
|
||||
SLONG PIO_max_alloc(Jrd::Database*);
|
||||
SLONG PIO_act_alloc(Jrd::Database*);
|
||||
Jrd::jrd_file* PIO_open(Jrd::Database*, const Firebird::PathName&, bool,
|
||||
blk*, const Firebird::PathName&);
|
||||
const Firebird::PathName&);
|
||||
bool PIO_read(Jrd::jrd_file*, Jrd::BufferDesc*, Ods::pag*, ISC_STATUS*);
|
||||
|
||||
#ifdef SUPERSERVER_V2
|
||||
|
@ -205,27 +205,6 @@ void PIO_close(jrd_file* main_file)
|
||||
}
|
||||
|
||||
|
||||
int PIO_connection(const Firebird::PathName& file_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P I O _ c o n n e c t i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Analyze a file specification and determine whether a page/lock
|
||||
* server is required and available. If so, return a "connection"
|
||||
* block. If not, return NULL.
|
||||
*
|
||||
* Note: The file name must have been expanded prior to this call.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
jrd_file* PIO_create(Database* dbb, const Firebird::PathName& string, bool overwrite, bool /*temporary*/)
|
||||
{
|
||||
/**************************************
|
||||
@ -562,7 +541,6 @@ SLONG PIO_act_alloc(Database* dbb)
|
||||
jrd_file* PIO_open(Database* dbb,
|
||||
const Firebird::PathName& string,
|
||||
bool trace_flag,
|
||||
blk* connection,
|
||||
const Firebird::PathName& file_name)
|
||||
{
|
||||
/**************************************
|
||||
@ -572,8 +550,7 @@ jrd_file* PIO_open(Database* dbb,
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Open a database file. If a "connection" block is provided, use
|
||||
* the connection to communication with a page/lock server.
|
||||
* Open a database file.
|
||||
*
|
||||
**************************************/
|
||||
int desc, flag;
|
||||
|
@ -62,7 +62,6 @@ entry(gds__attach_database)
|
||||
entry(perf_format)
|
||||
entry(perf_get_info)
|
||||
entry(perf_report)
|
||||
entry(gds__temp_file)
|
||||
entry(gds__vax_integer)
|
||||
entry(gds__encode)
|
||||
entry(gds__decode)
|
||||
|
@ -161,28 +161,6 @@ void PIO_close(jrd_file* main_file)
|
||||
}
|
||||
|
||||
|
||||
int PIO_connection(const Firebird::PathName& file_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* P I O _ c o n n e c t i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Analyze a file specification and determine whether a page/lock
|
||||
* server is required and available. If so, return a "connection"
|
||||
* block. If not, return NULL.
|
||||
*
|
||||
* Note: The file name must have been expanded prior to this call.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
jrd_file* PIO_create(Database* dbb, const Firebird::PathName& string, bool overwrite, bool temporary)
|
||||
{
|
||||
/**************************************
|
||||
@ -482,7 +460,6 @@ SLONG PIO_act_alloc(Database* dbb)
|
||||
jrd_file* PIO_open(Database* dbb,
|
||||
const Firebird::PathName& string,
|
||||
bool trace_flag,
|
||||
blk* connection,
|
||||
const Firebird::PathName& file_name)
|
||||
{
|
||||
/**************************************
|
||||
@ -492,9 +469,7 @@ jrd_file* PIO_open(Database* dbb,
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Open a database file. If a "connection"
|
||||
* block is provided, use the connection
|
||||
* to communicate with a page/lock server.
|
||||
* Open a database file.
|
||||
*
|
||||
**************************************/
|
||||
const TEXT* ptr = (string.hasData() ? string : file_name).c_str();
|
||||
|
@ -76,7 +76,6 @@
|
||||
#include "../jrd/os/path_utils.h"
|
||||
#include "../jrd/ibase.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
//#include "../jrd/license.h"
|
||||
#include "../jrd/lck.h"
|
||||
#include "../jrd/sdw.h"
|
||||
#include "../jrd/cch.h"
|
||||
@ -86,7 +85,6 @@
|
||||
#include "../jrd/all.h"
|
||||
#endif
|
||||
#include "../jrd/cch_proto.h"
|
||||
#include "../jrd/dls_proto.h"
|
||||
#include "../jrd/dpm_proto.h"
|
||||
#include "../jrd/err_proto.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
@ -98,6 +96,7 @@
|
||||
#include "../jrd/os/pio_proto.h"
|
||||
#include "../jrd/thd.h"
|
||||
#include "../jrd/isc_f_proto.h"
|
||||
#include "../jrd/TempSpace.h"
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Ods;
|
||||
@ -299,6 +298,7 @@ const SSHORT CLASS = CLASS_DARWIN_PPC;
|
||||
const SSHORT CLASS = CLASS_LINUX_AMD64;
|
||||
#endif
|
||||
|
||||
static const char* const SCRATCH = "fb_table_";
|
||||
|
||||
// CVC: Since nobody checks the result from this function (strange!), I changed
|
||||
// bool to void as the return type but left the result returned as comment.
|
||||
@ -493,7 +493,10 @@ USHORT PAG_add_file(const TEXT* file_name, SLONG start)
|
||||
#ifdef SUPPORT_RAW_DEVICES
|
||||
/* The following lines (taken from PAG_format_header) are needed to identify
|
||||
this file in raw_devices_validate_database as a valid database attachment. */
|
||||
MOV_time_stamp(reinterpret_cast<ISC_TIMESTAMP*>(header->hdr_creation_date));
|
||||
*(ISC_TIMESTAMP*)header->hdr_creation_date = Firebird::TimeStamp().value();
|
||||
// should we include milliseconds or not?
|
||||
//Firebird::TimeStamp::round_time(header->hdr_creation_date->timestamp_time, 0);
|
||||
|
||||
header->hdr_ods_version = ODS_VERSION | ODS_FIREBIRD_FLAG;
|
||||
header->hdr_implementation = CLASS;
|
||||
header->hdr_ods_minor = ODS_CURRENT;
|
||||
@ -632,38 +635,8 @@ void PAG_attach_temp_pages(thread_db* tdbb, USHORT pageSpaceID)
|
||||
PageSpace* pageSpaceTemp = dbb->dbb_page_manager.addPageSpace(pageSpaceID);
|
||||
if (!pageSpaceTemp->file)
|
||||
{
|
||||
mutexed_dir_list* dirs = DLS_get_access();
|
||||
|
||||
fb_assert(dirs);
|
||||
fb_assert(dirs->mdls_dls);
|
||||
dir_list* dir = dirs->mdls_dls;
|
||||
ULONG max_size = 0;
|
||||
for (dir_list* d = dir; d; d = d->dls_next)
|
||||
{
|
||||
const ULONG dir_size = d->dls_size - d->dls_inuse;
|
||||
if (max_size < dir_size)
|
||||
{
|
||||
max_size = dir_size;
|
||||
dir = d;
|
||||
}
|
||||
}
|
||||
|
||||
long hash = 0;
|
||||
TEXT* p = dbb->dbb_filename.begin(), *const e = dbb->dbb_filename.end();
|
||||
for (int i = 0; p < e; p++)
|
||||
{
|
||||
hash += *p << i;
|
||||
i = (i + 8) % 32;
|
||||
}
|
||||
|
||||
Firebird::PathName file_name(dir->dls_directory);
|
||||
if (file_name.at(file_name.length() - 1) != PathUtils::dir_sep) {
|
||||
file_name += PathUtils::dir_sep;
|
||||
}
|
||||
|
||||
file_name.printf("%sfb_tmp_%x_%x", file_name.c_str(), (unsigned int)pageSpaceID, hash);
|
||||
|
||||
pageSpaceTemp->file = PIO_create(dbb, file_name, false, true);
|
||||
Firebird::PathName file_name = TempFile::create(SCRATCH);
|
||||
pageSpaceTemp->file = PIO_create(dbb, file_name, true, true);
|
||||
PAG_format_pip(tdbb, *pageSpaceTemp);
|
||||
}
|
||||
}
|
||||
@ -972,7 +945,9 @@ void PAG_format_header(void)
|
||||
WIN window(HEADER_PAGE_NUMBER);
|
||||
header_page* header = (header_page*) CCH_fake(tdbb, &window, 1);
|
||||
header->hdr_header.pag_scn = 0;
|
||||
MOV_time_stamp(reinterpret_cast<ISC_TIMESTAMP*>(header->hdr_creation_date));
|
||||
*(ISC_TIMESTAMP*)header->hdr_creation_date = Firebird::TimeStamp().value();
|
||||
// should we include milliseconds or not?
|
||||
//Firebird::TimeStamp::round_time(header->hdr_creation_date->timestamp_time, 0);
|
||||
header->hdr_header.pag_type = pag_header;
|
||||
header->hdr_page_size = dbb->dbb_page_size;
|
||||
header->hdr_ods_version = ODS_VERSION | ODS_FIREBIRD_FLAG;
|
||||
@ -1523,11 +1498,7 @@ void PAG_init2(USHORT shadow_number)
|
||||
isc_arg_end);
|
||||
}
|
||||
|
||||
file->fil_next = PIO_open(dbb,
|
||||
file_name,
|
||||
false,
|
||||
0,
|
||||
file_name);
|
||||
file->fil_next = PIO_open(dbb, file_name, false, file_name);
|
||||
file->fil_max_page = last_page;
|
||||
file = file->fil_next;
|
||||
if (dbb->dbb_flags & DBB_force_write)
|
||||
|
@ -50,7 +50,6 @@
|
||||
#include "../jrd/lck.h"
|
||||
#include "../jrd/cch.h"
|
||||
#include "../jrd/tra.h"
|
||||
#include "../jrd/sort_mem.h"
|
||||
#include "gen/iberror.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../jrd/dpm_proto.h"
|
||||
@ -560,12 +559,7 @@ static void close_merge(thread_db* tdbb, RecordSource* rsb, irsb_mrg* impure)
|
||||
merge_file* mfb = &tail->irsb_mrg_file;
|
||||
sort_work_file* sfb = mfb->mfb_sfb;
|
||||
if (sfb) {
|
||||
if (sfb->sfb_file_name) {
|
||||
close(sfb->sfb_file);
|
||||
unlink(sfb->sfb_file_name);
|
||||
delete[] sfb->sfb_file_name;
|
||||
}
|
||||
delete sfb->sfb_mem;
|
||||
delete sfb->sfb_space;
|
||||
delete sfb;
|
||||
mfb->mfb_sfb = 0;
|
||||
}
|
||||
@ -1949,11 +1943,6 @@ static bool get_record(thread_db* tdbb,
|
||||
{
|
||||
select_node = NULL;
|
||||
}
|
||||
|
||||
EVL_expr(tdbb, column_node->nod_arg[0]);
|
||||
if (request->req_flags & req_null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (column_node && (request->req_flags & req_ansi_any))
|
||||
{
|
||||
@ -2413,11 +2402,9 @@ static UCHAR *get_sort(thread_db* tdbb, RecordSource* rsb
|
||||
|
||||
ULONG* data = 0;
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
SORT_get(tdbb->tdbb_status_vector, impure->irsb_sort_handle,
|
||||
&data, mode);
|
||||
SORT_get(tdbb->tdbb_status_vector, impure->irsb_sort_handle, &data, mode);
|
||||
#else
|
||||
SORT_get(tdbb->tdbb_status_vector, impure->irsb_sort_handle,
|
||||
&data);
|
||||
SORT_get(tdbb->tdbb_status_vector, impure->irsb_sort_handle, &data);
|
||||
#endif
|
||||
|
||||
return reinterpret_cast<UCHAR*>(data);
|
||||
@ -2736,20 +2723,17 @@ static void open_sort(thread_db* tdbb, RecordSource* rsb, irsb_sort* impure, UIN
|
||||
// Initialize for sort. If this is really a project operation,
|
||||
// establish a callback routine to reject duplicate records.
|
||||
|
||||
sort_context* handle = SORT_init(tdbb->tdbb_status_vector,
|
||||
map->smb_length,
|
||||
map->smb_keys,
|
||||
map->smb_keys,
|
||||
map->smb_key_desc,
|
||||
((map->smb_flags & SMB_project) ? reject : NULL), 0,
|
||||
tdbb->tdbb_attachment, max_records);
|
||||
|
||||
if (!(impure->irsb_sort_handle = handle))
|
||||
ERR_punt();
|
||||
impure->irsb_sort_handle =
|
||||
SORT_init(tdbb, map->smb_length, map->smb_keys,
|
||||
map->smb_keys, map->smb_key_desc,
|
||||
((map->smb_flags & SMB_project) ? reject : NULL),
|
||||
0, max_records);
|
||||
|
||||
// Mark sort_context with the impure area pointer
|
||||
|
||||
handle->scb_impure = impure;
|
||||
impure->irsb_sort_handle->scb_impure = impure;
|
||||
|
||||
try {
|
||||
|
||||
// Pump the input stream dry while pushing records into sort. For
|
||||
// each record, map all fields into the sort record. The reverse
|
||||
@ -2765,7 +2749,7 @@ static void open_sort(thread_db* tdbb, RecordSource* rsb, irsb_sort* impure, UIN
|
||||
|
||||
UCHAR* data = 0;
|
||||
SORT_put(tdbb->tdbb_status_vector, impure->irsb_sort_handle,
|
||||
(ULONG **) &data);
|
||||
(ULONG **) &data);
|
||||
|
||||
// Zero out the sort key. This solve a multitude of problems.
|
||||
|
||||
@ -2822,8 +2806,15 @@ static void open_sort(thread_db* tdbb, RecordSource* rsb, irsb_sort* impure, UIN
|
||||
}
|
||||
}
|
||||
|
||||
if (!SORT_sort(tdbb->tdbb_status_vector, impure->irsb_sort_handle))
|
||||
SORT_sort(tdbb->tdbb_status_vector, impure->irsb_sort_handle);
|
||||
|
||||
}
|
||||
catch (const Firebird::Exception& ex) {
|
||||
Firebird::stuff_exception(tdbb->tdbb_status_vector, ex);
|
||||
SORT_fini(impure->irsb_sort_handle, tdbb->tdbb_attachment);
|
||||
impure->irsb_sort_handle = NULL;
|
||||
ERR_punt();
|
||||
}
|
||||
|
||||
// For the sake of prudence, set all record parameter blocks to contain
|
||||
// the most recent format. This is will guarentee that all fields mapped
|
||||
@ -3184,12 +3175,12 @@ static ULONG read_merge_block(thread_db* tdbb, merge_file* mfb, ULONG block)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
fb_assert(mfb->mfb_sfb && mfb->mfb_sfb->sfb_file_name);
|
||||
fb_assert(mfb->mfb_sfb);
|
||||
|
||||
mfb->mfb_sfb->sfb_mem->read(tdbb->tdbb_status_vector,
|
||||
mfb->mfb_block_size * block,
|
||||
reinterpret_cast<char*>(mfb->mfb_block_data),
|
||||
mfb->mfb_block_size);
|
||||
SORT_read_block(tdbb->tdbb_status_vector, mfb->mfb_sfb,
|
||||
mfb->mfb_block_size * block,
|
||||
(UCHAR*) mfb->mfb_block_data,
|
||||
mfb->mfb_block_size);
|
||||
|
||||
return block;
|
||||
}
|
||||
@ -3389,26 +3380,14 @@ static void write_merge_block(thread_db* tdbb, merge_file* mfb, ULONG block)
|
||||
**************************************/
|
||||
sort_work_file* sfb = mfb->mfb_sfb;
|
||||
if (!sfb) {
|
||||
sfb = mfb->mfb_sfb = FB_NEW(*getDefaultMemoryPool()) sort_work_file;
|
||||
MemoryPool& pool = *getDefaultMemoryPool();
|
||||
sfb = mfb->mfb_sfb = FB_NEW(pool) sort_work_file;
|
||||
memset(sfb, 0, sizeof(sort_work_file));
|
||||
}
|
||||
if (!sfb->sfb_file_name) {
|
||||
TEXT file_name[MAXPATHLEN];
|
||||
|
||||
// Cast is ok because stdio_flag is false
|
||||
sfb->sfb_file = (int) (IPTR) gds__temp_file(FALSE, SCRATCH, file_name);
|
||||
if (sfb->sfb_file == -1)
|
||||
SORT_error(tdbb->tdbb_status_vector, sfb, "open", isc_io_error,
|
||||
errno);
|
||||
sfb->sfb_file_name =
|
||||
FB_NEW(*getDefaultMemoryPool()) char[strlen(file_name) + 1];
|
||||
strcpy(sfb->sfb_file_name, file_name);
|
||||
|
||||
sfb->sfb_mem = FB_NEW (*getDefaultMemoryPool()) SortMem(sfb, mfb->mfb_block_size);
|
||||
sfb->sfb_space = FB_NEW(pool) TempSpace(pool, SCRATCH);
|
||||
}
|
||||
|
||||
sfb->sfb_mem->write(tdbb->tdbb_status_vector,
|
||||
mfb->mfb_block_size * block,
|
||||
reinterpret_cast<char*>(mfb->mfb_block_data),
|
||||
mfb->mfb_block_size);
|
||||
SORT_write_block(tdbb->tdbb_status_vector, sfb,
|
||||
mfb->mfb_block_size * block,
|
||||
(UCHAR*) mfb->mfb_block_data,
|
||||
mfb->mfb_block_size);
|
||||
}
|
||||
|
@ -974,7 +974,7 @@ void SDW_start(const TEXT* file_name,
|
||||
try {
|
||||
|
||||
shadow_file =
|
||||
PIO_open(dbb, expanded_name, false, 0, file_name);
|
||||
PIO_open(dbb, expanded_name, false, file_name);
|
||||
|
||||
if (dbb->dbb_flags & DBB_force_write) {
|
||||
PIO_force_write(shadow_file, true);
|
||||
@ -1234,7 +1234,7 @@ static bool check_for_file(const SCHAR* name, USHORT length)
|
||||
// This use of PIO_open is NOT checked against DatabaseAccess configuration
|
||||
// parameter. It's not required, because here we only check for presence of
|
||||
// existing file, never really use (or create) it.
|
||||
jrd_file* temp_file = PIO_open(dbb, path, false, 0, path);
|
||||
jrd_file* temp_file = PIO_open(dbb, path, false, path);
|
||||
PIO_close(temp_file);
|
||||
} // try
|
||||
catch (const Firebird::Exception& ex) {
|
||||
|
743
src/jrd/sort.cpp
743
src/jrd/sort.cpp
File diff suppressed because it is too large
Load Diff
@ -29,12 +29,12 @@
|
||||
|
||||
#include "../jrd/jrd_blks.h"
|
||||
#include "../include/fb_blk.h"
|
||||
#include "../jrd/TempSpace.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
// Forward declaration
|
||||
struct sort_work_file;
|
||||
class SortMem;
|
||||
class Attachment;
|
||||
struct irsb_sort;
|
||||
struct merge_control;
|
||||
@ -203,7 +203,6 @@ struct run_control
|
||||
ULONG run_max_records; /* total number of records in run */
|
||||
#endif
|
||||
USHORT run_depth; /* Number of "elementary" runs */
|
||||
sort_work_file* run_sfb; /* Run sort file block */
|
||||
ULONG run_seek; /* Offset in file of run */
|
||||
ULONG run_size; /* Length of run in work file */
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
@ -212,7 +211,7 @@ struct run_control
|
||||
sort_record* run_record; /* Next record in run */
|
||||
SORTP* run_buffer; /* Run buffer */
|
||||
SORTP* run_end_buffer; /* End of buffer */
|
||||
ULONG run_buff_alloc; /* ALlocated buffer flag */
|
||||
bool run_buff_alloc; /* ALlocated buffer flag */
|
||||
};
|
||||
|
||||
/* Merge control block */
|
||||
@ -231,22 +230,17 @@ struct merge_control
|
||||
struct work_file_space
|
||||
{
|
||||
work_file_space* wfs_next;
|
||||
ULONG wfs_position; /* Starting position of free space */
|
||||
ULONG wfs_size; /* Length of free space */
|
||||
size_t wfs_position; /* Starting position of free space */
|
||||
size_t wfs_size; /* Length of free space */
|
||||
};
|
||||
|
||||
/* Sort work file control block */
|
||||
|
||||
struct sort_work_file
|
||||
{
|
||||
sort_work_file* sfb_next;
|
||||
int sfb_file; /* File descriptor */
|
||||
TEXT* sfb_file_name; /* ALLOC: File name for deletion */
|
||||
ULONG sfb_file_size; /* Real size of the work file */
|
||||
work_file_space* sfb_file_space; /* ALLOC: Available space in work file */
|
||||
work_file_space* sfb_free_wfs; /* ALLOC: Free space in work file */
|
||||
dir_list* sfb_dls; /* Place where file is created */
|
||||
SortMem* sfb_mem;
|
||||
TempSpace* sfb_space;
|
||||
};
|
||||
|
||||
/* Sort Context Block */
|
||||
@ -257,6 +251,7 @@ typedef bool (*FPTR_REJECT_DUP_CALLBACK)(const UCHAR*, const UCHAR*, void*);
|
||||
|
||||
struct sort_context
|
||||
{
|
||||
MemoryPool* scb_pool;
|
||||
sort_context* scb_next; /* Next known sort in system */
|
||||
SORTP *scb_memory; /* ALLOC: Memory for sort */
|
||||
SORTP *scb_end_memory; /* End of memory */
|
||||
@ -273,7 +268,7 @@ struct sort_context
|
||||
ULONG scb_key_length; /* Key length */
|
||||
ULONG scb_unique_length; /* Unique key length, used when duplicates eliminated */
|
||||
ULONG scb_records; /* Number of records */
|
||||
//UINT64 scb_max_records; // Maximum number of records to store . Unused.
|
||||
//UINT64 scb_max_records; // Maximum number of records to store. Unused.
|
||||
sort_work_file* scb_sfb; /* ALLOC: List of scratch files, if open */
|
||||
run_control* scb_runs; /* ALLOC: Run on scratch file, if any */
|
||||
merge_control* scb_merge; /* Top level merge block */
|
||||
|
@ -1,347 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Dmitry Yemanov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2002 Dmitry Yemanov <dimitr@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "firebird.h"
|
||||
|
||||
#include "../common/config/config.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../jrd/sort.h"
|
||||
#include "../jrd/sort_proto.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../jrd/sort_mem.h"
|
||||
|
||||
using namespace Jrd;
|
||||
|
||||
bool SortMem::is_initialized = false;
|
||||
|
||||
size_t SortMem::mem_block_size;
|
||||
size_t SortMem::mem_upper_limit;
|
||||
|
||||
size_t SortMem::mem_total_size = 0;
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Generic storage block implementation
|
||||
*/
|
||||
|
||||
SortMem::Block::Block(Block *tail, size_t length)
|
||||
: next(0), size(length)
|
||||
{
|
||||
// Link block with the chain
|
||||
if (tail)
|
||||
{
|
||||
tail->next = this;
|
||||
}
|
||||
prev = tail;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Virtual memory block implementation
|
||||
*/
|
||||
|
||||
SortMem::MemoryBlock::MemoryBlock(Block* tail, size_t length)
|
||||
: Block(tail, length)
|
||||
{
|
||||
// Allocate virtual memory block
|
||||
address = FB_NEW(*getDefaultMemoryPool()) char[size];
|
||||
}
|
||||
|
||||
SortMem::MemoryBlock::~MemoryBlock()
|
||||
{
|
||||
// Free virtual memory block
|
||||
delete[] address;
|
||||
}
|
||||
|
||||
size_t SortMem::MemoryBlock::read(ISC_STATUS *status, size_t position, char *buffer, size_t length)
|
||||
{
|
||||
// Read block from memory
|
||||
if (position + length > size)
|
||||
{
|
||||
length = size - position;
|
||||
}
|
||||
memcpy(buffer, address + position, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
size_t SortMem::MemoryBlock::write(ISC_STATUS *status, size_t position, char *buffer, size_t length)
|
||||
{
|
||||
// Write block to memory
|
||||
if (position + length > size)
|
||||
{
|
||||
length = size - position;
|
||||
}
|
||||
memcpy(address + position, buffer, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* File block implementation
|
||||
*/
|
||||
|
||||
SortMem::FileBlock::FileBlock(Block *tail, size_t length, sort_work_file* blk,
|
||||
size_t position)
|
||||
: Block(tail, length), file(blk), offset(position)
|
||||
{
|
||||
}
|
||||
|
||||
SortMem::FileBlock::~FileBlock()
|
||||
{
|
||||
}
|
||||
|
||||
size_t SortMem::FileBlock::read(ISC_STATUS *status, size_t position, char *buffer, size_t length)
|
||||
{
|
||||
// Read block from file
|
||||
if (position + length > size)
|
||||
{
|
||||
length = size - position;
|
||||
}
|
||||
return SORT_read_block(status, file, offset + position,
|
||||
reinterpret_cast<unsigned char*>(buffer), length) - offset - position;
|
||||
// _lseek(file->sfb_file, offset + position, SEEK_SET);
|
||||
// return _read(file->sfb_file, buffer, length);
|
||||
}
|
||||
|
||||
size_t SortMem::FileBlock::write(ISC_STATUS *status, size_t position, char *buffer, size_t length)
|
||||
{
|
||||
// Write block to file
|
||||
if (position + length > size)
|
||||
{
|
||||
length = size - position;
|
||||
}
|
||||
return SORT_write_block(status, file, offset + position,
|
||||
reinterpret_cast<unsigned char*>(buffer), length) - offset - position;
|
||||
// _lseek(file->sfb_file, offset + position, SEEK_SET);
|
||||
// return _write(file->sfb_file, buffer, length);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Virtual scratch file implementation
|
||||
*/
|
||||
|
||||
SortMem::SortMem(sort_work_file* blk, size_t size)
|
||||
: internal(blk), logical_size(0), physical_size(0), file_size(0), head(0), tail(0)
|
||||
{
|
||||
// Initialize itself
|
||||
if (!is_initialized)
|
||||
{
|
||||
mem_block_size = Config::getSortMemBlockSize();
|
||||
mem_upper_limit = Config::getSortMemUpperLimit();
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
// Allocate one block
|
||||
allocate(size);
|
||||
}
|
||||
|
||||
SortMem::~SortMem()
|
||||
{
|
||||
// Free all allocated blocks
|
||||
while (tail)
|
||||
{
|
||||
Block *block = tail->prev;
|
||||
delete tail;
|
||||
tail = block;
|
||||
}
|
||||
// We've just freed some memory
|
||||
mem_total_size -= physical_size - file_size;
|
||||
}
|
||||
|
||||
void SortMem::allocate(size_t size)
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
logical_size += size;
|
||||
bool mem_allocated = false;
|
||||
|
||||
// We've already got enough space to write data of the given size
|
||||
if (logical_size > physical_size)
|
||||
{
|
||||
Block *block;
|
||||
|
||||
// Calculate how much virtual memory we should allocate
|
||||
size_t smart_size = (mem_block_size > size) ? mem_block_size : size;
|
||||
|
||||
// Check whether virtual memory should be allocated or file should be used instead
|
||||
if (mem_total_size + smart_size <= mem_upper_limit)
|
||||
{
|
||||
// Allocate block in virtual memory
|
||||
try
|
||||
{
|
||||
block = FB_NEW (*getDefaultMemoryPool())
|
||||
MemoryBlock(tail, smart_size);
|
||||
mem_allocated = true;
|
||||
}
|
||||
// Not enough memory to allocate block
|
||||
catch (Firebird::BadAlloc)
|
||||
{
|
||||
// Check whether we can try to allocate less memory
|
||||
if (smart_size > size)
|
||||
{
|
||||
// Allocate minimal possible amount of memory once more
|
||||
smart_size = size;
|
||||
try
|
||||
{
|
||||
block = FB_NEW (*getDefaultMemoryPool())
|
||||
MemoryBlock(tail, smart_size);
|
||||
mem_allocated = true;
|
||||
}
|
||||
catch (Firebird::BadAlloc) {}
|
||||
}
|
||||
}
|
||||
if (mem_allocated)
|
||||
{
|
||||
physical_size += smart_size;
|
||||
// We've just allocated some virtual memory
|
||||
mem_total_size += smart_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mem_allocated)
|
||||
{
|
||||
// Allocate block on disk
|
||||
block = FB_NEW (*getDefaultMemoryPool())
|
||||
FileBlock(tail, size, internal, file_size);
|
||||
physical_size += size;
|
||||
// We've just allocated some file storage
|
||||
file_size += size;
|
||||
}
|
||||
|
||||
// Append new block to the chain
|
||||
if (!head)
|
||||
{
|
||||
head = block;
|
||||
}
|
||||
tail = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SortMem::Block* SortMem::seek(size_t &position)
|
||||
{
|
||||
Block *block = 0;
|
||||
|
||||
// Check whether the given offset is valid
|
||||
if (position < physical_size)
|
||||
{
|
||||
if (position < physical_size / 2)
|
||||
{
|
||||
// Let's walk forward
|
||||
block = head;
|
||||
while (block && position >= block->size)
|
||||
{
|
||||
position -= block->size;
|
||||
block = block->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Let's walk backward
|
||||
block = tail;
|
||||
while (block && physical_size - position > block->size)
|
||||
{
|
||||
position += block->size;
|
||||
block = block->prev;
|
||||
}
|
||||
position += block->size - physical_size;
|
||||
}
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
size_t SortMem::read(ISC_STATUS *status, size_t position, char *address, size_t length)
|
||||
{
|
||||
// If we'are not allowed to use memory, don't waste time
|
||||
// playing with all these memory blocks - just use scratch file and return
|
||||
if (!mem_upper_limit)
|
||||
{
|
||||
return SORT_read_block(status, internal, position,
|
||||
reinterpret_cast<unsigned char*>(address), length);
|
||||
}
|
||||
|
||||
size_t copied = 0;
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
// Search for the first needed block
|
||||
size_t pos = position;
|
||||
Block *block = seek(pos);
|
||||
fb_assert(block);
|
||||
|
||||
// Read data from as many blocks as necessary
|
||||
for (Block *itr = block; itr && length > 0; itr = itr->next, pos = 0)
|
||||
{
|
||||
size_t n = itr->read(status, pos, address, length);
|
||||
address += n;
|
||||
copied += n;
|
||||
length -= n;
|
||||
}
|
||||
fb_assert(!length);
|
||||
}
|
||||
|
||||
// New seek value
|
||||
return position + copied;
|
||||
}
|
||||
|
||||
size_t SortMem::write(ISC_STATUS *status, size_t position, char *address, size_t length)
|
||||
{
|
||||
// If we'are not allowed to use memory, don't waste time
|
||||
// playing with all these memory blocks - just use scratch file and return
|
||||
if (!mem_upper_limit)
|
||||
{
|
||||
return SORT_write_block(status, internal, position,
|
||||
reinterpret_cast<unsigned char*>(address), length);
|
||||
}
|
||||
|
||||
// There's probably not enough space, try to allocate one more block
|
||||
if (position + length >= logical_size)
|
||||
{
|
||||
allocate(position + length - logical_size);
|
||||
}
|
||||
|
||||
size_t copied = 0;
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
// Search for the first needed block
|
||||
size_t pos = position;
|
||||
Block *block = seek(pos);
|
||||
fb_assert(block);
|
||||
|
||||
// Write data to as many blocks as necessary
|
||||
for (Block *itr = block; itr && length > 0; itr = itr->next, pos = 0)
|
||||
{
|
||||
size_t n = itr->write(status, pos, address, length);
|
||||
address += n;
|
||||
copied += n;
|
||||
length -= n;
|
||||
}
|
||||
fb_assert(!length);
|
||||
}
|
||||
|
||||
// New seek value
|
||||
return position + copied;
|
||||
}
|
||||
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Dmitry Yemanov
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2002 Dmitry Yemanov <dimitr@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef JRD_SORT_MEM_H
|
||||
#define JRD_SORT_MEM_H
|
||||
|
||||
#include "../jrd/sort.h"
|
||||
|
||||
/*
|
||||
* Virtual scratch file
|
||||
*/
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class SortMem {
|
||||
private:
|
||||
|
||||
// Generic storage block
|
||||
class Block {
|
||||
|
||||
friend class SortMem;
|
||||
|
||||
protected:
|
||||
Block *prev;
|
||||
Block *next;
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
// Read bytes from the block into the given buffer
|
||||
virtual size_t read(ISC_STATUS*, size_t, char*, size_t) = 0;
|
||||
// Write bytes from the given buffer into the block
|
||||
virtual size_t write(ISC_STATUS*, size_t, char*, size_t) = 0;
|
||||
|
||||
Block(Block*, size_t);
|
||||
virtual ~Block() {}
|
||||
};
|
||||
|
||||
// Virtual memory block
|
||||
class MemoryBlock : public Block {
|
||||
private:
|
||||
// Base address of the allocated virtual memory
|
||||
char* address;
|
||||
|
||||
public:
|
||||
size_t read(ISC_STATUS*, size_t, char*, size_t);
|
||||
size_t write(ISC_STATUS*, size_t, char*, size_t);
|
||||
|
||||
MemoryBlock(Block*, size_t);
|
||||
~MemoryBlock();
|
||||
};
|
||||
|
||||
// File block
|
||||
class FileBlock : public Block {
|
||||
private:
|
||||
// Sort file block
|
||||
sort_work_file* file;
|
||||
// File offset
|
||||
size_t offset;
|
||||
|
||||
public:
|
||||
size_t read(ISC_STATUS*, size_t, char*, size_t);
|
||||
size_t write(ISC_STATUS*, size_t, char*, size_t);
|
||||
|
||||
FileBlock(Block*, size_t, sort_work_file*, size_t);
|
||||
~FileBlock();
|
||||
};
|
||||
|
||||
// Initialization flag
|
||||
static bool is_initialized;
|
||||
|
||||
// Virtual memory allocation values
|
||||
static size_t mem_block_size;
|
||||
static size_t mem_upper_limit;
|
||||
|
||||
// Total amount of allocated virtual memory
|
||||
static size_t mem_total_size;
|
||||
|
||||
sort_work_file* internal;
|
||||
|
||||
// Virtual scratch file size
|
||||
size_t logical_size;
|
||||
// Amount of storage space allocated for this scratch file
|
||||
size_t physical_size;
|
||||
// File size on disk
|
||||
size_t file_size;
|
||||
|
||||
// First block in chain
|
||||
Block *head;
|
||||
// Last block in chain
|
||||
Block *tail;
|
||||
|
||||
// Allocate one more block, if necessary
|
||||
void allocate(size_t);
|
||||
// Convert logical position to the physical one - pair [block, offset]
|
||||
Block* seek(size_t&);
|
||||
|
||||
public:
|
||||
// Read bytes from the scratch file
|
||||
size_t read(ISC_STATUS*, size_t, char*, size_t);
|
||||
// Write bytes into the scratch file
|
||||
size_t write(ISC_STATUS*, size_t, char*, size_t);
|
||||
|
||||
SortMem(sort_work_file*, size_t);
|
||||
~SortMem();
|
||||
};
|
||||
|
||||
} //namespace Jrd
|
||||
|
||||
#endif // JRD_SORT_MEM_H
|
||||
|
@ -32,24 +32,20 @@ namespace Jrd {
|
||||
}
|
||||
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
void SORT_diddle_key(UCHAR *, Jrd::sort_context*, bool);
|
||||
void SORT_get(ISC_STATUS*, Jrd::sort_context*, ULONG **, RSE_GET_MODE);
|
||||
void SORT_read_block(ISC_STATUS*, Jrd::sort_work_file*, ULONG, BLOB_PTR *, ULONG);
|
||||
void SORT_diddle_key(UCHAR *, Jrd::sort_context*, bool);
|
||||
void SORT_get(ISC_STATUS*, Jrd::sort_context*, ULONG **, RSE_GET_MODE);
|
||||
void SORT_read_block(ISC_STATUS*, Jrd::sort_work_file*, ULONG, BLOB_PTR *, ULONG);
|
||||
#else
|
||||
void SORT_get(ISC_STATUS*, Jrd::sort_context*, ULONG **);
|
||||
ULONG SORT_read_block(ISC_STATUS*, Jrd::sort_work_file*, ULONG, BLOB_PTR *,
|
||||
ULONG);
|
||||
void SORT_get(ISC_STATUS*, Jrd::sort_context*, ULONG **);
|
||||
ULONG SORT_read_block(ISC_STATUS*, Jrd::sort_work_file*, ULONG, BLOB_PTR *, ULONG);
|
||||
#endif
|
||||
|
||||
void SORT_error(ISC_STATUS*, Jrd::sort_work_file*, TEXT *, ISC_STATUS, int);
|
||||
void SORT_fini(Jrd::sort_context*, Jrd::Attachment*);
|
||||
Jrd::sort_context* SORT_init(ISC_STATUS*, USHORT, USHORT, USHORT, const Jrd::sort_key_def*,
|
||||
Jrd::FPTR_REJECT_DUP_CALLBACK, void*, Jrd::Attachment*, UINT64);
|
||||
void SORT_put(ISC_STATUS*, Jrd::sort_context*, ULONG **);
|
||||
void SORT_shutdown(Jrd::Attachment*);
|
||||
bool SORT_sort(ISC_STATUS*, Jrd::sort_context*);
|
||||
ULONG SORT_write_block(ISC_STATUS*, Jrd::sort_work_file*, ULONG, BLOB_PTR *,
|
||||
ULONG);
|
||||
void SORT_fini(Jrd::sort_context*, Jrd::Attachment*);
|
||||
Jrd::sort_context* SORT_init(Jrd::thread_db*, USHORT, USHORT, USHORT, const Jrd::sort_key_def*,
|
||||
Jrd::FPTR_REJECT_DUP_CALLBACK, void*, UINT64);
|
||||
void SORT_put(ISC_STATUS*, Jrd::sort_context*, ULONG **);
|
||||
void SORT_shutdown(Jrd::Attachment*);
|
||||
void SORT_sort(ISC_STATUS*, Jrd::sort_context*);
|
||||
ULONG SORT_write_block(ISC_STATUS*, Jrd::sort_work_file*, ULONG, BLOB_PTR *, ULONG);
|
||||
|
||||
#endif // JRD_SORT_PROTO_H
|
||||
|
||||
|
@ -37,10 +37,10 @@
|
||||
#include "../qli/hsh_proto.h"
|
||||
#include "../qli/lex_proto.h"
|
||||
#include "../qli/proc_proto.h"
|
||||
#include "../jrd/gds_proto.h"
|
||||
#include "../jrd/utl_proto.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../common/utils_proto.h"
|
||||
#include "../common/classes/TempFile.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
@ -59,11 +59,7 @@ const SLONG LIB$_INPSTRTRU = 0x15821c;
|
||||
#include <io.h> // isatty
|
||||
#endif
|
||||
|
||||
#ifdef SMALL_FILE_NAMES
|
||||
static const char* SCRATCH = "fb_q";
|
||||
#else
|
||||
static const char* SCRATCH = "fb_query_";
|
||||
#endif
|
||||
|
||||
const char* FOPEN_INPUT_TYPE = "r";
|
||||
|
||||
@ -160,17 +156,16 @@ void LEX_edit( SLONG start, SLONG stop)
|
||||
* push the scratch file on the input stack.
|
||||
*
|
||||
**************************************/
|
||||
TEXT filename[MAXPATHLEN];
|
||||
|
||||
FILE* scratch = (FILE*) gds__temp_file(TRUE, SCRATCH, filename);
|
||||
if (scratch == (FILE *) - 1)
|
||||
const Firebird::PathName filename = TempFile::create(SCRATCH);
|
||||
FILE* scratch = fopen(filename.c_str(), "w+b");
|
||||
if (scratch == (FILE *) -1)
|
||||
IBERROR(61); // Msg 61 couldn't open scratch file
|
||||
#ifdef WIN_NT
|
||||
stop--;
|
||||
#endif
|
||||
|
||||
if (fseek(trace_file, start, 0)) {
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
IBERROR(59); // Msg 59 fseek failed
|
||||
}
|
||||
|
||||
@ -183,12 +178,12 @@ void LEX_edit( SLONG start, SLONG stop)
|
||||
|
||||
fclose(scratch);
|
||||
|
||||
if (gds__edit(filename, TRUE))
|
||||
LEX_push_file(filename, true);
|
||||
if (gds__edit(filename.c_str(), TRUE))
|
||||
LEX_push_file(filename.c_str(), true);
|
||||
|
||||
unlink(filename);
|
||||
unlink(filename.c_str());
|
||||
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
}
|
||||
|
||||
|
||||
@ -352,7 +347,7 @@ void LEX_fini(void)
|
||||
*
|
||||
**************************************/
|
||||
|
||||
if (trace_file && (trace_file != (FILE *) - 1)) {
|
||||
if (trace_file) {
|
||||
fclose(trace_file);
|
||||
unlink(trace_file_name);
|
||||
}
|
||||
@ -545,8 +540,10 @@ void LEX_init(void)
|
||||
* scratch trace file to keep all input.
|
||||
*
|
||||
**************************************/
|
||||
trace_file = (FILE*) gds__temp_file(TRUE, SCRATCH, trace_file_name);
|
||||
if (trace_file == (FILE *) - 1)
|
||||
const Firebird::PathName filename = TempFile::create(SCRATCH);
|
||||
strcpy(trace_file_name, filename.c_str());
|
||||
trace_file = fopen(trace_file_name, "w+b");
|
||||
if (trace_file == (FILE *) -1)
|
||||
IBERROR(61); // Msg 61 couldn't open scratch file
|
||||
|
||||
QLI_token = (qli_tok*) ALLOCPV(type_tok, MAXSYMLEN);
|
||||
@ -726,7 +723,7 @@ void LEX_put_procedure(FB_API_HANDLE blob, SLONG start, SLONG stop)
|
||||
ISC_STATUS_ARRAY status_vector;
|
||||
|
||||
if (fseek(trace_file, start, 0)) {
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
IBERROR(62); // Msg 62 fseek failed
|
||||
}
|
||||
|
||||
@ -756,7 +753,7 @@ void LEX_put_procedure(FB_API_HANDLE blob, SLONG start, SLONG stop)
|
||||
ERRQ_bugcheck(58); // Msg 58 isc_put_segment failed
|
||||
}
|
||||
|
||||
fseek(trace_file, (SLONG) 0, 2);
|
||||
fseek(trace_file, 0, 2);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user