mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-27 20:43:03 +01:00
356 lines
8.5 KiB
C++
356 lines
8.5 KiB
C++
/*
|
|
* PROGRAM: JRD Access Method
|
|
* MODULE: dls.c
|
|
* 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"
|
|
|
|
static MDLS DLS_cfg_tmpdir = { NULL, FALSE }; /* directory list object */
|
|
|
|
/* Note that the only kind of writing permitted on the fdls 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.
|
|
*/
|
|
|
|
/* external function directory list */
|
|
|
|
static FDLS first_fdls = { 0, { 0 } };
|
|
static BOOLEAN fdls_mutex_init = FALSE;
|
|
static MUTX_T fdls_mutex[1];
|
|
|
|
/* external file directory list */
|
|
|
|
static EDLS first_edls = { 0, { 0 } };
|
|
static BOOLEAN edls_mutex_init = FALSE;
|
|
static MUTX_T edls_mutex[1];
|
|
|
|
BOOLEAN DLS_get_temp_space(ULONG size, SFB sfb)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D L S _ g e t _ t e m p _ s p a c e
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Allocate disk space with required size
|
|
*
|
|
**************************************/
|
|
|
|
MDLS *ptr;
|
|
BOOLEAN result = FALSE;
|
|
|
|
assert(size > (ULONG) 0);
|
|
assert(sfb);
|
|
|
|
ptr = DLS_get_access();
|
|
|
|
if (!ptr->mdls_mutex_init) {
|
|
V4_MUTEX_INIT(ptr->mdls_mutex);
|
|
ptr->mdls_mutex_init = TRUE;
|
|
}
|
|
|
|
V4_MUTEX_LOCK(ptr->mdls_mutex);
|
|
if (!sfb->sfb_dls) {
|
|
/* allocate temp. space starting search from the begining of the dls 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 dls entry */
|
|
if (size <= (sfb->sfb_dls->dls_size - sfb->sfb_dls->dls_inuse)) {
|
|
sfb->sfb_dls->dls_inuse += size;
|
|
result = TRUE;
|
|
}
|
|
}
|
|
V4_MUTEX_UNLOCK(ptr->mdls_mutex);
|
|
|
|
return (result);
|
|
}
|
|
|
|
|
|
void DLS_put_temp_space(SFB 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
|
|
*
|
|
**************************************/
|
|
|
|
MDLS *ptr;
|
|
|
|
if (sfb && sfb->sfb_dls) {
|
|
ptr = DLS_get_access();
|
|
assert(ptr->mdls_mutex_init);
|
|
V4_MUTEX_LOCK(ptr->mdls_mutex);
|
|
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;
|
|
V4_MUTEX_UNLOCK(ptr->mdls_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN API_ROUTINE DLS_add_dir(ULONG size, TEXT * dir_name)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D L S _ a d d _ d i r
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Add new entry to the temporary directory list.
|
|
*
|
|
**************************************/
|
|
|
|
MDLS *mdls;
|
|
DLS new_dls, dls;
|
|
|
|
/* allocate dls structure */
|
|
|
|
new_dls = (DLS) gds__alloc((SLONG) (sizeof(struct dls) +
|
|
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 = (DLS) NULL;
|
|
|
|
/* get access to directory list object */
|
|
|
|
mdls = DLS_get_access();
|
|
|
|
/* 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);
|
|
|
|
/* add new entry to the end of list */
|
|
|
|
if (!mdls->mdls_dls) {
|
|
mdls->mdls_dls = new_dls;
|
|
}
|
|
else {
|
|
dls = mdls->mdls_dls;
|
|
while (dls->dls_next)
|
|
dls = dls->dls_next;
|
|
dls->dls_next = new_dls;
|
|
}
|
|
|
|
/* release lock */
|
|
|
|
V4_MUTEX_UNLOCK(mdls->mdls_mutex);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
MDLS *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
|
|
*
|
|
**************************************/
|
|
|
|
return (&DLS_cfg_tmpdir);
|
|
}
|
|
|
|
BOOLEAN DLS_add_func_dir(TEXT * directory_name)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D L S _ a d d _ f u n c _ d i r
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Add an external function directory name to the list
|
|
* Return TRUE if successful, FALSE if no memory available.
|
|
*
|
|
**************************************/
|
|
FDLS *current_fdls, *new_fdls;
|
|
size_t name_length;
|
|
|
|
name_length = strlen(directory_name);
|
|
|
|
new_fdls = (FDLS *) gds__alloc((SLONG) (sizeof(FDLS) + name_length));
|
|
if (!new_fdls)
|
|
return FALSE;
|
|
|
|
new_fdls->fdls_next = 0;
|
|
strcpy(new_fdls->fdls_directory, directory_name);
|
|
|
|
/* Lock the mutex for the directory list, initializing it if
|
|
this is the first access. */
|
|
|
|
if (!fdls_mutex_init) {
|
|
V4_MUTEX_INIT(fdls_mutex);
|
|
fdls_mutex_init = TRUE;
|
|
}
|
|
|
|
/* Note that when the distinction is implemented, the
|
|
following should be a write lock. */
|
|
V4_MUTEX_LOCK(fdls_mutex);
|
|
|
|
/* Append the new fdls to the list, then release the mutex */
|
|
current_fdls = &first_fdls;
|
|
while (current_fdls->fdls_next)
|
|
current_fdls = current_fdls->fdls_next;
|
|
current_fdls->fdls_next = new_fdls;
|
|
|
|
/* Release the (write) lock for the fdls linked list. */
|
|
V4_MUTEX_UNLOCK(fdls_mutex);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
FDLS *DLS_get_func_dirs(void)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D L S _ g e t _ f u n c _ d i r s
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Return pointer to the first function directory entry
|
|
*
|
|
**************************************/
|
|
|
|
return first_fdls.fdls_next;
|
|
}
|
|
|
|
|
|
BOOLEAN DLS_add_file_dir(TEXT *directory_name)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D L S _ a d d _ f i l e _ d i r
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Add an external file directory name to the list
|
|
* Return TRUE if successful, FALSE if no memory available.
|
|
*
|
|
**************************************/
|
|
EDLS *current_edls, *new_edls;
|
|
size_t name_length;
|
|
|
|
name_length = strlen(directory_name);
|
|
|
|
new_edls = (EDLS *) gds__alloc((SLONG) (sizeof(EDLS) + name_length));
|
|
if (!new_edls)
|
|
return FALSE;
|
|
|
|
new_edls->edls_next = 0;
|
|
strcpy(new_edls->edls_directory, directory_name);
|
|
|
|
/* Lock the mutex for the directory list, initializing it if
|
|
this is the first access. */
|
|
|
|
if (!edls_mutex_init)
|
|
{
|
|
V4_MUTEX_INIT(edls_mutex);
|
|
edls_mutex_init = TRUE;
|
|
}
|
|
|
|
/* Note that when the distinction is implemented, the
|
|
following should be a write lock. */
|
|
|
|
V4_MUTEX_LOCK(edls_mutex);
|
|
|
|
/* Append the new edls to the list, then release the mutex */
|
|
|
|
current_edls = &first_edls;
|
|
while (current_edls->edls_next)
|
|
current_edls = current_edls->edls_next;
|
|
current_edls->edls_next = new_edls;
|
|
|
|
/* Release the (write) lock for the fdls linked list. */
|
|
|
|
V4_MUTEX_UNLOCK(edls_mutex);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
EDLS *DLS_get_file_dirs(void)
|
|
{
|
|
/**************************************
|
|
*
|
|
* D L S _ g e t _ f i l e _ d i r s
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Return pointer to the first external file directory entry
|
|
*
|
|
**************************************/
|
|
|
|
return first_edls.edls_next;
|
|
}
|