8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-25 00:03:03 +01:00
firebird-mirror/src/jrd/dls.cpp
alexpeshkoff 1591a54e5e Thread cleanup:
1. Added macros to declare thread entrypoints
2. THD_mutex_* functions use Firebird::Mutex
3. Thread local storage use fb_tls.h
2004-06-08 13:41:08 +00:00

229 lines
5.7 KiB
C++

/*
* 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();
#ifdef V4_THREADING
if (!ptr->mdls_mutex_init) {
V4_MUTEX_INIT(ptr->mdls_mutex);
ptr->mdls_mutex_init = true;
}
V4_MUTEX_LOCK(ptr->mdls_mutex);
#endif
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;
}
}
#ifdef V4_THREADING
V4_MUTEX_UNLOCK(ptr->mdls_mutex);
#endif
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();
#ifdef V4_THREADING
fb_assert(ptr->mdls_mutex_init);
V4_MUTEX_LOCK(ptr->mdls_mutex);
#endif
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;
#ifdef V4_THREADING
V4_MUTEX_UNLOCK(ptr->mdls_mutex);
#endif
}
}
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();
#ifdef V4_THREADING
/* lock mutex, initialize it in case of the first access */
if (!mdls->mdls_mutex_init) {
V4_MUTEX_INIT(mdls->mdls_mutex);
mdls->mdls_mutex_init = true;
}
V4_MUTEX_LOCK(mdls->mdls_mutex);
#endif
/* 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;
}
#ifdef V4_THREADING
/* release lock */
V4_MUTEX_UNLOCK(mdls->mdls_mutex);
#endif
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;
for (int i = 0; i < dir_list.Count(); i++) {
DLS_add_dir(dir_list[i].second, dir_list[i].first.c_str());
}
}
return (&DLS_cfg_tmpdir);
}