Skip to content

Commit 0c2eb20

Browse files
author
Michael Meskes
committed
ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp> added thread-safe
descriptor handling
1 parent f1d37a9 commit 0c2eb20

15 files changed

+345
-84
lines changed

src/interfaces/ecpg/ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2247,5 +2247,10 @@ Sun, 30 Sep 2007 13:37:31 +0200
22472247

22482248
- Applied another patch by ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp>
22492249
to get memory allocation thread-safe. He also did some cleaning up.
2250+
2251+
Tue, 02 Oct 2007 11:32:25 +0200
2252+
2253+
- ITAGAKI Takahiro <itagaki.takahiro@oss.ntt.co.jp> added thread-safe
2254+
descriptor handling
22502255
- Set ecpg library version to 6.0.
22512256
- Set ecpg version to 4.4.

src/interfaces/ecpg/ecpglib/connect.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.44 2007/09/30 11:38:48 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.45 2007/10/02 09:49:59 meskes Exp $ */
22

33
#define POSTGRES_ECPG_INTERNAL
44
#include "postgres_fe.h"
@@ -447,6 +447,7 @@ ECPGconnect(int lineno, int c, const char *name, const char *user, const char *p
447447

448448
this->cache_head = NULL;
449449
this->prep_stmts = NULL;
450+
this->descriptors = NULL;
450451

451452
if (all_connections == NULL)
452453
this->next = NULL;

src/interfaces/ecpg/ecpglib/descriptor.c

Lines changed: 102 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,69 @@
11
/* dynamic SQL support routines
22
*
3-
* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.23 2007/08/14 10:01:52 meskes Exp $
3+
* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.24 2007/10/02 09:49:59 meskes Exp $
44
*/
55

66
#define POSTGRES_ECPG_INTERNAL
77
#include "postgres_fe.h"
88
#include "pg_type.h"
99

10+
#include "ecpg-pthread-win32.h"
1011
#include "ecpgtype.h"
1112
#include "ecpglib.h"
1213
#include "ecpgerrno.h"
1314
#include "extern.h"
1415
#include "sqlca.h"
1516
#include "sql3types.h"
1617

17-
struct descriptor *all_descriptors = NULL;
18+
static void descriptor_free(struct descriptor *desc);
19+
static void descriptor_deallocate_all(struct descriptor *list);
20+
21+
/* We manage descriptors separately for each thread. */
22+
#ifdef ENABLE_THREAD_SAFETY
23+
static pthread_key_t descriptor_key;
24+
#ifndef WIN32
25+
static pthread_once_t descriptor_once = PTHREAD_ONCE_INIT;
26+
#endif
27+
28+
static void
29+
descriptor_destructor(void *arg)
30+
{
31+
descriptor_deallocate_all(arg);
32+
}
33+
34+
NON_EXEC_STATIC void
35+
descriptor_key_init(void)
36+
{
37+
pthread_key_create(&descriptor_key, descriptor_destructor);
38+
}
39+
40+
static struct descriptor *
41+
get_descriptors(void)
42+
{
43+
pthread_once(&descriptor_once, descriptor_key_init);
44+
return (struct descriptor *) pthread_getspecific(descriptor_key);
45+
}
46+
47+
static void
48+
set_descriptors(struct descriptor *value)
49+
{
50+
pthread_setspecific(descriptor_key, value);
51+
}
52+
53+
#else
54+
static struct descriptor *all_descriptors = NULL;
55+
#define get_descriptors() (all_descriptors)
56+
#define set_descriptors(value) do { all_descriptors = (value); } while(0)
57+
#endif
1858

1959
/* old internal convenience function that might go away later */
20-
static PGresult
21-
*
60+
static PGresult *
2261
ECPGresultByDescriptor(int line, const char *name)
2362
{
24-
PGresult **resultpp = ECPGdescriptor_lvalue(line, name);
25-
26-
if (resultpp)
27-
return *resultpp;
28-
return NULL;
63+
struct descriptor *desc = ECPGfind_desc(line, name);
64+
if (desc == NULL)
65+
return NULL;
66+
return desc->result;
2967
}
3068

3169
static unsigned int
@@ -445,20 +483,9 @@ ECPGget_desc(int lineno, const char *desc_name, int index,...)
445483
bool
446484
ECPGset_desc_header(int lineno, const char *desc_name, int count)
447485
{
448-
struct descriptor *desc;
449-
450-
for (desc = all_descriptors; desc; desc = desc->next)
451-
{
452-
if (strcmp(desc_name, desc->name) == 0)
453-
break;
454-
}
455-
486+
struct descriptor *desc = ECPGfind_desc(lineno, desc_name);
456487
if (desc == NULL)
457-
{
458-
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
459488
return false;
460-
}
461-
462489
desc->count = count;
463490
return true;
464491
}
@@ -471,17 +498,9 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
471498
struct descriptor_item *desc_item;
472499
struct variable *var;
473500

474-
for (desc = all_descriptors; desc; desc = desc->next)
475-
{
476-
if (strcmp(desc_name, desc->name) == 0)
477-
break;
478-
}
479-
501+
desc = ECPGfind_desc(lineno, desc_name);
480502
if (desc == NULL)
481-
{
482-
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, desc_name);
483503
return false;
484-
}
485504

486505
for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
487506
{
@@ -506,7 +525,7 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
506525

507526
va_start(args, index);
508527

509-
do
528+
for (;;)
510529
{
511530
enum ECPGdtype itemtype;
512531
const char *tobeinserted = NULL;
@@ -585,47 +604,69 @@ ECPGset_desc(int lineno, const char *desc_name, int index,...)
585604
return false;
586605
}
587606
}
588-
} while (true);
607+
}
589608
ECPGfree(var);
590609

591610
return true;
592611
}
593612

613+
/* Free the descriptor and items in it. */
614+
static void
615+
descriptor_free(struct descriptor *desc)
616+
{
617+
struct descriptor_item *desc_item;
618+
619+
for (desc_item = desc->items; desc_item;)
620+
{
621+
struct descriptor_item *di;
622+
623+
ECPGfree(desc_item->data);
624+
di = desc_item;
625+
desc_item = desc_item->next;
626+
ECPGfree(di);
627+
}
628+
629+
ECPGfree(desc->name);
630+
PQclear(desc->result);
631+
ECPGfree(desc);
632+
}
633+
594634
bool
595635
ECPGdeallocate_desc(int line, const char *name)
596636
{
597637
struct descriptor *desc;
598-
struct descriptor **lastptr = &all_descriptors;
638+
struct descriptor *prev;
599639
struct sqlca_t *sqlca = ECPGget_sqlca();
600640

601641
ECPGinit_sqlca(sqlca);
602-
for (desc = all_descriptors; desc; lastptr = &desc->next, desc = desc->next)
642+
for (desc = get_descriptors(), prev = NULL; desc; prev = desc, desc = desc->next)
603643
{
604644
if (!strcmp(name, desc->name))
605645
{
606-
struct descriptor_item *desc_item;
607-
608-
for (desc_item = desc->items; desc_item;)
609-
{
610-
struct descriptor_item *di;
611-
612-
ECPGfree(desc_item->data);
613-
di = desc_item;
614-
desc_item = desc_item->next;
615-
ECPGfree(di);
616-
}
617-
618-
*lastptr = desc->next;
619-
ECPGfree(desc->name);
620-
PQclear(desc->result);
621-
ECPGfree(desc);
646+
if (prev)
647+
prev->next = desc->next;
648+
else
649+
set_descriptors(desc->next);
650+
descriptor_free(desc);
622651
return true;
623652
}
624653
}
625654
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
626655
return false;
627656
}
628657

658+
/* Deallocate all descriptors in the list */
659+
static void
660+
descriptor_deallocate_all(struct descriptor *list)
661+
{
662+
while (list)
663+
{
664+
struct descriptor *next = list->next;
665+
descriptor_free(list);
666+
list = next;
667+
}
668+
}
669+
629670
bool
630671
ECPGallocate_desc(int line, const char *name)
631672
{
@@ -636,7 +677,7 @@ ECPGallocate_desc(int line, const char *name)
636677
new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
637678
if (!new)
638679
return false;
639-
new->next = all_descriptors;
680+
new->next = get_descriptors();
640681
new->name = ECPGalloc(strlen(name) + 1, line);
641682
if (!new->name)
642683
{
@@ -654,23 +695,24 @@ ECPGallocate_desc(int line, const char *name)
654695
return false;
655696
}
656697
strcpy(new->name, name);
657-
all_descriptors = new;
698+
set_descriptors(new);
658699
return true;
659700
}
660701

661-
PGresult **
662-
ECPGdescriptor_lvalue(int line, const char *descriptor)
702+
/* Find descriptor with name in the connection. */
703+
struct descriptor *
704+
ECPGfind_desc(int line, const char *name)
663705
{
664-
struct descriptor *i;
706+
struct descriptor *desc;
665707

666-
for (i = all_descriptors; i != NULL; i = i->next)
708+
for (desc = get_descriptors(); desc; desc = desc->next)
667709
{
668-
if (!strcmp(descriptor, i->name))
669-
return &i->result;
710+
if (strcmp(name, desc->name) == 0)
711+
return desc;
670712
}
671713

672-
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, (char *) descriptor);
673-
return NULL;
714+
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, name);
715+
return NULL; /* not found */
674716
}
675717

676718
bool

src/interfaces/ecpg/ecpglib/execute.c

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.70 2007/09/26 10:57:00 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.71 2007/10/02 09:49:59 meskes Exp $ */
22

33
/*
44
* The aim is to get a simpler inteface to the database routines.
@@ -1088,17 +1088,9 @@ ECPGexecute(struct statement * stmt)
10881088
struct descriptor *desc;
10891089
struct descriptor_item *desc_item;
10901090

1091-
for (desc = all_descriptors; desc; desc = desc->next)
1092-
{
1093-
if (strcmp(var->pointer, desc->name) == 0)
1094-
break;
1095-
}
1096-
1091+
desc = ECPGfind_desc(stmt->lineno, var->pointer);
10971092
if (desc == NULL)
1098-
{
1099-
ECPGraise(stmt->lineno, ECPG_UNKNOWN_DESCRIPTOR, ECPG_SQLSTATE_INVALID_SQL_DESCRIPTOR_NAME, var->pointer);
11001093
return false;
1101-
}
11021094

11031095
desc_counter++;
11041096
for (desc_item = desc->items; desc_item; desc_item = desc_item->next)
@@ -1334,16 +1326,15 @@ ECPGexecute(struct statement * stmt)
13341326

13351327
if (var != NULL && var->type == ECPGt_descriptor)
13361328
{
1337-
PGresult **resultpp = ECPGdescriptor_lvalue(stmt->lineno, (const char *) var->pointer);
1338-
1339-
if (resultpp == NULL)
1329+
struct descriptor *desc = ECPGfind_desc(stmt->lineno, var->pointer);
1330+
if (desc == NULL)
13401331
status = false;
13411332
else
13421333
{
1343-
if (*resultpp)
1344-
PQclear(*resultpp);
1345-
*resultpp = results;
1346-
clear_result = FALSE;
1334+
if (desc->result)
1335+
PQclear(desc->result);
1336+
desc->result = results;
1337+
clear_result = false;
13471338
ECPGlog("ECPGexecute putting result (%d tuples) into descriptor '%s'\n", PQntuples(results), (const char *) var->pointer);
13481339
}
13491340
var = var->next;

src/interfaces/ecpg/ecpglib/extern.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.28 2007/09/30 11:38:48 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/extern.h,v 1.29 2007/10/02 09:49:59 meskes Exp $ */
22

33
#ifndef _ECPG_LIB_EXTERN_H
44
#define _ECPG_LIB_EXTERN_H
@@ -36,6 +36,8 @@ bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type,
3636

3737
#ifdef ENABLE_THREAD_SAFETY
3838
void ecpg_pthreads_init(void);
39+
#else
40+
#define ecpg_pthreads_init() ((void)0)
3941
#endif
4042
struct connection *ECPGget_connection(const char *);
4143
char *ECPGalloc(long, int);
@@ -92,6 +94,7 @@ struct connection
9294
int autocommit;
9395
struct ECPGtype_information_cache *cache_head;
9496
struct prepared_statement *prep_stmts;
97+
struct descriptor *descriptors;
9598
struct connection *next;
9699
};
97100

@@ -105,8 +108,6 @@ struct descriptor
105108
struct descriptor_item *items;
106109
};
107110

108-
extern struct descriptor *all_descriptors;
109-
110111
struct descriptor_item
111112
{
112113
int num;
@@ -136,7 +137,7 @@ struct variable
136137
struct variable *next;
137138
};
138139

139-
PGresult **ECPGdescriptor_lvalue(int line, const char *descriptor);
140+
struct descriptor *ECPGfind_desc(int line, const char *name);
140141

141142
bool ECPGstore_result(const PGresult *results, int act_field,
142143
const struct statement * stmt, struct variable * var);

src/interfaces/ecpg/ecpglib/misc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.37 2007/09/30 11:38:48 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.38 2007/10/02 09:49:59 meskes Exp $ */
22

33
#define POSTGRES_ECPG_INTERNAL
44
#include "postgres_fe.h"
@@ -431,6 +431,7 @@ DllMain(HANDLE module, DWORD reason, LPVOID reserved)
431431
auto_mem_key_init();
432432
ecpg_actual_connection_init();
433433
ecpg_sqlca_key_init();
434+
descriptor_key_init();
434435
}
435436
return TRUE;
436437
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy