/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- dbeng_catalog_new
- dbeng_catalog_new_table
- dbeng_catalog_delete
- dbeng_catalog_init_table_details
- dbeng_catalog_term_table_details
- dbeng_catalog_table_details
- dbeng_catalog_fname
- dbeng_catalog_rep_list
- dbeng_catalog_list
- dbeng_catalog_tfind
- dbeng_catalog_ffind
- dbeng_catalog_open
- dbeng_catalog_close
/* Bbuuzzb low level system catalog management module.
Rick Smereka, Copyright (C) 2001-2004.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, get a copy via the Internet at
http://gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
You can contact the author via email at rsmereka@future-lab.com
Original QNX version. Nov/2001, Rick Smereka
Ported to Red Hat Linux, 32-bit Windows and DOS.
Dec/2001, Rick Smereka
Changed function 'dbeng_catalog_open' to open the catalog using
'dbeng_open_systable'. Added a parameter to 'dbeng_catalog_new_table'
consisting of a 'systable' flag. Feb/2002, Rick Smereka
Changed function 'dbeng_catalog_new_table' to create the empty table
and also create the catalog entry (if requested). Mar/2002,
Rick Smereka
Added function 'dbeng_catalog_list'. Aug/2002, Rick Smereka
Ported to Debian Linux. Nov/2002, Rick Smereka
Added functions 'dbeng_catalog_init_table_details',
'dbeng_catalog_term_table_details' and 'dbeng_catalog_table_details'.
Made function 'dbeng_catalog_rep_list' private.
Changed all logging calls from 'sys_log' to 'logman'.
Mar/2004, Rick Smereka */
#include "stdhead.h"
#include "dbeng.h"
#include "dbmess.h"
#include "dbengcfg.h"
#include "dbengcat.h"
#include "dbiocode.h"
/* global catalog table pointer */
struct dbeng_table *cat = DBENG_OT_NULL;
/* private functions */
static int dbeng_catalog_rep_list(char *);
static int dbeng_catalog_tfind(char *);
static int dbeng_catalog_ffind(char *);
static int dbeng_catalog_open(void);
static int dbeng_catalog_close(void);
int dbeng_catalog_new(char *tname, char *fname)
{
/* Create a new entry in the system catalog. The table name (logical)
is expected in 'tname' and the physical file name is
expected in 'fname'. The table name must be unique. Function returns
'DBENG_OK' if the catalog entry was successfully added,
an engine i/o code otherwise. */
char mname[] = "dbeng_catalog_new";
int ret;
logman("%s:enter", mname);
if (tname == (char *)NULL || !strlen(tname))
{
dbeng_io_code_log(mname, "exit:null or empty[tname]",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (fname == (char *)NULL || !strlen(fname))
{
dbeng_io_code_log(mname, "exit:null or empty[fname]",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
/* physical file must exist, not */
/* if (!exist(fname))
{
dbeng_io_code_log(mname, "exit:file not found", DBENG_NO_SUCH_FILE);
return(DBENG_NO_SUCH_FILE);
} */
/* open catalog */
if ((ret = dbeng_catalog_open()) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_catalog_open", ret);
return(ret);
}
/* attempt to locate an existing catalog entry with the same table name */
if (dbeng_catalog_tfind(tname) == DBENG_OK)
{
dbeng_io_code_log(mname, "exit:catalog rec already exists",
DBENG_CATALOG_ENTRY_EXISTS);
(void)dbeng_catalog_close();
return(DBENG_CATALOG_ENTRY_EXISTS);
}
/* add new catalog record */
if ((ret = dbeng_new(cat)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_new", ret);
(void)dbeng_catalog_close();
return(ret);
}
if ((ret = dbeng_put_field(cat, tname, DBENG_CATALOG_FIELD_TNAME))
!= DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_put_field[tname]", ret);
(void)dbeng_catalog_close();
return(ret);
}
if ((ret = dbeng_put_field(cat, fname, DBENG_CATALOG_FIELD_FNAME))
!= DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_put_field[fname]", ret);
(void)dbeng_catalog_close();
return(ret);
}
if ((ret = dbeng_write_recd(cat)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_write_recd", ret);
(void)dbeng_catalog_close();
return(ret);
}
/* close catalog */
if ((ret = dbeng_catalog_close()) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_catalog_close", ret);
return(ret);
}
dbeng_io_code_log(mname, "normal exit", DBENG_OK);
return(DBENG_OK);
}
int dbeng_catalog_new_table(char *iname, char *oname, int systable_flag)
{
/* Translate new table name(s) to the proper output
name. 'iname' may contain a single name or two
names comma delimited. A single name is assumed
to be the table physical file name. Two names are
assumed to be the table logical name followed by
the physical name. Upon success, the translated
name is placed into 'oname' which must be already
allocated to sufficient size. Function returns a
'dbeng' code. */
char mname[] = "dbeng_catalog_new_table", *pname, *lname;
int nwords, catalog_flag, ret;
logman("%s:enter", mname);
if (iname == (char *)NULL || !strlen(iname))
{
dbeng_io_code_log(mname, "exit:[iname]null or empty",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (oname == (char *)NULL)
{
dbeng_io_code_log(mname, "exit:[oname]null", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
oname[0] = EOS;
(void)dbeng_config_get_catalog_flag(&catalog_flag);
nwords = ll_words(iname, ',');
if (nwords == 1)
{
/* only physical file name given */
if (systable_flag)
/* if its a system table, use the same name */
strcpy(oname, iname);
if (!systable_flag)
if (catalog_flag)
/* if catalog is on, prefix the name with the file indicator */
sprintf(oname, "%c%s", DBENG_CATALOG_FNAME_IND, iname);
else
/* if catalog is not active, use same name */
strcpy(oname, iname);
if (!zcreate(iname))
{
dbeng_io_code_log(mname, "exit:cannot create table",
DBENG_CANNOT_CREATE_TABLE);
ret = DBENG_CANNOT_CREATE_TABLE;
}
else
{
if (systable_flag)
dbeng_io_code_log(mname, "exit:created systen table", DBENG_OK);
else
dbeng_io_code_log(mname, "exit:created table", DBENG_OK);
ret = DBENG_OK;
}
return(ret);
}
/* both logical and physical file names given, separate the names */
if ((pname = initstring(iname)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[pname]", DBENG_MEMORY_FAIL);
return(DBENG_MEMORY_FAIL);
}
if ((lname = initstring(iname)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[lname]", DBENG_MEMORY_FAIL);
free(pname);
return(DBENG_MEMORY_FAIL);
}
pname[0] = EOS;
lname[0] = EOS;
if (!ll_word(iname, lname, 1, ','))
{
dbeng_io_code_log(mname, "bad rc[FALSE] from ll_word[lname]",
DBENG_INTERNAL_ERROR);
free(lname);
free(pname);
return(DBENG_INTERNAL_ERROR);
}
if (!ll_word(iname, pname, 2, ','))
{
dbeng_io_code_log(mname, "bad rc[FALSE] from ll_word[pname]",
DBENG_INTERNAL_ERROR);
free(lname);
free(pname);
return(DBENG_INTERNAL_ERROR);
}
/* attempt to create the new table file using the physical file name */
if (!zcreate(pname))
{
dbeng_io_code_log(mname, "exit:error creating empty table",
DBENG_CANNOT_CREATE_TABLE);
free(lname);
free(pname);
return(DBENG_CANNOT_CREATE_TABLE);
}
/* attempt to create the catalog entry */
if ((ret = dbeng_catalog_new(lname, pname)) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_catalog_new", ret);
free(lname);
unlink(pname);
free(pname);
return(ret);
}
if (catalog_flag)
/* output logical name (into 'oname') if catalog is on */
strcpy(oname, lname);
else
/* output physical file name (no indicator) if catalog is off */
strcpy(oname, pname);
free(lname);
free(pname);
logman("%s:normal exit[0],oname=%s,l=%d", mname, oname,
strlen(oname));
return(DBENG_OK);
}
int dbeng_catalog_delete(char *tname)
{
/* Delete the catalog entry with the table name 'tname'.
Function returns 'DBENG_OK' upon success, an engine
i/o code otherwise. */
char mname[] = "dbeng_catalog_delete";
int ret;
logman("%s:enter", mname);
if (tname == (char *)NULL || !strlen(tname))
{
dbeng_io_code_log(mname, "exit:[tname]null or empty",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
/* open catalog */
if ((ret = dbeng_catalog_open()) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_catalog_open", ret);
return(ret);
}
/* find table name in catalog */
if ((ret = dbeng_catalog_tfind(tname)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:catalog entry not found", ret);
(void)dbeng_catalog_close();
return(ret);
}
if ((ret = dbeng_delete_recd(cat)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_delete_recd", ret);
(void)dbeng_catalog_close();
return(ret);
}
if ((ret = dbeng_catalog_close()) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_catalog_close", ret);
return(ret);
}
dbeng_io_code_log(mname, "normal exit", DBENG_OK);
return(DBENG_OK);
}
int dbeng_catalog_init_table_details(char *tname, int systable_flag,
struct dbengcat_details **det)
{
// Prepare the catalog details structure for use.
struct dbengcat_details *ot;
char mname[] = "dbeng_catalog_init_table_details";
int size;
if (tname == (char *)NULL || !strlen(tname))
{
dbeng_io_code_log(mname, "exit:null or empty[tname]",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (det == (struct dbengcat_details **)NULL)
{
dbeng_io_code_log(mname, "exit:null[**det]",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
size = sizeof(struct dbengcat_details);
// allocate structure
if ((ot = (struct dbengcat_details *)malloc(size)) ==
(struct dbengcat_details *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[ot]", DBENG_MEMORY_FAIL);
return(DBENG_MEMORY_FAIL);
}
if ((ot->logical_name = (char *)malloc(strlen(tname) + 1)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[ot->logical_name]",
DBENG_MEMORY_FAIL);
free(ot);
return(DBENG_MEMORY_FAIL);
}
strcpy(ot->logical_name, tname);
ot->systable_flag = systable_flag;
ot->physical_name = (char *)NULL;
ot->apack = 0;
#ifdef MULTIUSER
ot->rep_list = (char *)NULL;
#endif
*det = ot;
return(DBENG_OK);
}
int dbeng_catalog_term_table_details(struct dbengcat_details **det)
{
// De-allocate the entire catalog details structure.
struct dbengcat_details *ot;
char mname[] = "dbeng_catalog_term_table_details";
int ret;
if (det == (struct dbengcat_details **)NULL)
{
dbeng_io_code_log(mname, "null[**det]", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (*det == (struct dbengcat_details *)NULL)
{
dbeng_io_code_log(mname, "null[*det]", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
ot = *det;
free(ot->logical_name);
if (ot->physical_name != (char *)NULL)
free(ot->physical_name);
#ifdef MULTIUSER
if (ot->rep_list != (char *)NULL)
free(ot->rep_list);
#endif
free(*det);
*det = (struct dbengcat_details *)NULL;
return(DBENG_OK);
}
int dbeng_catalog_table_details(struct dbengcat_details *det)
{
/* Find a catalog entry by its logical table name and return all
catalog details. Function returns a 'dbeng' code. */
char mname[] = "dbeng_catalog_table_details", tmp[25];
int ret, catalog_flag, len;
if (det == (struct dbengcat_details *)NULL)
{
dbeng_io_code_log(mname, "null or empty[det]", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (det->logical_name == (char *)NULL || !strlen(det->logical_name))
{
dbeng_io_code_log(mname, "null or empty[det->logical_name]",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
logman("%s:enter", mname);
(void)dbeng_config_get_catalog_flag(&catalog_flag);
/* first, resolve supplied table name (could be logical or physical)
to the physical OS path/file name */
// if its a system table, copy name
if (det->systable_flag)
{
if ((det->physical_name = (char *)malloc(strlen(det->logical_name) + 1))
== (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[det->physical_name][1]",
DBENG_MEMORY_FAIL);
return(DBENG_MEMORY_FAIL);
}
strcpy(det->physical_name, det->logical_name);
dbeng_io_code_log(mname, "found system table", DBENG_OK);
return(DBENG_OK);
}
// if the catalog flag is not on, copy name
if (!catalog_flag)
{
if ((det->physical_name = (char *)malloc(strlen(det->logical_name) + 1))
== (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[det->physical_name][2]",
DBENG_MEMORY_FAIL);
return(DBENG_MEMORY_FAIL);
}
strcpy(det->physical_name, det->logical_name);
dbeng_io_code_log(mname, "catalog is not on", DBENG_OK);
return(DBENG_OK);
}
/* if the logical name starts with the file name indicator, copy
the same name minus the indicator */
if (det->logical_name[0] == DBENG_CATALOG_FNAME_IND)
{
if ((det->physical_name = (char *)malloc(strlen(det->logical_name) + 1))
== (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[det->physical_name][3]",
DBENG_MEMORY_FAIL);
return(DBENG_MEMORY_FAIL);
}
strcpy(det->physical_name, &det->logical_name[1]);
dbeng_io_code_log(mname, "exit:found physical file name", DBENG_OK);
return(DBENG_OK);
}
/* only other possibility is a catalog table name which we
look-up and get the physical file name */
if (cat != DBENG_OT_NULL)
{
dbeng_io_code_log(mname, "exit:catalog already open",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
/* open catalog */
if ((ret = dbeng_catalog_open()) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_catalog_open", ret);
return(ret);
}
// find catalog entry by its logical name
if ((ret = dbeng_catalog_tfind(det->logical_name)) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_catalog_tfind", ret);
(void)dbeng_catalog_close();
return(ret);
}
// get size of physical name
if ((ret = dbeng_field_size(cat, DBENG_CATALOG_FIELD_FNAME, &len)) !=
DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_field_size", ret);
(void)dbeng_catalog_close();
return(ret);
}
if ((det->physical_name = (char *)malloc(len + 1)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[det->physical_name][4]",
DBENG_MEMORY_FAIL);
(void)dbeng_catalog_close();
return(DBENG_MEMORY_FAIL);
}
// load physical file name
if ((ret = dbeng_get_field(cat, det->physical_name,
DBENG_CATALOG_FIELD_FNAME)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_get_field", ret);
free(det->physical_name);
det->physical_name = (char *)NULL;
(void)dbeng_catalog_close();
return(ret);
}
// load autopack value (ok if not present)
if ((ret = dbeng_get_field(cat, tmp, DBENG_CATALOG_FIELD_AUTOPACK)) !=
DBENG_OK)
if (ret == DBENG_NO_SUCH_FIELD)
{
det->apack = 0;
ret = DBENG_OK;
}
else
{
dbeng_io_code_log(mname, "exit:bad rc from dbeng_get_field", ret);
(void)dbeng_catalog_close();
return(ret);
}
else
{
if (!qatoi(tmp, &len))
{
dbeng_io_code_log(mname, "exit:autopack value not a number",
DBENG_INVALID_FUNCTION);
(void)dbeng_catalog_close();
return(DBENG_INVALID_FUNCTION);
}
det->apack = len;
}
// load replication list if present (database server only)
#ifdef MULTIUSER
if ((det->rep_list = (char *)malloc(DBENG_MAXRECFIELD)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[det->rep_list]",
DBENG_MEMORY_FAIL);
(void)dbeng_catalog_close();
return(DBENG_MEMORY_FAIL);
}
if ((ret = dbeng_catalog_rep_list(det->rep_list)) != DBENG_OK)
{
// ok if no replication entry
if (ret == DBENG_NO_REPLICATION_ENTRY)
{
dbeng_io_code_log(mname, "normal exit:no rep entry", DBENG_OK);
(void)dbeng_catalog_close();
free(det->rep_list);
det->rep_list = (char *)NULL;
return(DBENG_OK);
}
dbeng_io_code_log(mname, "exit:bad rc from dbeng_catalog_rep_list", ret);
(void)dbeng_catalog_close();
free(det->rep_list);
det->rep_list = (char *)NULL;
return(ret);
}
#endif
(void)dbeng_catalog_close();
dbeng_io_code_log(mname, "normal exit", ret);
return(ret);
}
int dbeng_catalog_fname(char *tname, char *fname)
{
/* Given a table name ('tname'), locate and return the physical
name ('fname') from the system catalog. Upon success, the
physical file name will be loaded into 'fname' which must
already be allocated to sufficient size. Note that this
function assumes the catalog is currently closed. Function
returns 'DBENG_OK' upon success, an engine i/o code
otherwise. */
char mname[] = "dbeng_catalog_fname";
int ret;
logman("%s:enter", mname);
if (tname == (char *)NULL || !strlen(tname))
{
dbeng_io_code_log(mname, "exit:'tname' null or empty",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (cat != DBENG_OT_NULL)
{
dbeng_io_code_log(mname, "exit:catalog already open",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (fname == (char *)NULL)
{
dbeng_io_code_log(mname, "exit:'fname' null", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
fname[0] = EOS;
/* open catalog */
if ((ret = dbeng_catalog_open()) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_catalog_open", ret);
return(ret);
}
/* find table name in catalog */
if ((ret = dbeng_catalog_tfind(tname)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad rc from dbeng_catalog_tfind", ret);
(void)dbeng_catalog_close();
return(ret);
}
/* load physical file name into 'fname' */
if ((ret = dbeng_get_field(cat, fname, DBENG_CATALOG_FIELD_FNAME)) !=
DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_get_field", ret);
(void)dbeng_catalog_close();
return(ret);
}
if ((ret = dbeng_catalog_close()) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_catalog_close", ret);
return(ret);
}
dbeng_io_code_log(mname, "normal exit", DBENG_OK);
return(DBENG_OK);
}
static int dbeng_catalog_rep_list(char *rep_list)
{
/* Get and return the replication list for the table. Upon success, the
replication list will be loaded into 'rep_list' which must
already be allocated to sufficient size. The format of
the replication list is:
port,tname
There may be multiple entries in the replication list.
Each entry will be delimited by 'DBENG_LIST_DELIM'.
Note that this function assumes the catalog is
currently open and the catalog file pointer is pointing
at the record in question. Function returns 'DBENG_OK' upon
success, an engine i/o code otherwise. */
char mname[] = "dbeng_catalog_rep_list";
char *before, *after, *wdata, *tname, port_char[10];
int ret, nentries, i, entry_size, nsubsubfields, port;
logman("%s:enter", mname);
if (rep_list == (char *)NULL)
{
dbeng_io_code_log(mname, "exit:'rep_list' null", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
rep_list[0] = EOS;
/* get number of entries in replication list */
if ((ret = dbeng_nsubfields(cat, DBENG_CATALOG_FIELD_REPLICATE, &nentries))
!= DBENG_OK)
{
if (ret == DBENG_NO_SUCH_FIELD)
{
dbeng_io_code_log(mname, "no replication entry",
DBENG_NO_REPLICATION_ENTRY);
return(DBENG_NO_REPLICATION_ENTRY);
}
dbeng_io_code_log(mname, "bad rc from dbeng_nsubfields", ret);
return(ret);
}
if ((before = (char *)malloc(DBENG_MAXRECFIELD)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[before]", DBENG_MEMORY_FAIL);
return(DBENG_MEMORY_FAIL);
}
if ((after = (char *)malloc(DBENG_MAXRECFIELD)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[after]", DBENG_MEMORY_FAIL);
free(before);
return(DBENG_MEMORY_FAIL);
}
before[0] = after[0] = EOS;
/* loop through all replication entries */
for(i = 1; i <= nentries; i++)
{
if ((ret = dbeng_subfield_size(cat, DBENG_CATALOG_FIELD_REPLICATE, i,
&entry_size)) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_subfield_size", ret);
free(before);
free(after);
return(ret);
}
if (entry_size <= 0)
{
logman("%s:entry[%d]:empty catalog entry,ignoring", mname, i);
continue;
}
/* must have exactly two subsubfields (port and table name) */
if ((ret = dbeng_nsubsubfields(cat, DBENG_CATALOG_FIELD_REPLICATE, i,
&nsubsubfields)) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_nsubsubfields", ret);
free(before);
free(after);
return(ret);
}
if (nsubsubfields != 2)
{
logman("%s:replication entry invalid", mname);
continue;
}
if ((wdata = (char *)malloc(entry_size + 1)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[wdata]", DBENG_MEMORY_FAIL);
free(before);
free(after);
return(ret);
}
if ((tname = (char *)malloc(entry_size + 1)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[tname]", DBENG_MEMORY_FAIL);
free(wdata);
free(before);
free(after);
return(ret);
}
if ((ret = dbeng_get_subsubfield(cat, port_char,
DBENG_CATALOG_FIELD_REPLICATE, i,
DBENG_CATALOG_SSF_PORT)) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_get_subsubfield[port]",
ret);
free(tname);
free(wdata);
free(before);
free(after);
return(ret);
}
/* port number must be valid and in range */
if (!qatoi(port_char, &port))
{
logman("%s:entry[%d]:non-numeric port,ignoring", mname, i);
free(tname);
free(wdata);
continue;
}
if (port <= 0)
{
logman("%s:entry[%d]:out of range[port],ignoring", mname, i);
free(tname);
free(wdata);
continue;
}
if ((ret = dbeng_get_subsubfield(cat, tname,
DBENG_CATALOG_FIELD_REPLICATE, i,
DBENG_CATALOG_SSF_TNAME)) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_get_subsubfield[tname]",
ret);
free(tname);
free(wdata);
free(before);
free(after);
return(ret);
}
sprintf(wdata, "%d,%s", port, tname);
free(tname);
if (!ll_wordput(before, after, wdata, i, DBENG_LIST_DELIM))
{
dbeng_io_code_log(mname, "error putting list item",
DBENG_INTERNAL_ERROR);
free(before);
free(after);
free(wdata);
return(DBENG_INTERNAL_ERROR);
}
free(wdata);
strcpy(before, after);
}
strcpy(rep_list, after);
free(before);
free(after);
if (!strlen(rep_list))
{
dbeng_io_code_log(mname, "exit:list is empty",
DBENG_NO_REPLICATION_ENTRY);
return(DBENG_NO_REPLICATION_ENTRY);
}
dbeng_io_code_log(mname, "normal exit", DBENG_OK);
return(DBENG_OK);
}
int dbeng_catalog_list(char *pat, char *list_out)
{
/* Return a list of matching table names (logical) from
the system catalog. List is returned in 'list_out'
which must be already allocated to sufficient size.
The list is delimited by 'DEBNG_LIST_DELIM'. Each
entry in the list contains the logical name
followed by the file path/name (physical name). The two
fields in the list are delimited by a comma.
The parameter 'pat' may contain a pattern
acceptable to the 'pmatch' function. If 'pat' is
'NULL' or empty, all entries from the catalog
will be returned. Function returns a 'dbeng' code. */
char *before, *after, *wdata, *tname, *fname;
char mname[] = "dbeng_catalog_list";
long rec_cnt, dummy;
int cnt, is_pat, ret, process;
logman("%s:enter", mname);
if (list_out == NULL)
{
dbeng_io_code_log(mname, "null[list_out]", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
is_pat = (pat == (char *)NULL || !strlen(pat)) ? FALSE : TRUE;
list_out[0] = EOS;
/* open catalog */
if ((ret = dbeng_catalog_open()) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_catalog_open", ret);
return(ret);
}
/* get the number of records */
if ((ret = dbeng_rec_count(cat, &rec_cnt, &dummy)) != DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_count_rec(cat)", ret);
(void)dbeng_catalog_close();
return(ret);
}
/* it is not an error if there are no records */
if (rec_cnt == 0L)
{
dbeng_io_code_log(mname, "list is empty", DBENG_OK);
(void)dbeng_catalog_close();
return(DBENG_OK);
}
if ((before = (char *)malloc(DBENG_MAXRECFIELD)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[before]", DBENG_MEMORY_FAIL);
(void)dbeng_catalog_close();
return(DBENG_MEMORY_FAIL);
}
if ((after = (char *)malloc(DBENG_MAXRECFIELD)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[after]", DBENG_MEMORY_FAIL);
free(before);
(void)dbeng_catalog_close();
return(DBENG_MEMORY_FAIL);
}
if ((wdata = (char *)malloc(1023)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[wdata]", DBENG_MEMORY_FAIL);
free(before);
free(after);
(void)dbeng_catalog_close();
return(DBENG_MEMORY_FAIL);
}
if ((tname = (char *)malloc(1023)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[tname]", DBENG_MEMORY_FAIL);
free(before);
free(after);
free(wdata);
(void)dbeng_catalog_close();
return(DBENG_MEMORY_FAIL);
}
if ((fname = (char *)malloc(1023)) == (char *)NULL)
{
dbeng_io_code_log(mname, "alloc fail[fname]", DBENG_MEMORY_FAIL);
free(before);
free(after);
free(wdata);
free(tname);
(void)dbeng_catalog_close();
return(DBENG_MEMORY_FAIL);
}
before[0] = after[0] = EOS;
cnt = 1;
if ((ret = dbeng_goto_top(cat)) != DBENG_OK)
{
dbeng_io_code_log(mname, "error going top of catalog", ret);
free(before);
free(after);
free(wdata);
free(tname);
free(fname);
(void)dbeng_catalog_close();
return(ret);
}
/* get first record */
if ((ret = dbeng_get_recd(cat)) != DBENG_OK)
{
dbeng_io_code_log(mname, "error getting first record", ret);
free(before);
free(after);
free(wdata);
free(tname);
free(fname);
(void)dbeng_catalog_close();
return(ret);
}
while(ret == DBENG_OK)
{
if ((ret = dbeng_get_field(cat, tname, DBENG_CATALOG_FIELD_TNAME)) !=
DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_get_field(tname)", ret);
free(before);
free(after);
free(wdata);
free(tname);
free(fname);
(void)dbeng_catalog_close();
return(ret);
}
process = TRUE;
/* match to pattern (if supplied) */
if (is_pat)
if (!pmatch(pat, tname))
process = FALSE;
if (process)
{
if ((ret = dbeng_get_field(cat, fname, DBENG_CATALOG_FIELD_FNAME)) !=
DBENG_OK)
{
dbeng_io_code_log(mname, "bad rc from dbeng_get_field(fname)", ret);
free(before);
free(after);
free(wdata);
free(tname);
free(fname);
(void)dbeng_catalog_close();
return(ret);
}
sprintf(wdata, "%s,%s", tname, fname);
if (!ll_wordput(before, after, wdata, cnt, DBENG_LIST_DELIM))
{
dbeng_io_code_log(mname, "error putting list item",
DBENG_INTERNAL_ERROR);
free(before);
free(after);
free(wdata);
free(tname);
free(fname);
(void)dbeng_catalog_close();
return(DBENG_INTERNAL_ERROR);
}
cnt++;
strcpy(before, after);
}
/* get next record */
ret = dbeng_get_recd(cat);
}
(void)dbeng_catalog_close();
strcpy(list_out, after);
free(before);
free(after);
free(wdata);
free(tname);
free(fname);
dbeng_io_code_log(mname, "normal exit", DBENG_OK);
return(DBENG_OK);
}
/* private functions */
static int dbeng_catalog_tfind(char *tname)
{
/* Locate the table by table name ('tname') within the
system catalog. The system catalog table is assumed
to be already open. It is an error if the catalog
is found to be closed. Function returns 'DBENG_OK' if
the table name was found, an engine i/o code
otherwise. */
char mname[] = "dbeng_catalog_tfind";
int ret;
logman("%s:enter", mname);
if (tname == (char *)NULL || !strlen(tname))
{
dbeng_io_code_log(mname, "exit:'tname' null or empty",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (cat == DBENG_OT_NULL)
{
dbeng_io_code_log(mname, "exit:catalog not open", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if ((ret = dbeng_goto_top(cat)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_goto_top", ret);
return(ret);
}
if ((ret = dbeng_find_field(cat, 0, tname, DBENG_CATALOG_FIELD_TNAME))
== DBENG_EOF)
ret = DBENG_NO_CATALOG_ENTRY;
dbeng_io_code_log(mname, "normal exit", ret);
return(ret);
}
static int dbeng_catalog_ffind(char *fname)
{
/* Locate the table by file name ('fname') within the
system catalog. The system catalog table is assumed
to be already open. It is an error if the catalog
is found to be closed. Function returns 'DBENG_OK' if
the file name was found, an engine i/o code
otherwise. */
char mname[] = "dbeng_catalog_ffind";
int ret;
logman("%s:enter", mname);
if (fname == (char *)NULL || !strlen(fname))
{
dbeng_io_code_log(mname, "exit:'fname' null or empty",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if (cat == DBENG_OT_NULL)
{
dbeng_io_code_log(mname, "exit:catalog not open", DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if ((ret = dbeng_goto_top(cat)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:bad ret from dbeng_goto_top", ret);
return(ret);
}
if ((ret = dbeng_find_field(cat, 0, fname, DBENG_CATALOG_FIELD_FNAME))
== DBENG_EOF)
ret = DBENG_NO_CATALOG_ENTRY;
dbeng_io_code_log(mname, "normal exit", ret);
return(ret);
}
static int dbeng_catalog_open(void)
{
/* Open the catalog table and load the 'cat' pointer. Function
returns 'DBENG_OK' upon success, an engine i/o code
otherwise. */
char mname[] = "dbeng_catalog_open";
char *cat_table;
int ret;
int tid;
logman("%s:enter", mname);
if (cat != DBENG_OT_NULL)
{
dbeng_io_code_log(mname, "exit:catalog already open",
DBENG_INVALID_FUNCTION);
return(DBENG_INVALID_FUNCTION);
}
if ((cat_table = (char *)malloc(DBENG_PATH_LIMIT + 1)) == (char *)NULL)
{
dbeng_io_code_log(mname, "exit:alloc fail[cat_table]",
DBENG_MEMORY_FAIL);
return(DBENG_MEMORY_FAIL);
}
/* get catalog table name */
if ((ret = dbeng_config_get_catalog(cat_table)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:error getting catalog name", ret);
free(cat_table);
return(ret);
}
if ((ret = dbeng_open_systable(cat_table, &tid)) != DBENG_OK)
{
dbeng_io_code_log(mname, "exit:error opening catalog", ret);
free(cat_table);
return(ret);
}
free(cat_table);
/* load table pointer from tid */
if ((cat = dbeng_atid_lookup(tid)) == DBENG_OT_NULL)
{
dbeng_io_code_log(mname, "exit:dbeng_atid_lookup error on catalog table",
DBENG_UNABLE_TO_OPEN);
return(DBENG_UNABLE_TO_OPEN);
}
dbeng_io_code_log(mname, "normal exit", DBENG_OK);
return(DBENG_OK);
}
static int dbeng_catalog_close(void)
{
/* Close the system catalog table. Function returns 'DBENG_OK'
upon success, an engine i/o code otherwise. */
char mname[] = "dbeng_catalog_close";
int ret;
logman("%s:enter", mname);
if (cat == DBENG_OT_NULL)
{
dbeng_io_code_log(mname, "exit:catalog table not open", DBENG_NO_SUCH_FILE);
return(DBENG_NO_SUCH_FILE);
}
ret = dbeng_close_table(cat);
cat = DBENG_OT_NULL;
dbeng_io_code_log(mname, "normal exit", ret);
return(ret);
}