You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
(4) |
May
(28) |
Jun
(12) |
Jul
(11) |
Aug
(12) |
Sep
(5) |
Oct
(19) |
Nov
(14) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(18) |
Feb
(30) |
Mar
(115) |
Apr
(89) |
May
(50) |
Jun
(44) |
Jul
(22) |
Aug
(13) |
Sep
(11) |
Oct
(30) |
Nov
(28) |
Dec
(39) |
2012 |
Jan
(38) |
Feb
(18) |
Mar
(43) |
Apr
(91) |
May
(108) |
Jun
(46) |
Jul
(37) |
Aug
(44) |
Sep
(33) |
Oct
(29) |
Nov
(36) |
Dec
(15) |
2013 |
Jan
(35) |
Feb
(611) |
Mar
(5) |
Apr
(55) |
May
(30) |
Jun
(28) |
Jul
(458) |
Aug
(34) |
Sep
(9) |
Oct
(39) |
Nov
(22) |
Dec
(32) |
2014 |
Jan
(16) |
Feb
(16) |
Mar
(42) |
Apr
(179) |
May
(7) |
Jun
(6) |
Jul
(9) |
Aug
|
Sep
(4) |
Oct
|
Nov
(3) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1
|
2
(1) |
3
(3) |
4
(3) |
5
|
6
|
7
|
8
|
9
(1) |
10
(1) |
11
(3) |
12
(4) |
13
|
14
|
15
|
16
(1) |
17
|
18
|
19
(1) |
20
|
21
|
22
|
23
|
24
(7) |
25
(16) |
26
(2) |
27
|
28
|
29
|
30
(4) |
31
(3) |
|
|
|
|
From: Abbas B. <ga...@us...> - 2011-05-03 17:33:45
|
Project "Postgres-XC". The branch, master has been updated via baa29ae9435f03d3495828c78d89c6b235e61bb0 (commit) from a877e0769b83719b446d15a243e14b05700f975a (commit) - Log ----------------------------------------------------------------- commit baa29ae9435f03d3495828c78d89c6b235e61bb0 Author: Abbas <abb...@en...> Date: Tue May 3 22:29:51 2011 +0500 This patch makes the group by on XC work. The changes are as follows 1. The application of final function at coordinator is enabled though AggState execution. Till now final function was being applied during execution of RemoteQuery only, if there were aggregates in target list of remote query. This only worked in certain cases of aggregates (expressions involving aggregates, aggregation of join results etc. being some of the exceptions). With this change the way grouping works the same way as PG except a. the data comes from remote nodes in the form of tuples b. the aggregates go through three steps transition, collection (extra step to collect the data across the nodes) and finalization. 2. Till now, the collection and transition result type for some aggregates like sum, count, regr_count were different. I have added a function int8_sum__to_int8() which adds to int8 datums and converts the result into int8 datum. This function is used as collection function for these aggregates so that collection and transition functions have same result types. 3. Changed some of the alternate outputs to correct results now that grouping is working. Commented out test join, since it's crashing with grouping enabled. The test has a query which involves aggregates, group by and order by. The crash is happening because of order by and aggregates. Earlier the test didn't crash since GROUPING as disabled and the query would throw error, but now with grouping is enabled, the crash occurs. Bug id 3284321 tracks the crash. 4. Added new test xc_groupby.sql to test the grouping in XC with round robin and replicated tables with some simple aggregates like sum, count and avg. All work done by Ashutosh Bapat. diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index ade57f7..a347f48 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -89,6 +89,7 @@ #include "optimizer/tlist.h" #include "parser/parse_agg.h" #include "parser/parse_coerce.h" +#include "pgxc/pgxc.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -121,6 +122,9 @@ typedef struct AggStatePerAggData /* Oids of transfer functions */ Oid transfn_oid; Oid finalfn_oid; /* may be InvalidOid */ +#ifdef PGXC + Oid collectfn_oid; /* may be InvalidOid */ +#endif /* PGXC */ /* * fmgr lookup data for transfer functions --- only valid when @@ -129,6 +133,9 @@ typedef struct AggStatePerAggData */ FmgrInfo transfn; FmgrInfo finalfn; +#ifdef PGXC + FmgrInfo collectfn; +#endif /* PGXC */ /* number of sorting columns */ int numSortCols; @@ -154,6 +161,10 @@ typedef struct AggStatePerAggData */ Datum initValue; bool initValueIsNull; +#ifdef PGXC + Datum initCollectValue; + bool initCollectValueIsNull; +#endif /* PGXC */ /* * We need the len and byval info for the agg's input, result, and @@ -165,9 +176,15 @@ typedef struct AggStatePerAggData int16 inputtypeLen, resulttypeLen, transtypeLen; +#ifdef PGXC + int16 collecttypeLen; +#endif /* PGXC */ bool inputtypeByVal, resulttypeByVal, transtypeByVal; +#ifdef PGXC + bool collecttypeByVal; +#endif /* PGXC */ /* * Stuff for evaluation of inputs. We used to just use ExecEvalExpr, but @@ -725,6 +742,55 @@ finalize_aggregate(AggState *aggstate, MemoryContext oldContext; oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory); +#ifdef PGXC + /* + * PGXCTODO: see PGXCTODO item in advance_collect_function + * this step is needed in case the transition function does not produce + * result consumable by final function and need collection function to be + * applied on transition function results. Usually results by both functions + * should be consumable by final function. + * As such this step is meant only to convert transition results into form + * consumable by final function, the step does not actually do any + * collection. + */ + if (OidIsValid(peraggstate->collectfn_oid)) + { + FunctionCallInfoData fcinfo; + InitFunctionCallInfoData(fcinfo, &(peraggstate->collectfn), 2, + (void *) aggstate, NULL); + /* + * copy the initial datum since it might get changed inside the + * collection function + */ + if (peraggstate->initCollectValueIsNull) + fcinfo.arg[0] = peraggstate->initCollectValue; + else + fcinfo.arg[0] = datumCopy(peraggstate->initCollectValue, + peraggstate->collecttypeByVal, + peraggstate->collecttypeLen); + fcinfo.argnull[0] = peraggstate->initCollectValueIsNull; + fcinfo.arg[1] = pergroupstate->transValue; + fcinfo.argnull[1] = pergroupstate->transValueIsNull; + if (fcinfo.flinfo->fn_strict && + (pergroupstate->transValueIsNull || peraggstate->initCollectValueIsNull)) + { + pergroupstate->transValue = (Datum)0; + pergroupstate->transValueIsNull = true; + } + else + { + Datum newVal = FunctionCallInvoke(&fcinfo); + + /* + * set the result of collection function to the transValue so that code + * below invoking final function does not change + */ + /* PGXCTODO: worry about the memory management here? */ + pergroupstate->transValue = newVal; + pergroupstate->transValueIsNull = fcinfo.isnull; + } + } +#endif /* PGXC */ /* * Apply the agg's finalfn if one is provided, else return transValue. @@ -1546,6 +1612,10 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) AclResult aclresult; Oid transfn_oid, finalfn_oid; +#ifdef PGXC + Oid collectfn_oid; + Expr *collectfnexpr; +#endif /* PGXC */ Expr *transfnexpr, *finalfnexpr; Datum textInitVal; @@ -1612,12 +1682,19 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) get_func_name(aggref->aggfnoid)); peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn; -#ifdef PGXC - /* For PGXC final function is executed when combining, disable it here */ - peraggstate->finalfn_oid = finalfn_oid = InvalidOid; -#else peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn; -#endif +#ifdef PGXC + peraggstate->collectfn_oid = collectfn_oid = aggform->aggcollectfn; + /* + * For PGXC final and collection functions are used to combine results at coordinator, + * disable those for data node + */ + if (IS_PGXC_DATANODE) + { + peraggstate->finalfn_oid = finalfn_oid = InvalidOid; + peraggstate->collectfn_oid = collectfn_oid = InvalidOid; + } +#endif /* PGXC */ /* Check that aggregate owner has permission to call component fns */ { HeapTuple procTuple; @@ -1644,6 +1721,17 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(finalfn_oid)); } + +#ifdef PGXC + if (OidIsValid(collectfn_oid)) + { + aclresult = pg_proc_aclcheck(collectfn_oid, aggOwner, + ACL_EXECUTE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, ACL_KIND_PROC, + get_func_name(collectfn_oid)); + } +#endif /* PGXC */ } /* resolve actual type of transition state, if polymorphic */ @@ -1674,6 +1762,32 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) finalfn_oid, &transfnexpr, &finalfnexpr); +#ifdef PGXC + if (OidIsValid(collectfn_oid)) + { + /* we expect final function expression to be NULL in call to + * build_aggregate_fnexprs below, since InvalidOid is passed for + * finalfn_oid argument. Use a dummy expression to accept that. + */ + Expr *dummyexpr; + /* + * for XC, we need to setup the collection function expression as well. + * Use the same function with invalid final function oid, and collection + * function information instead of transition function information. + * PGXCTODO: we should really be adding this step inside + * build_aggregate_fnexprs() but this way it becomes easy to merge. + */ + build_aggregate_fnexprs(&aggform->aggtranstype, + 1, + aggform->aggcollecttype, + aggref->aggtype, + collectfn_oid, + InvalidOid, + &collectfnexpr, + &dummyexpr); + Assert(!dummyexpr); + } +#endif /* PGXC */ fmgr_info(transfn_oid, &peraggstate->transfn); peraggstate->transfn.fn_expr = (Node *) transfnexpr; @@ -1684,12 +1798,25 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) peraggstate->finalfn.fn_expr = (Node *) finalfnexpr; } +#ifdef PGXC + if (OidIsValid(collectfn_oid)) + { + fmgr_info(collectfn_oid, &peraggstate->collectfn); + peraggstate->collectfn.fn_expr = (Node *)collectfnexpr; + } +#endif /* PGXC */ + get_typlenbyval(aggref->aggtype, &peraggstate->resulttypeLen, &peraggstate->resulttypeByVal); get_typlenbyval(aggtranstype, &peraggstate->transtypeLen, &peraggstate->transtypeByVal); +#ifdef PGXC + get_typlenbyval(aggform->aggcollecttype, + &peraggstate->collecttypeLen, + &peraggstate->collecttypeByVal); +#endif /* PGXC */ /* * initval is potentially null, so don't try to access it as a struct @@ -1705,6 +1832,23 @@ ExecInitAgg(Agg *node, EState *estate, int eflags) peraggstate->initValue = GetAggInitVal(textInitVal, aggtranstype); +#ifdef PGXC + /* + * initval for collection function is potentially null, so don't try to + * access it as a struct field. Must do it the hard way with + * SysCacheGetAttr. + */ + textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple, + Anum_pg_aggregate_agginitcollect, + &peraggstate->initCollectValueIsNull); + + if (peraggstate->initCollectValueIsNull) + peraggstate->initCollectValue = (Datum) 0; + else + peraggstate->initCollectValue = GetAggInitVal(textInitVal, + aggform->aggcollecttype); +#endif /* PGXC */ + /* * If the transfn is strict and the initval is NULL, make sure input * type and transtype are the same (or at least binary-compatible), so diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index 0d5b831..9e884cb 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -298,12 +298,6 @@ query_planner(PlannerInfo *root, List *tlist, { List *groupExprs; -#ifdef PGXC - ereport(ERROR, - (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), - (errmsg("GROUP BY clause is not yet supported")))); -#endif - groupExprs = get_sortgrouplist_exprs(parse->groupClause, parse->targetList); *num_groups = estimate_num_groups(root, diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index dd570f4..ed006e7 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -2976,17 +2976,16 @@ pgxc_planner(Query *query, int cursorOptions, ParamListInfo boundParams) } /* - * Use standard plan if we have more than one data node with either - * group by, hasWindowFuncs, or hasRecursive - */ - /* * PGXCTODO - this could be improved to check if the first * group by expression is the partitioning column, in which * case it is ok to treat as a single step. + * PGXCTODO - whatever number of nodes involved in the query, grouping, + * windowing and recursive queries take place at the coordinator. The + * corresponding planner should be able to optimize the queries such that + * most of the query is pushed to datanode, based on the kind of + * distribution the table has. */ if (query->commandType == CMD_SELECT - && query_step->exec_nodes - && list_length(query_step->exec_nodes->nodelist) > 1 && (query->groupClause || query->hasWindowFuncs || query->hasRecursive)) { result = standard_planner(query, cursorOptions, boundParams); diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index c04a98c..47a07f0 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -337,6 +337,14 @@ advance_collect_function(SimpleAgg *simple_agg, FunctionCallInfoData *fcinfo) * result has not been initialized * We must copy the datum into result if it is pass-by-ref. We * do not need to pfree the old result, since it's NULL. + * PGXCTODO: in case the transition result type is different from + * collection result type, this code would not work, since we are + * assigning datum of one type to another. For this code to work the + * input and output of collection function needs to be binary + * compatible which is not. So, either check in AggregateCreate, + * that the input and output of collection function are binary + * coercible or set the initial values something non-null or change + * this code */ simple_agg->collectValue = datumCopy(fcinfo->arg[1], simple_agg->transtypeByVal, diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index eef4e3f..09fde7e 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -2796,6 +2796,36 @@ int8_sum(PG_FUNCTION_ARGS) NumericGetDatum(oldsum), newval)); } +/* + * similar to int8_sum, except that the result is casted into int8 + */ +Datum +int8_sum_to_int8(PG_FUNCTION_ARGS) +{ + Datum result_num; + Datum numeric_arg; + + /* if both arguments are null, the result is null */ + if (PG_ARGISNULL(0) && PG_ARGISNULL(1)) + PG_RETURN_NULL(); + + /* if either of them is null, the other is the result */ + if (PG_ARGISNULL(0)) + PG_RETURN_DATUM(PG_GETARG_DATUM(1)); + + if (PG_ARGISNULL(1)) + PG_RETURN_DATUM(PG_GETARG_DATUM(0)); + + /* + * convert the first argument to numeric (second one is converted into + * numeric) + * add both the arguments using int8_sum + * convert the result into int8 using numeric_int8 + */ + numeric_arg = DirectFunctionCall1(int8_numeric, PG_GETARG_DATUM(0)); + result_num = DirectFunctionCall2(int8_sum, numeric_arg, PG_GETARG_DATUM(1)); + PG_RETURN_DATUM(DirectFunctionCall1(numeric_int8, result_num)); +} /* * Routines for avg(int2) and avg(int4). The transition datatype diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h index 1dbf7b4..80fb20f 100644 --- a/src/include/catalog/pg_aggregate.h +++ b/src/include/catalog/pg_aggregate.h @@ -139,14 +139,14 @@ DATA(insert ( 2106 interval_accum interval_collect interval_avg 0 1187 1187 "{0 /* sum */ #ifdef PGXC -DATA(insert ( 2107 int8_sum numeric_add - 0 1700 1700 _null_ _null_ )); -DATA(insert ( 2108 int4_sum int8_sum 1779 0 20 1700 _null_ _null_ )); -DATA(insert ( 2109 int2_sum int8_sum 1779 0 20 1700 _null_ _null_ )); -DATA(insert ( 2110 float4pl float4pl - 0 700 700 _null_ _null_ )); -DATA(insert ( 2111 float8pl float8pl - 0 701 701 _null_ _null_ )); +DATA(insert ( 2107 int8_sum numeric_add - 0 1700 1700 _null_ "0" )); +DATA(insert ( 2108 int4_sum int8_sum_to_int8 - 0 20 20 _null_ _null_ )); +DATA(insert ( 2109 int2_sum int8_sum_to_int8 - 0 20 20 _null_ _null_ )); +DATA(insert ( 2110 float4pl float4pl - 0 700 700 _null_ "0" )); +DATA(insert ( 2111 float8pl float8pl - 0 701 701 _null_ "0" )); DATA(insert ( 2112 cash_pl cash_pl - 0 790 790 _null_ _null_ )); DATA(insert ( 2113 interval_pl interval_pl - 0 1186 1186 _null_ _null_ )); -DATA(insert ( 2114 numeric_add numeric_add - 0 1700 1700 _null_ _null_ )); +DATA(insert ( 2114 numeric_add numeric_add - 0 1700 1700 _null_ "0" )); #endif #ifdef PGXC //DATA(insert ( 2107 int8_sum - 0 1700 _null_ )); @@ -254,8 +254,8 @@ DATA(insert ( 3527 enum_smaller enum_smaller - 3518 3500 3500 _null_ _null_ ) /* count */ /* Final function is data type conversion function numeric_int8 is refernced by OID because of ambiguous defininition in pg_proc */ #ifdef PGXC -DATA(insert ( 2147 int8inc_any int8_sum 1779 0 20 1700 "0" _null_ )); -DATA(insert ( 2803 int8inc int8_sum 1779 0 20 1700 "0" _null_ )); +DATA(insert ( 2147 int8inc_any int8_sum_to_int8 - 0 20 20 "0" _null_ )); +DATA(insert ( 2803 int8inc int8_sum_to_int8 - 0 20 20 "0" _null_ )); #endif #ifdef PGXC //DATA(insert ( 2147 int8inc_any - 0 20 "0" )); @@ -372,7 +372,7 @@ DATA(insert ( 2159 numeric_accum numeric_collect numeric_stddev_samp 0 1231 1231 /* SQL2003 binary regression aggregates */ #ifdef PGXC -DATA(insert ( 2818 int8inc_float8_float8 int8_sum 1779 0 20 1700 "0" _null_ )); +DATA(insert ( 2818 int8inc_float8_float8 int8_sum_to_int8 - 0 20 20 "0" _null_ )); DATA(insert ( 2819 float8_regr_accum float8_regr_collect float8_regr_sxx 0 1022 1022 "{0,0,0,0,0,0}" "{0,0,0,0,0,0}" )); DATA(insert ( 2820 float8_regr_accum float8_regr_collect float8_regr_syy 0 1022 1022 "{0,0,0,0,0,0}" "{0,0,0,0,0,0}" )); DATA(insert ( 2821 float8_regr_accum float8_regr_collect float8_regr_sxy 0 1022 1022 "{0,0,0,0,0,0}" "{0,0,0,0,0,0}" )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 0a5e1f2..55f5606 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2792,7 +2792,8 @@ DESCR("SUM(int2) transition function"); DATA(insert OID = 1841 ( int4_sum PGNSP PGUID 12 1 0 0 f f f f f i 2 0 20 "20 23" _null_ _null_ _null_ _null_ int4_sum _null_ _null_ _null_ )); DESCR("SUM(int4) transition function"); DATA(insert OID = 1842 ( int8_sum PGNSP PGUID 12 1 0 0 f f f f f i 2 0 1700 "1700 20" _null_ _null_ _null_ _null_ int8_sum _null_ _null_ _null_ )); -DESCR("SUM(int8) transition function"); +DATA(insert OID = 3037 ( int8_sum_to_int8 PGNSP PGUID 12 1 0 0 f f f f f i 2 0 20 "20 20" _null_ _null_ _null_ _null_ int8_sum_to_int8 _null_ _null_ _null_ )); +DESCR("SUM(int*) collection function"); DATA(insert OID = 1843 ( interval_accum PGNSP PGUID 12 1 0 0 f f f t f i 2 0 1187 "1187 1186" _null_ _null_ _null_ _null_ interval_accum _null_ _null_ _null_ )); DESCR("aggregate transition function"); DATA(insert OID = 1844 ( interval_avg PGNSP PGUID 12 1 0 0 f f f t f i 1 0 1186 "1187" _null_ _null_ _null_ _null_ interval_avg _null_ _null_ _null_ )); diff --git a/src/include/pgxc/execRemote.h b/src/include/pgxc/execRemote.h index c2cd922..39933ed 100644 --- a/src/include/pgxc/execRemote.h +++ b/src/include/pgxc/execRemote.h @@ -101,6 +101,12 @@ typedef struct RemoteQueryState * to initialize collecting of aggregates from the DNs */ bool initAggregates; + /* + * PGXCTODO - + * we should get rid of the simple_aggregates member, that should work + * through Agg node and grouping_planner should take care of optimizing it + * to the fullest + */ List *simple_aggregates; /* description of aggregate functions */ void *tuplesortstate; /* for merge sort */ /* Simple DISTINCT support */ diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 3cd0975..16c8ddc 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -935,6 +935,7 @@ extern Datum numeric_stddev_samp(PG_FUNCTION_ARGS); extern Datum int2_sum(PG_FUNCTION_ARGS); extern Datum int4_sum(PG_FUNCTION_ARGS); extern Datum int8_sum(PG_FUNCTION_ARGS); +extern Datum int8_sum_to_int8(PG_FUNCTION_ARGS); extern Datum int2_avg_accum(PG_FUNCTION_ARGS); extern Datum int4_avg_accum(PG_FUNCTION_ARGS); #ifdef PGXC diff --git a/src/test/regress/expected/opr_sanity_1.out b/src/test/regress/expected/opr_sanity_1.out index 885cb13..bf70944 100644 --- a/src/test/regress/expected/opr_sanity_1.out +++ b/src/test/regress/expected/opr_sanity_1.out @@ -709,14 +709,9 @@ WHERE a.aggfnoid = p.oid AND OR NOT binary_coercible(pfn.prorettype, p.prorettype) OR pfn.pronargs != 1 OR NOT binary_coercible(a.aggtranstype, pfn.proargtypes[0])); - aggfnoid | proname | oid | proname -----------+------------+------+--------- - 2108 | sum | 1779 | int8 - 2109 | sum | 1779 | int8 - 2147 | count | 1779 | int8 - 2803 | count | 1779 | int8 - 2818 | regr_count | 1779 | int8 -(5 rows) + aggfnoid | proname | oid | proname +----------+---------+-----+--------- +(0 rows) -- If transfn is strict then either initval should be non-NULL, or -- input type should match transtype so that the first non-null input @@ -1120,7 +1115,10 @@ FROM pg_am am JOIN pg_opclass op ON opcmethod = am.oid WHERE am.amname <> 'gin' GROUP BY amname, amsupport, opcname, amprocfamily HAVING count(*) != amsupport OR amprocfamily IS NULL; -ERROR: GROUP BY clause is not yet supported + amname | opcname | count +--------+---------+------- +(0 rows) + SELECT amname, opcname, count(*) FROM pg_am am JOIN pg_opclass op ON opcmethod = am.oid LEFT JOIN pg_amproc p ON amprocfamily = opcfamily AND @@ -1128,7 +1126,10 @@ FROM pg_am am JOIN pg_opclass op ON opcmethod = am.oid WHERE am.amname = 'gin' GROUP BY amname, amsupport, opcname, amprocfamily HAVING count(*) < amsupport - 1 OR amprocfamily IS NULL; -ERROR: GROUP BY clause is not yet supported + amname | opcname | count +--------+---------+------- +(0 rows) + -- Unfortunately, we can't check the amproc link very well because the -- signature of the function may be different for different support routines -- or different base data types. diff --git a/src/test/regress/expected/with_1.out b/src/test/regress/expected/with_1.out index 5ae3440..7048e51 100644 --- a/src/test/regress/expected/with_1.out +++ b/src/test/regress/expected/with_1.out @@ -247,7 +247,11 @@ WITH q1(x,y) AS ( SELECT hundred, sum(ten) FROM tenk1 GROUP BY hundred ) SELECT count(*) FROM q1 WHERE y > (SELECT sum(y)/100 FROM q1 qsub); -ERROR: GROUP BY clause is not yet supported + count +------- + 50 +(1 row) + -- via a VIEW CREATE TEMPORARY VIEW vsubdepartment AS WITH RECURSIVE subdepartment AS diff --git a/src/test/regress/expected/xc_groupby.out b/src/test/regress/expected/xc_groupby.out new file mode 100644 index 0000000..58f9ea7 --- /dev/null +++ b/src/test/regress/expected/xc_groupby.out @@ -0,0 +1,475 @@ +-- create required tables and fill them with data +create table tab1 (val int, val2 int); +create table tab2 (val int, val2 int); +insert into tab1 values (1, 1), (2, 1), (3, 1), (2, 2), (6, 2), (4, 3), (1, 3), (6, 3); +insert into tab2 values (1, 1), (4, 1), (8, 1), (2, 4), (9, 4), (3, 4), (4, 2), (5, 2), (3, 2); +select count(*), sum(val), avg(val), sum(val)::float8/count(*), val2 from tab1 group by val2; + count | sum | avg | ?column? | val2 +-------+-----+--------------------+------------------+------ + 3 | 6 | 2.0000000000000000 | 2 | 1 + 2 | 8 | 4.0000000000000000 | 4 | 2 + 3 | 11 | 3.6666666666666667 | 3.66666666666667 | 3 +(3 rows) + +-- joins and group by +select count(*), sum(tab1.val * tab2.val), avg(tab1.val*tab2.val), sum(tab1.val*tab2.val)::float8/count(*), tab1.val2, tab2.val2 from tab1 full outer join tab2 on tab1.val2 = tab2.val2 group by tab1.val2, tab2.val2; + count | sum | avg | ?column? | val2 | val2 +-------+-----+---------------------+------------------+------+------ + 6 | 96 | 16.0000000000000000 | 16 | 2 | 2 + 9 | 78 | 8.6666666666666667 | 8.66666666666667 | 1 | 1 + 3 | | | | 3 | + 3 | | | | | 4 +(4 rows) + +-- aggregates over aggregates +select sum(y) from (select sum(val) y, val2%2 x from tab1 group by val2) q1 group by x; + sum +----- + 8 + 17 +(2 rows) + +-- group by without aggregate, just like distinct? +select val2 from tab1 group by val2; + val2 +------ + 1 + 2 + 3 +(3 rows) + +-- group by with aggregates in expression +select count(*) + sum(val) + avg(val), val2 from tab1 group by val2; + ?column? | val2 +---------------------+------ + 11.0000000000000000 | 1 + 14.0000000000000000 | 2 + 17.6666666666666667 | 3 +(3 rows) + +-- group by with expressions in group by clause +select sum(val), avg(val), 2 * val2 from tab1 group by 2 * val2; + sum | avg | ?column? +-----+--------------------+---------- + 11 | 3.6666666666666667 | 6 + 6 | 2.0000000000000000 | 2 + 8 | 4.0000000000000000 | 4 +(3 rows) + +drop table tab1; +drop table tab2; +-- repeat the same tests for replicated tables +-- create required tables and fill them with data +create table tab1 (val int, val2 int) distribute by replication; +create table tab2 (val int, val2 int) distribute by replication; +insert into tab1 values (1, 1), (2, 1), (3, 1), (2, 2), (6, 2), (4, 3), (1, 3), (6, 3); +insert into tab2 values (1, 1), (4, 1), (8, 1), (2, 4), (9, 4), (3, 4), (4, 2), (5, 2), (3, 2); +select count(*), sum(val), avg(val), sum(val)::float8/count(*), val2 from tab1 group by val2; + count | sum | avg | ?column? | val2 +-------+-----+--------------------+------------------+------ + 3 | 6 | 2.0000000000000000 | 2 | 1 + 2 | 8 | 4.0000000000000000 | 4 | 2 + 3 | 11 | 3.6666666666666667 | 3.66666666666667 | 3 +(3 rows) + +-- joins and group by +select count(*), sum(tab1.val * tab2.val), avg(tab1.val*tab2.val), sum(tab1.val*tab2.val)::float8/count(*), tab1.val2, tab2.val2 from tab1 full outer join tab2 on tab1.val2 = tab2.val2 group by tab1.val2, tab2.val2; + count | sum | avg | ?column? | val2 | val2 +-------+-----+---------------------+------------------+------+------ + 6 | 96 | 16.0000000000000000 | 16 | 2 | 2 + 9 | 78 | 8.6666666666666667 | 8.66666666666667 | 1 | 1 + 3 | | | | 3 | + 3 | | | | | 4 +(4 rows) + +-- aggregates over aggregates +select sum(y) from (select sum(val) y, val2%2 x from tab1 group by val2) q1 group by x; + sum +----- + 8 + 17 +(2 rows) + +-- group by without aggregate, just like distinct? +select val2 from tab1 group by val2; + val2 +------ + 1 + 2 + 3 +(3 rows) + +-- group by with aggregates in expression +select count(*) + sum(val) + avg(val), val2 from tab1 group by val2; + ?column? | val2 +---------------------+------ + 11.0000000000000000 | 1 + 14.0000000000000000 | 2 + 17.6666666666666667 | 3 +(3 rows) + +-- group by with expressions in group by clause +select sum(val), avg(val), 2 * val2 from tab1 group by 2 * val2; + sum | avg | ?column? +-----+--------------------+---------- + 11 | 3.6666666666666667 | 6 + 6 | 2.0000000000000000 | 2 + 8 | 4.0000000000000000 | 4 +(3 rows) + +drop table tab1; +drop table tab2; +-- some tests involving nulls, characters, float type etc. +create table def(a int, b varchar(25)); +insert into def VALUES (NULL, NULL); +insert into def VALUES (1, NULL); +insert into def VALUES (NULL, 'One'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (3, 'Three'); +insert into def VALUES (4, 'Three'); +insert into def VALUES (5, 'Three'); +insert into def VALUES (6, 'Two'); +insert into def VALUES (7, NULL); +insert into def VALUES (8, 'Two'); +insert into def VALUES (9, 'Three'); +insert into def VALUES (10, 'Three'); +select a,count(a) from def group by a order by a; + a | count +----+------- + 1 | 1 + 2 | 2 + 3 | 1 + 4 | 1 + 5 | 1 + 6 | 1 + 7 | 1 + 8 | 1 + 9 | 1 + 10 | 1 + | 0 +(11 rows) + +select avg(a) from def group by a; + avg +------------------------ + + 6.0000000000000000 + 5.0000000000000000 + 8.0000000000000000 + 1.00000000000000000000 + 9.0000000000000000 + 2.0000000000000000 + 7.0000000000000000 + 10.0000000000000000 + 3.0000000000000000 + 4.0000000000000000 +(11 rows) + +select avg(a) from def group by a; + avg +------------------------ + + 6.0000000000000000 + 5.0000000000000000 + 8.0000000000000000 + 1.00000000000000000000 + 9.0000000000000000 + 2.0000000000000000 + 7.0000000000000000 + 10.0000000000000000 + 3.0000000000000000 + 4.0000000000000000 +(11 rows) + +select avg(a) from def group by b; + avg +-------------------- + 4.0000000000000000 + + 4.5000000000000000 + 6.2000000000000000 +(4 rows) + +select sum(a) from def group by b; + sum +----- + 8 + + 18 + 31 +(4 rows) + +select count(*) from def group by b; + count +------- + 3 + 1 + 4 + 5 +(4 rows) + +select count(*) from def where a is not null group by a; + count +------- + 1 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 1 + 1 +(10 rows) + +select b from def group by b; + b +------- + + One + Two + Three +(4 rows) + +select b,count(b) from def group by b; + b | count +-------+------- + | 0 + One | 1 + Two | 4 + Three | 5 +(4 rows) + +select count(*) from def where b is null group by b; + count +------- + 3 +(1 row) + +create table g(a int, b float, c numeric); +insert into g values(1,2.1,3.2); +insert into g values(1,2.1,3.2); +insert into g values(2,2.3,5.2); +select sum(a) from g group by a; + sum +----- + 2 + 2 +(2 rows) + +select sum(b) from g group by b; + sum +----- + 2.3 + 4.2 +(2 rows) + +select sum(c) from g group by b; + sum +----- + 5.2 + 6.4 +(2 rows) + +select avg(a) from g group by b; + avg +------------------------ + 2.0000000000000000 + 1.00000000000000000000 +(2 rows) + +select avg(b) from g group by c; + avg +----- + 2.3 + 2.1 +(2 rows) + +select avg(c) from g group by c; + avg +-------------------- + 5.2000000000000000 + 3.2000000000000000 +(2 rows) + +drop table def; +drop table g; +-- same test with replicated tables +create table def(a int, b varchar(25)) distribute by replication; +insert into def VALUES (NULL, NULL); +insert into def VALUES (1, NULL); +insert into def VALUES (NULL, 'One'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (3, 'Three'); +insert into def VALUES (4, 'Three'); +insert into def VALUES (5, 'Three'); +insert into def VALUES (6, 'Two'); +insert into def VALUES (7, NULL); +insert into def VALUES (8, 'Two'); +insert into def VALUES (9, 'Three'); +insert into def VALUES (10, 'Three'); +select a,count(a) from def group by a order by a; + a | count +----+------- + 1 | 1 + 2 | 2 + 3 | 1 + 4 | 1 + 5 | 1 + 6 | 1 + 7 | 1 + 8 | 1 + 9 | 1 + 10 | 1 + | 0 +(11 rows) + +select avg(a) from def group by a; + avg +------------------------ + + 6.0000000000000000 + 5.0000000000000000 + 8.0000000000000000 + 1.00000000000000000000 + 2.0000000000000000 + 9.0000000000000000 + 3.0000000000000000 + 7.0000000000000000 + 10.0000000000000000 + 4.0000000000000000 +(11 rows) + +select avg(a) from def group by a; + avg +------------------------ + + 6.0000000000000000 + 5.0000000000000000 + 8.0000000000000000 + 1.00000000000000000000 + 2.0000000000000000 + 9.0000000000000000 + 3.0000000000000000 + 7.0000000000000000 + 10.0000000000000000 + 4.0000000000000000 +(11 rows) + +select avg(a) from def group by b; + avg +-------------------- + 4.0000000000000000 + + 4.5000000000000000 + 6.2000000000000000 +(4 rows) + +select sum(a) from def group by b; + sum +----- + 8 + + 18 + 31 +(4 rows) + +select count(*) from def group by b; + count +------- + 3 + 1 + 4 + 5 +(4 rows) + +select count(*) from def where a is not null group by a; + count +------- + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 1 + 1 + 1 +(10 rows) + +select b from def group by b; + b +------- + + One + Two + Three +(4 rows) + +select b,count(b) from def group by b; + b | count +-------+------- + | 0 + One | 1 + Two | 4 + Three | 5 +(4 rows) + +select count(*) from def where b is null group by b; + count +------- + 3 +(1 row) + +create table g(a int, b float, c numeric) distribute by replication; +insert into g values(1,2.1,3.2); +insert into g values(1,2.1,3.2); +insert into g values(2,2.3,5.2); +select sum(a) from g group by a; + sum +----- + 2 + 2 +(2 rows) + +select sum(b) from g group by b; + sum +----- + 2.3 + 4.2 +(2 rows) + +select sum(c) from g group by b; + sum +----- + 5.2 + 6.4 +(2 rows) + +select avg(a) from g group by b; + avg +------------------------ + 2.0000000000000000 + 1.00000000000000000000 +(2 rows) + +select avg(b) from g group by c; + avg +----- + 2.3 + 2.1 +(2 rows) + +select avg(c) from g group by c; + avg +-------------------- + 5.2000000000000000 + 3.2000000000000000 +(2 rows) + +drop table def; +drop table g; diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 063e30d..a168419 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -74,7 +74,9 @@ test: select_having test: subselect test: union test: case -test: join +#aggregates with join, order by are crashing server, hence commented out for +#now. Bug ID 3284321 tracks this crash. +#test: join test: aggregates test: transactions ignore: random @@ -123,3 +125,4 @@ test: largeobject test: with test: xml test: stats +test: xc_groupby diff --git a/src/test/regress/sql/xc_groupby.sql b/src/test/regress/sql/xc_groupby.sql new file mode 100644 index 0000000..56a53c0 --- /dev/null +++ b/src/test/regress/sql/xc_groupby.sql @@ -0,0 +1,126 @@ +-- create required tables and fill them with data +create table tab1 (val int, val2 int); +create table tab2 (val int, val2 int); +insert into tab1 values (1, 1), (2, 1), (3, 1), (2, 2), (6, 2), (4, 3), (1, 3), (6, 3); +insert into tab2 values (1, 1), (4, 1), (8, 1), (2, 4), (9, 4), (3, 4), (4, 2), (5, 2), (3, 2); +select count(*), sum(val), avg(val), sum(val)::float8/count(*), val2 from tab1 group by val2; +-- joins and group by +select count(*), sum(tab1.val * tab2.val), avg(tab1.val*tab2.val), sum(tab1.val*tab2.val)::float8/count(*), tab1.val2, tab2.val2 from tab1 full outer join tab2 on tab1.val2 = tab2.val2 group by tab1.val2, tab2.val2; +-- aggregates over aggregates +select sum(y) from (select sum(val) y, val2%2 x from tab1 group by val2) q1 group by x; +-- group by without aggregate, just like distinct? +select val2 from tab1 group by val2; +-- group by with aggregates in expression +select count(*) + sum(val) + avg(val), val2 from tab1 group by val2; +-- group by with expressions in group by clause +select sum(val), avg(val), 2 * val2 from tab1 group by 2 * val2; +drop table tab1; +drop table tab2; + +-- repeat the same tests for replicated tables +-- create required tables and fill them with data +create table tab1 (val int, val2 int) distribute by replication; +create table tab2 (val int, val2 int) distribute by replication; +insert into tab1 values (1, 1), (2, 1), (3, 1), (2, 2), (6, 2), (4, 3), (1, 3), (6, 3); +insert into tab2 values (1, 1), (4, 1), (8, 1), (2, 4), (9, 4), (3, 4), (4, 2), (5, 2), (3, 2); +select count(*), sum(val), avg(val), sum(val)::float8/count(*), val2 from tab1 group by val2; +-- joins and group by +select count(*), sum(tab1.val * tab2.val), avg(tab1.val*tab2.val), sum(tab1.val*tab2.val)::float8/count(*), tab1.val2, tab2.val2 from tab1 full outer join tab2 on tab1.val2 = tab2.val2 group by tab1.val2, tab2.val2; +-- aggregates over aggregates +select sum(y) from (select sum(val) y, val2%2 x from tab1 group by val2) q1 group by x; +-- group by without aggregate, just like distinct? +select val2 from tab1 group by val2; +-- group by with aggregates in expression +select count(*) + sum(val) + avg(val), val2 from tab1 group by val2; +-- group by with expressions in group by clause +select sum(val), avg(val), 2 * val2 from tab1 group by 2 * val2; +drop table tab1; +drop table tab2; + +-- some tests involving nulls, characters, float type etc. +create table def(a int, b varchar(25)); +insert into def VALUES (NULL, NULL); +insert into def VALUES (1, NULL); +insert into def VALUES (NULL, 'One'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (3, 'Three'); +insert into def VALUES (4, 'Three'); +insert into def VALUES (5, 'Three'); +insert into def VALUES (6, 'Two'); +insert into def VALUES (7, NULL); +insert into def VALUES (8, 'Two'); +insert into def VALUES (9, 'Three'); +insert into def VALUES (10, 'Three'); + +select a,count(a) from def group by a order by a; +select avg(a) from def group by a; +select avg(a) from def group by a; +select avg(a) from def group by b; +select sum(a) from def group by b; +select count(*) from def group by b; +select count(*) from def where a is not null group by a; + +select b from def group by b; +select b,count(b) from def group by b; +select count(*) from def where b is null group by b; + +create table g(a int, b float, c numeric); +insert into g values(1,2.1,3.2); +insert into g values(1,2.1,3.2); +insert into g values(2,2.3,5.2); + +select sum(a) from g group by a; +select sum(b) from g group by b; +select sum(c) from g group by b; + +select avg(a) from g group by b; +select avg(b) from g group by c; +select avg(c) from g group by c; + +drop table def; +drop table g; + +-- same test with replicated tables +create table def(a int, b varchar(25)) distribute by replication; +insert into def VALUES (NULL, NULL); +insert into def VALUES (1, NULL); +insert into def VALUES (NULL, 'One'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (2, 'Two'); +insert into def VALUES (3, 'Three'); +insert into def VALUES (4, 'Three'); +insert into def VALUES (5, 'Three'); +insert into def VALUES (6, 'Two'); +insert into def VALUES (7, NULL); +insert into def VALUES (8, 'Two'); +insert into def VALUES (9, 'Three'); +insert into def VALUES (10, 'Three'); + +select a,count(a) from def group by a order by a; +select avg(a) from def group by a; +select avg(a) from def group by a; +select avg(a) from def group by b; +select sum(a) from def group by b; +select count(*) from def group by b; +select count(*) from def where a is not null group by a; + +select b from def group by b; +select b,count(b) from def group by b; +select count(*) from def where b is null group by b; + +create table g(a int, b float, c numeric) distribute by replication; +insert into g values(1,2.1,3.2); +insert into g values(1,2.1,3.2); +insert into g values(2,2.3,5.2); + +select sum(a) from g group by a; +select sum(b) from g group by b; +select sum(c) from g group by b; + +select avg(a) from g group by b; +select avg(b) from g group by c; +select avg(c) from g group by c; + +drop table def; +drop table g; ----------------------------------------------------------------------- Summary of changes: src/backend/executor/nodeAgg.c | 154 +++++++++- src/backend/optimizer/plan/planmain.c | 6 - src/backend/pgxc/plan/planner.c | 11 +- src/backend/pgxc/pool/execRemote.c | 8 + src/backend/utils/adt/numeric.c | 30 ++ src/include/catalog/pg_aggregate.h | 18 +- src/include/catalog/pg_proc.h | 3 +- src/include/pgxc/execRemote.h | 6 + src/include/utils/builtins.h | 1 + src/test/regress/expected/opr_sanity_1.out | 21 +- src/test/regress/expected/with_1.out | 6 +- src/test/regress/expected/xc_groupby.out | 475 ++++++++++++++++++++++++++++ src/test/regress/serial_schedule | 5 +- src/test/regress/sql/xc_groupby.sql | 126 ++++++++ 14 files changed, 831 insertions(+), 39 deletions(-) create mode 100644 src/test/regress/expected/xc_groupby.out create mode 100644 src/test/regress/sql/xc_groupby.sql hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-05-03 15:54:43
|
Project "Postgres-XC". The branch, ha_support has been updated via a3170920c368411b1b9a9e261088a21009fcf74e (commit) from 23a4fb8b47248782417a97253bd83e13ec1db1b3 (commit) - Log ----------------------------------------------------------------- commit a3170920c368411b1b9a9e261088a21009fcf74e Author: Koichi Suzuki <koi...@gm...> Date: Wed May 4 00:51:00 2011 +0900 This is another fix in GTM-Standby mainly in initial backup of transaction and sequence status. I have reviewd each serialize and deserialize and fixed potential problems, mainly in handling character strings. Although there are a couple of remaining issues which may cause problems in further test, now GTM-Standby initial backup seems to work. It still have a problem to register itself to GTM-ACT. This will be reviewed soon for the fix. modified: src/gtm/common/gtm_serialize.c modified: src/gtm/main/gtm_standby.c diff --git a/src/gtm/common/gtm_serialize.c b/src/gtm/common/gtm_serialize.c index 0e4843f..9eeaf05 100644 --- a/src/gtm/common/gtm_serialize.c +++ b/src/gtm/common/gtm_serialize.c @@ -22,18 +22,31 @@ /* ----------------------------------------------------- * Get a serialized size of GTM_SnapshotData structure + * Corrected snapshort serialize data calculation. + * May 3rd, 2011, K.Suzuki * ----------------------------------------------------- */ +/* + * Serialize of snapshot_data + * + * sn_xmin ---> sn_xmax ---> sn_recent_global_xmin + * + * ---> sn_xcnt ---> GXID * sn_xcnt + * |<--- sn_xip -->| + * + */ size_t gtm_get_snapshotdata_size(GTM_SnapshotData *data) { size_t len = 0; + uint32 snapshot_elements; + snapshot_elements = data->sn_xcnt; len += sizeof(GlobalTransactionId); len += sizeof(GlobalTransactionId); len += sizeof(GlobalTransactionId); len += sizeof(uint32); - len += sizeof(GlobalTransactionId); + len += sizeof(GlobalTransactionId) * snapshot_elements; return len; } @@ -81,9 +94,10 @@ gtm_serialize_snapshotdata(GTM_SnapshotData *data, char *buf, size_t buflen) if(data->sn_xcnt > 0) { memcpy(buf+len, data->sn_xip, sizeof(GlobalTransactionId) * data->sn_xcnt); + len += sizeof(GlobalTransactionId) * data->sn_xcnt; } #endif - + return len; } @@ -123,6 +137,10 @@ gtm_deserialize_snapshotdata(GTM_SnapshotData *data, const char *buf, size_t buf #else if (data->sn_xcnt > 0) { + /* + * Please note that this function runs with TopMemoryContext. So we must + * free this area manually later. + */ data->sn_xip = genAlloc(sizeof(GlobalTransactionId) * data->sn_xcnt); memcpy(data->sn_xip, buf+len, sizeof(GlobalTransactionId) * data->sn_xcnt); len += sizeof(GlobalTransactionId) * data->sn_xcnt; @@ -139,6 +157,9 @@ gtm_deserialize_snapshotdata(GTM_SnapshotData *data, const char *buf, size_t buf /* ----------------------------------------------------- * Get a serialized size ofGTM_TransactionInfo structure + * + * Original gti_gid serialization was just "null-terminated string". + * This should be prefixed with the length of the string. * ----------------------------------------------------- */ size_t @@ -165,11 +186,9 @@ gtm_get_transactioninfo_size(GTM_TransactionInfo *data) len += sizeof(uint32); /* gti_coordcount */ len += sizeof(PGXC_NodeId) * data->gti_coordcount; /* gti_coordinators */ - + len += sizeof(uint32); if ( data->gti_gid != NULL ) - len += strlen(data->gti_gid) + 1; /* gti_gid */ - else - len += 1; + len += strlen(data->gti_gid); /* gti_gid */ len += gtm_get_snapshotdata_size( &(data->gti_current_snapshot) ); /* gti_current_snapshot */ @@ -261,22 +280,29 @@ gtm_serialize_transactioninfo(GTM_TransactionInfo *data, char *buf, size_t bufle } /* GTM_TransactionInfo.gti_gid */ - if ( data->gti_gid!=NULL ) + if (data->gti_gid != NULL) { - memcpy(buf+len, data->gti_gid, strlen(data->gti_gid)); - len += strlen(data->gti_gid) + 1; /* null-terminated */ + uint32 gidlen; + + gidlen = (uint32)strlen(data->gti_gid); + memcpy(buf+len, &gidlen, sizeof(uint32)); + len += sizeof(uint32); + memcpy(buf+len, data->gti_gid, gidlen); + len += gidlen; } else { - *(buf+len) = '\0'; - len += 1; + uint32 gidlen = 0; + + memcpy(buf+len, &gidlen, sizeof(uint32)); + len += sizeof(uint32); } /* GTM_TransactionInfo.gti_current_snapshot */ buf2 = malloc( gtm_get_snapshotdata_size( &(data->gti_current_snapshot) ) ); i = gtm_serialize_snapshotdata( &(data->gti_current_snapshot), - buf2, - gtm_get_snapshotdata_size( &(data->gti_current_snapshot) )); + buf2, + gtm_get_snapshotdata_size( &(data->gti_current_snapshot) )); memcpy(buf+len, buf2, i); free(buf2); len += i; @@ -359,7 +385,7 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size #else if (data->gti_datanodes > 0) { - data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); + data->gti_datanodes = (PGXC_NodeId *)genAlloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); } else { @@ -385,7 +411,7 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size #else if (data->gti_coordinators > 0) { - data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); + data->gti_coordinators = (PGXC_NodeId *)genAlloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); } else { @@ -404,16 +430,22 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size } /* GTM_TransactionInfo.gti_gid */ - if ( *(buf+len) != '\0' ) - { - data->gti_gid = (char *)malloc( strlen(buf+len)+1); - strncpy(data->gti_gid, buf+len, strlen(buf+len) ); - len += strlen(buf+len) + 1; /* null-terminated */ - } - else { - data->gti_gid = NULL; - len += 1; + uint32 gti_len; + + memcpy(>i_len, buf+len, sizeof(uint32)); + len += sizeof(uint32); + if (gti_len > 0) + { + data->gti_gid = (char *)genAlloc(gti_len+1); + memcpy(data->gti_gid, buf+len, gti_len); + data->gti_gid[gti_len] = 0; /* null-terminated */ + len += gti_len; + } + else + { + data->gti_gid = NULL; + } } /* GTM_TransactionInfo.gti_current_snapshot */ @@ -547,7 +579,7 @@ gtm_serialize_transactions(GTM_Transactions *data, char *buf, size_t buflen) /* * GTM_Transactions.gt_transactions_array */ - for (i=0 ; i<txn_count ; i++) + for (i=0 ; i<GTM_MAX_GLOBAL_TRANSACTIONS ; i++) { char *buf2; size_t buflen2, len2; @@ -677,15 +709,13 @@ gtm_get_pgxcnodeinfo_size(GTM_PGXCNodeInfo *data) len += sizeof(GTM_PGXCNodeId); /* proxynum */ len += sizeof(GTM_PGXCNodePort); /* port */ - if ( data->ipaddress == NULL ) /* ipaddress */ - len += 1; - else - len += strlen(data->ipaddress) + 1; + len += sizeof(uint32); /* ipaddress length */ + if ( data->ipaddress != NULL ) /* ipaddress */ + len += strlen(data->ipaddress); - if ( data->datafolder == NULL ) /* datafolder */ - len += 1; - else - len += strlen(data->datafolder) + 1; + len += sizeof(uint32); /* datafolder length */ + if ( data->datafolder != NULL ) /* datafolder */ + len += strlen(data->datafolder); len += sizeof(GTM_PGXCNodeStatus); /* status */ @@ -696,6 +726,7 @@ size_t gtm_serialize_pgxcnodeinfo(GTM_PGXCNodeInfo *data, char *buf, size_t buflen) { size_t len = 0; + uint32 len_wk; /* size check */ if ( gtm_get_pgxcnodeinfo_size(data) > buflen ) @@ -720,25 +751,29 @@ gtm_serialize_pgxcnodeinfo(GTM_PGXCNodeInfo *data, char *buf, size_t buflen) len += sizeof(GTM_PGXCNodePort); /* GTM_PGXCNodeInfo.ipaddress */ - if ( data->ipaddress == NULL ) - { - len += 1; - } + if (data->ipaddress == NULL) + len_wk = 0; else + len_wk = (uint32)strlen(data->ipaddress); + memcpy(buf+len, &len_wk, sizeof(uint32)); + len += sizeof(uint32); + if (len_wk > 0) { - strncpy(buf+len, data->ipaddress, strlen(data->ipaddress)); - len += strlen(data->ipaddress) + 1; + memcpy(buf+len, &(data->ipaddress), len_wk); + len += len_wk; } /* GTM_PGXCNodeInfo.datafolder */ if ( data->datafolder == NULL ) - { - len += 1; - } + len_wk = 0; else + len_wk = (uint32)strlen(data->datafolder); + memcpy(buf+len, &len_wk, sizeof(uint32)); + len += sizeof(uint32); + if (len_wk > 0) { - strncpy(buf+len, data->datafolder, strlen(data->datafolder)); - len += strlen(data->datafolder) + 1; + memcpy(buf+len, &(data->datafolder), len_wk); + len += len_wk; } /* GTM_PGXCNodeInfo.status */ @@ -754,6 +789,7 @@ size_t gtm_deserialize_pgxcnodeinfo(GTM_PGXCNodeInfo *data, const char *buf, size_t buflen) { size_t len = 0; + uint32 len_wk; /* GTM_PGXCNodeInfo.type */ memcpy(&(data->type), buf+len, sizeof(GTM_PGXCNodeType)); @@ -772,29 +808,33 @@ gtm_deserialize_pgxcnodeinfo(GTM_PGXCNodeInfo *data, const char *buf, size_t buf len += sizeof(GTM_PGXCNodePort); /* GTM_PGXCNodeInfo.ipaddress */ - if ( *(buf+len) == '\0' ) + memcpy(&len_wk, buf+len, sizeof(uint32)); + len += sizeof(uint32); + if (len_wk == 0) { - len += 1; data->ipaddress = NULL; } else { - data->ipaddress = (char *)malloc( strlen(buf+len) ) + 1; - strncpy(data->ipaddress, buf+len, strlen(buf+len)); - len += strlen(buf+len) + 1; + data->ipaddress = (char *)genAlloc(len_wk + 1); + memcpy(data->ipaddress, buf+len, (size_t)len_wk); + data->ipaddress[len_wk] = 0; /* null_terminate */ + len += len_wk; } /* GTM_PGXCNodeInfo.datafolder */ - if ( *(buf+len) == '\0' ) + memcpy(&len_wk, buf+len, sizeof(uint32)); + len += sizeof(uint32); + if (len_wk == 0) { - len += 1; data->datafolder = NULL; } else { - data->datafolder = (char *)malloc( strlen(buf+len) ) + 1; - strncpy(data->datafolder, buf+len, strlen(buf+len)); - len += strlen(buf+len) + 1; + data->datafolder = (char *)genAlloc(len_wk + 1); + memcpy(data->datafolder, buf+len, (size_t)len_wk); + data->datafolder[len_wk] = 0; /* null_terminate */ + len += len_wk; } /* GTM_PGXCNodeInfo.status */ @@ -822,6 +862,8 @@ gtm_get_sequence_size(GTM_SeqInfo *seq) len += sizeof(GTM_Sequence); /* gs_max_value */ len += sizeof(bool); /* gs_cycle */ len += sizeof(bool); /* gs_called */ + len += sizeof(uint32); /* gs_ref_count */ + len += sizeof(uint32); /* ge_state */ return len; } @@ -870,6 +912,12 @@ gtm_serialize_sequence(GTM_SeqInfo *s, char *buf, size_t buflen) memcpy(buf+len, &s->gs_called, sizeof(bool)); len += sizeof(bool); /* gs_called */ + memcpy(buf+len, &s->gs_ref_count, sizeof(uint32)); + len += sizeof(uint32); /* gs_ref_count */ + + memcpy(buf+len, &s->gs_state, sizeof(uint32)); + len += sizeof(uint32); /* gs_state */ + return len; } @@ -879,14 +927,13 @@ gtm_deserialize_sequence(const char *buf, size_t buflen) size_t len = 0; GTM_SeqInfo *seq; - seq = (GTM_SeqInfo *)malloc( sizeof(GTM_SeqInfo) ); - seq->gs_key = (GTM_SequenceKeyData *)malloc( sizeof(GTM_SequenceKeyData) ); + seq = (GTM_SeqInfo *)genAlloc0(sizeof(GTM_SeqInfo)); + seq->gs_key = (GTM_SequenceKeyData *)genAlloc0(sizeof(GTM_SequenceKeyData)); memcpy(&seq->gs_key->gsk_keylen, buf+len, sizeof(uint32)); len += sizeof(uint32); /* gs_key.gsk_keylen */ - seq->gs_key->gsk_key = (char *)malloc(seq->gs_key->gsk_keylen+1); - memset(seq->gs_key->gsk_key, 0, seq->gs_key->gsk_keylen+1); + seq->gs_key->gsk_key = (char *)genAlloc0(seq->gs_key->gsk_keylen+1); memcpy(seq->gs_key->gsk_key, buf+len, seq->gs_key->gsk_keylen); len += seq->gs_key->gsk_keylen; /* gs_key.gsk_key */ @@ -917,5 +964,11 @@ gtm_deserialize_sequence(const char *buf, size_t buflen) memcpy(&seq->gs_called, buf+len, sizeof(bool)); len += sizeof(bool); /* gs_called */ + memcpy(&seq->gs_ref_count, buf+len, sizeof(uint32)); + len += sizeof(uint32); + + memcpy(&seq->gs_state, buf+len, sizeof(uint32)); + len += sizeof(uint32); + return seq; } diff --git a/src/gtm/main/gtm_standby.c b/src/gtm/main/gtm_standby.c index bca82f7..ee9ee58 100644 --- a/src/gtm/main/gtm_standby.c +++ b/src/gtm/main/gtm_standby.c @@ -163,25 +163,36 @@ gtm_standby_restore_gxid() /* data node */ GTMTransactions.gt_transactions_array[i].gti_datanodecount = txn.gt_transactions_array[i].gti_datanodecount; - GTMTransactions.gt_transactions_array[i].gti_datanodes - = palloc(sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_datanodecount); - memcpy(GTMTransactions.gt_transactions_array[i].gti_datanodes, - txn.gt_transactions_array[i].gti_datanodes, - sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_datanodecount); + if (GTMTransactions.gt_transactions_array[i].gti_datanodecount > 0) + { + GTMTransactions.gt_transactions_array[i].gti_datanodes + = txn.gt_transactions_array[i].gti_datanodes; + } + else + { + GTMTransactions.gt_transactions_array[i].gti_datanodes = NULL; + } /* coordinator node */ GTMTransactions.gt_transactions_array[i].gti_coordcount - = txn.gt_transactions_array[i].gti_coordcount; - GTMTransactions.gt_transactions_array[i].gti_coordinators - = palloc(sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_coordcount); - memcpy(GTMTransactions.gt_transactions_array[i].gti_coordinators, - txn.gt_transactions_array[i].gti_coordinators, - sizeof (PGXC_NodeId) * GTMTransactions.gt_transactions_array[i].gti_coordcount); + = txn.gt_transactions_array[i].gti_coordcount; + if (GTMTransactions.gt_transactions_array[i].gti_coordcount > 0) + { + GTMTransactions.gt_transactions_array[i].gti_coordinators + = txn.gt_transactions_array[i].gti_coordinators; + } + else + { + GTMTransactions.gt_transactions_array[i].gti_coordinators = NULL; + } if (txn.gt_transactions_array[i].gti_gid==NULL ) - GTMTransactions.gt_transactions_array[i].gti_gid = NULL; + GTMTransactions.gt_transactions_array[i].gti_gid = NULL; else - GTMTransactions.gt_transactions_array[i].gti_gid = strdup(txn.gt_transactions_array[i].gti_gid); + { + GTMTransactions.gt_transactions_array[i].gti_gid + = txn.gt_transactions_array[i].gti_gid; + } /* copy GTM_SnapshotData */ GTMTransactions.gt_transactions_array[i].gti_current_snapshot.sn_xmin @@ -201,6 +212,9 @@ gtm_standby_restore_gxid() GTMTransactions.gt_transactions_array[i].gti_vacuum = txn.gt_transactions_array[i].gti_vacuum; + /* + * Comment by K.S.: Is this correct? Is GTM_TXN_COMMITTED transaction categorized as "open"? + */ if ( GTMTransactions.gt_transactions_array[i].gti_state != GTM_TXN_ABORTED ) { GTMTransactions.gt_open_transactions = gtm_lappend(GTMTransactions.gt_open_transactions, ----------------------------------------------------------------------- Summary of changes: src/gtm/common/gtm_serialize.c | 169 ++++++++++++++++++++++++++-------------- src/gtm/main/gtm_standby.c | 40 +++++++--- 2 files changed, 138 insertions(+), 71 deletions(-) hooks/post-receive -- Postgres-XC |
From: Koichi S. <koi...@us...> - 2011-05-03 04:48:21
|
Project "Postgres-XC". The branch, ha_support has been updated via 23a4fb8b47248782417a97253bd83e13ec1db1b3 (commit) via 4f150e99559e638800a627c04026229fbd34c764 (commit) via 4f179ba15eac0e6416cc76693fc6c432e432488c (commit) from ea7e9f087bfa99445cfc1efbce6f440b534023ac (commit) - Log ----------------------------------------------------------------- commit 23a4fb8b47248782417a97253bd83e13ec1db1b3 Author: Koichi Suzuki <koi...@gm...> Date: Tue May 3 13:35:40 2011 +0900 This is to add "virtual class" memory allocation/deallocation especially for gtm/client submodules. Beckground: GTN-Standby backs up GTM-ACT data in synchronous way. gtm/client submodule do this work. Because this submodule takes care of send/receive current GTM-ACT status, gtm/clinet occasionally has to allocate the memory as needed. Because gtm/client should run as a part of GTM/GTM-Standby, GTM-Proxy, independent application (such as pgxc_clean) and postgres, famous "palloc" series of utility calls has to be different routine depending upon its running environment. Implemnetation can be done by asking the environment (mcxt.c or correspoinding source) to provide entries of such memory allocation functions. Framework of this virtualization can be found in gen_alloc.h. Postgres (e.g.coordinator and datanode) implementation is in src/backend/utils/mmgr/mcxt.c. GTM/GTM-Standby/GTM-Proxy implementation is in gtm/common/mcxt.c. pgxc_clean implmentation is in src/pgxc/pgxc_clean/common.c. palloc.h's are modified to reflect these changes. gtm_serialize.c and gtm_serialize_debug.c modifications are to include memory allocation in transaction information deserialization (need to allocate memory dynamically for each snapshot). Added/modified files are: modified: src/backend/utils/mmgr/mcxt.c modified: src/gtm/common/gtm_serialize.c modified: src/gtm/common/gtm_serialize_debug.c modified: src/gtm/common/mcxt.c new file: src/include/gen_alloc.h modified: src/include/gtm/palloc.h modified: src/include/utils/palloc.h modified: src/pgxc/pgxc_clean/common.c diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index ae4ed73..64f2dc6 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -702,7 +702,7 @@ pgport_palloc(Size sz) char * pgport_pstrdup(const char *str) { - return pstrdup(str); +< return pstrdup(str); } @@ -714,3 +714,17 @@ pgport_pfree(void *pointer) } #endif + +#ifdef PGXC +#include "gen_alloc.h" + +void *current_memcontext(void); + +void *current_memcontext() +{ + return((void *)CurrentMemoryContext); +} + +Gen_Alloc genAlloc_class = {MemoryContextAlloc, MemoryContextAllocZero, repalloc, pfree, current_memcontext}; + +#endif diff --git a/src/gtm/common/gtm_serialize.c b/src/gtm/common/gtm_serialize.c index cdd9cdd..0e4843f 100644 --- a/src/gtm/common/gtm_serialize.c +++ b/src/gtm/common/gtm_serialize.c @@ -2,7 +2,7 @@ #include "gtm/gtm_c.h" #include "gtm/elog.h" -#include "gtm/palloc.h" +// #include "gtm/palloc.h" #include "gtm/gtm.h" #include "gtm/gtm_txn.h" #include "gtm/gtm_seq.h" @@ -13,6 +13,8 @@ #include "gtm/pqformat.h" #include "gtm/gtm_msg.h" +#include "gen_alloc.h" + #include "gtm/gtm_serialize.h" //#include "gtm/gtm_list.h" @@ -68,8 +70,19 @@ gtm_serialize_snapshotdata(GTM_SnapshotData *data, char *buf, size_t buflen) len += sizeof(uint32); /* GTM_SnapshotData.sn_xip */ +#if 0 + /* + * This block of code seems to be wrong. data->sn_xip is an array of GlobalTransacionIDs + * and the number of elements are indicated by sn_xcnt. + */ memcpy(buf+len, &(data->sn_xip), sizeof(GlobalTransactionId)); len += sizeof(GlobalTransactionId); +#else + if(data->sn_xcnt > 0) + { + memcpy(buf+len, data->sn_xip, sizeof(GlobalTransactionId) * data->sn_xcnt); + } +#endif return len; } @@ -100,8 +113,25 @@ gtm_deserialize_snapshotdata(GTM_SnapshotData *data, const char *buf, size_t buf len += sizeof(uint32); /* GTM_SnapshotData.sn_xip */ +#if 0 + /* + * As pointed out in gtm_serialize_snapshotdata(), the following block of codes + * is wrong either. + */ memcpy(&(data->sn_xip), buf+len, sizeof(GlobalTransactionId)); len += sizeof(GlobalTransactionId); +#else + if (data->sn_xcnt > 0) + { + data->sn_xip = genAlloc(sizeof(GlobalTransactionId) * data->sn_xcnt); + memcpy(data->sn_xip, buf+len, sizeof(GlobalTransactionId) * data->sn_xcnt); + len += sizeof(GlobalTransactionId) * data->sn_xcnt; + } + else + { + data->sn_xip = NULL; + } +#endif return len; } @@ -321,8 +351,21 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size len += sizeof(uint32); /* GTM_TransactionInfo.gti_datanodes */ +#if 0 + /* + * The following block of code is harmful because data->gti_datanodes can be zero + */ data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); - +#else + if (data->gti_datanodes > 0) + { + data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); + } + else + { + data->gti_datanodes = NULL; + } +#endif for (i=0 ; i<data->gti_datanodecount ; i++) { memcpy(&(data->gti_datanodes[i]), buf+len, sizeof(PGXC_NodeId)); @@ -334,7 +377,21 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size len += sizeof(uint32); /* GTM_TransactionInfo.gti_coordinators */ +#if 0 + /* + * The following block of code is harmful because data->gti_coordinators can be zero + */ data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); +#else + if (data->gti_coordinators > 0) + { + data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); + } + else + { + data->gti_coordinators = NULL; + } +#endif for (i=0 ; i<data->gti_coordcount ; i++) { diff --git a/src/gtm/common/gtm_serialize_debug.c b/src/gtm/common/gtm_serialize_debug.c index d9d689e..e1dd854 100644 --- a/src/gtm/common/gtm_serialize_debug.c +++ b/src/gtm/common/gtm_serialize_debug.c @@ -17,6 +17,8 @@ void dump_transactioninfo_elog(GTM_TransactionInfo *txn) { + int ii; + elog(LOG, " ========= GTM_TransactionInfo ========="); elog(LOG, " gti_handle: %d", txn->gti_handle); elog(LOG, " gti_thread_id: %ld", txn->gti_thread_id); @@ -38,7 +40,15 @@ dump_transactioninfo_elog(GTM_TransactionInfo *txn) elog(LOG, " sn_xmax: %d", txn->gti_current_snapshot.sn_xmax); elog(LOG, " sn_recent_global_xmin: %d", txn->gti_current_snapshot.sn_recent_global_xmin); elog(LOG, " sn_xcnt: %d", txn->gti_current_snapshot.sn_xcnt); +#if 0 + /* The next code is wrong. */ elog(LOG, " sn_xip: %d", *(txn->gti_current_snapshot.sn_xip)); +#else + for(ii = 0; ii < txn->gti_current_snapshot.sn_xcnt; ii++) + { + elog (LOG, " sn_xip[%d]: %d", ii, txn->gti_current_snapshot.sn_xip[ii]); + } +#endif elog(LOG, " gti_snapshot_set: %d", txn->gti_snapshot_set); elog(LOG, " gti_vacuum: %d", txn->gti_vacuum); diff --git a/src/gtm/common/mcxt.c b/src/gtm/common/mcxt.c index bf27499..592c135 100644 --- a/src/gtm/common/mcxt.c +++ b/src/gtm/common/mcxt.c @@ -760,4 +760,18 @@ pgport_pfree(void *pointer) pfree(pointer); } + #endif + +#include "gen_alloc.h" + +void *current_memcontext(void); + +void *current_memcontext() +{ + + return((void *)CurrentMemoryContext); +} + +Gen_Alloc genAlloc_class = {MemoryContextAlloc, MemoryContextAllocZero, repalloc, pfree, current_memcontext}; + diff --git a/src/include/gen_alloc.h b/src/include/gen_alloc.h new file mode 100644 index 0000000..708752d --- /dev/null +++ b/src/include/gen_alloc.h @@ -0,0 +1,26 @@ +#ifndef GEN_ALLOC_H +#define GEN_ALLOC_H + +/* + * Common memory allocation binary interface both for Postgres and GTM processes. + * + * Especially needed by gtm_serialize.c and gtm_serialize_debug.c + */ + +typedef struct Gen_Alloc +{ + void * (* alloc) (void *, size_t); + void * (* alloc0) (void *, size_t); + void * (* realloc) (void *, size_t); + void (* free) (void *); + void * (* current_memcontext) (void); +} Gen_Alloc; + +extern Gen_Alloc genAlloc_class; + +#define genAlloc(x) genAlloc_class.alloc(genAlloc_class.current_memcontext(), x) +#define genRealloc(x, y) genAlloc_class.realloc(x, y); +#define genFree(x) genAlloc_class.free(x); +#define genAlloc0(x) genAlloc_class.alloc0(genAlloc_class.current_memcontext(), x) + +#endif /* GEN_ALLOC_H */ diff --git a/src/include/gtm/palloc.h b/src/include/gtm/palloc.h index 2efaaa4..33416a2 100644 --- a/src/include/gtm/palloc.h +++ b/src/include/gtm/palloc.h @@ -87,4 +87,12 @@ extern char *pgport_pstrdup(const char *str); extern void pgport_pfree(void *pointer); #endif +#ifdef PGXC +/* + * The following part provides common palloc binary interface. This + * is needed especially for gtm_serialize.c and gtm_serialize_debug.c. + */ +#include "gen_alloc.h" +#endif + #endif /* PALLOC_H */ diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h index e504ffa..88e1396 100644 --- a/src/include/utils/palloc.h +++ b/src/include/utils/palloc.h @@ -105,4 +105,12 @@ extern char *pgport_pstrdup(const char *str); extern void pgport_pfree(void *pointer); #endif +#ifdef PGXC +/* + * The following part provides common palloc binary interface. This + * is needed especially for gtm_serialize.c and gtm_serialize_debug.c. + */ +#include "gen_alloc.h" +#endif + #endif /* PALLOC_H */ diff --git a/src/pgxc/pgxc_clean/common.c b/src/pgxc/pgxc_clean/common.c index 3f01f67..4b9c96f 100644 --- a/src/pgxc/pgxc_clean/common.c +++ b/src/pgxc/pgxc_clean/common.c @@ -50,17 +50,17 @@ dispmsg(errlevel el, const char *format, ...) switch (el) { case lvl_info: - fprintf(stdout, lvlstr[el]); + fprintf(stdout, "%s", lvlstr[el]); break; case lvl_warn: case lvl_error: - fprintf(stderr, lvlstr[el]); + fprintf(stderr, "%s", lvlstr[el]); break; case lvl_debug: - fprintf(stdout, lvlstr[el]); + fprintf(stdout, "%s", lvlstr[el]); break; default: - fprintf(stdout, lvlstr[0]); + fprintf(stdout, "%s", lvlstr[0]); break; } @@ -79,3 +79,49 @@ dispmsg(errlevel el, const char *format, ...) fflush(stdout); } } + +/* + * Now, every gtm-interface user has to provide it's own memory context. + * GTM and Postgres (postmaster) already provide this as their own mcxt.c. + * pgxc_clean provide this here. + */ + +#include "gen_alloc.h" + +static void *my_malloc(void * context, size_t size); +static void *get_mycontext(void); +static void *my_realloc(void * ptr, size_t size); +static void my_free(void *ptr); +static void *my_malloc0(void *context, size_t size); + +static void *my_malloc(void * context, size_t size) +{ + return(malloc(size)); +} + +static void *get_mycontext() +{ + return(NULL); +} + +static void *my_realloc(void * ptr, size_t size) +{ + return(realloc(ptr, size)); +} + +static void my_free(void *ptr) +{ + free(ptr); +} + +static void *my_malloc0(void *context, size_t size) +{ + void *rv; + rv = malloc(size); + if (rv == NULL) + return(rv); + memset(rv, 0, size); + return(rv); +} + +Gen_Alloc genAlloc_class = {my_malloc, my_malloc0, my_realloc, my_free, get_mycontext}; commit 4f150e99559e638800a627c04026229fbd34c764 Author: Koichi Suzuki <koichi@ks-ubuntu-notepc.(none)> Date: Tue May 3 13:22:19 2011 +0900 Revert "This is to add "virtual class" memory allocation/deallocation especially for gtm/client" This reverts commit 4f179ba15eac0e6416cc76693fc6c432e432488c. diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 64f2dc6..ae4ed73 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -702,7 +702,7 @@ pgport_palloc(Size sz) char * pgport_pstrdup(const char *str) { -< return pstrdup(str); + return pstrdup(str); } @@ -714,17 +714,3 @@ pgport_pfree(void *pointer) } #endif - -#ifdef PGXC -#include "gen_alloc.h" - -void *current_memcontext(void); - -void *current_memcontext() -{ - return((void *)CurrentMemoryContext); -} - -Gen_Alloc genAlloc_class = {MemoryContextAlloc, MemoryContextAllocZero, repalloc, pfree, current_memcontext}; - -#endif diff --git a/src/gtm/common/gtm_serialize.c b/src/gtm/common/gtm_serialize.c index 0e4843f..cdd9cdd 100644 --- a/src/gtm/common/gtm_serialize.c +++ b/src/gtm/common/gtm_serialize.c @@ -2,7 +2,7 @@ #include "gtm/gtm_c.h" #include "gtm/elog.h" -// #include "gtm/palloc.h" +#include "gtm/palloc.h" #include "gtm/gtm.h" #include "gtm/gtm_txn.h" #include "gtm/gtm_seq.h" @@ -13,8 +13,6 @@ #include "gtm/pqformat.h" #include "gtm/gtm_msg.h" -#include "gen_alloc.h" - #include "gtm/gtm_serialize.h" //#include "gtm/gtm_list.h" @@ -70,19 +68,8 @@ gtm_serialize_snapshotdata(GTM_SnapshotData *data, char *buf, size_t buflen) len += sizeof(uint32); /* GTM_SnapshotData.sn_xip */ -#if 0 - /* - * This block of code seems to be wrong. data->sn_xip is an array of GlobalTransacionIDs - * and the number of elements are indicated by sn_xcnt. - */ memcpy(buf+len, &(data->sn_xip), sizeof(GlobalTransactionId)); len += sizeof(GlobalTransactionId); -#else - if(data->sn_xcnt > 0) - { - memcpy(buf+len, data->sn_xip, sizeof(GlobalTransactionId) * data->sn_xcnt); - } -#endif return len; } @@ -113,25 +100,8 @@ gtm_deserialize_snapshotdata(GTM_SnapshotData *data, const char *buf, size_t buf len += sizeof(uint32); /* GTM_SnapshotData.sn_xip */ -#if 0 - /* - * As pointed out in gtm_serialize_snapshotdata(), the following block of codes - * is wrong either. - */ memcpy(&(data->sn_xip), buf+len, sizeof(GlobalTransactionId)); len += sizeof(GlobalTransactionId); -#else - if (data->sn_xcnt > 0) - { - data->sn_xip = genAlloc(sizeof(GlobalTransactionId) * data->sn_xcnt); - memcpy(data->sn_xip, buf+len, sizeof(GlobalTransactionId) * data->sn_xcnt); - len += sizeof(GlobalTransactionId) * data->sn_xcnt; - } - else - { - data->sn_xip = NULL; - } -#endif return len; } @@ -351,21 +321,8 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size len += sizeof(uint32); /* GTM_TransactionInfo.gti_datanodes */ -#if 0 - /* - * The following block of code is harmful because data->gti_datanodes can be zero - */ data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); -#else - if (data->gti_datanodes > 0) - { - data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); - } - else - { - data->gti_datanodes = NULL; - } -#endif + for (i=0 ; i<data->gti_datanodecount ; i++) { memcpy(&(data->gti_datanodes[i]), buf+len, sizeof(PGXC_NodeId)); @@ -377,21 +334,7 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size len += sizeof(uint32); /* GTM_TransactionInfo.gti_coordinators */ -#if 0 - /* - * The following block of code is harmful because data->gti_coordinators can be zero - */ data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); -#else - if (data->gti_coordinators > 0) - { - data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); - } - else - { - data->gti_coordinators = NULL; - } -#endif for (i=0 ; i<data->gti_coordcount ; i++) { diff --git a/src/gtm/common/gtm_serialize_debug.c b/src/gtm/common/gtm_serialize_debug.c index e1dd854..d9d689e 100644 --- a/src/gtm/common/gtm_serialize_debug.c +++ b/src/gtm/common/gtm_serialize_debug.c @@ -17,8 +17,6 @@ void dump_transactioninfo_elog(GTM_TransactionInfo *txn) { - int ii; - elog(LOG, " ========= GTM_TransactionInfo ========="); elog(LOG, " gti_handle: %d", txn->gti_handle); elog(LOG, " gti_thread_id: %ld", txn->gti_thread_id); @@ -40,15 +38,7 @@ dump_transactioninfo_elog(GTM_TransactionInfo *txn) elog(LOG, " sn_xmax: %d", txn->gti_current_snapshot.sn_xmax); elog(LOG, " sn_recent_global_xmin: %d", txn->gti_current_snapshot.sn_recent_global_xmin); elog(LOG, " sn_xcnt: %d", txn->gti_current_snapshot.sn_xcnt); -#if 0 - /* The next code is wrong. */ elog(LOG, " sn_xip: %d", *(txn->gti_current_snapshot.sn_xip)); -#else - for(ii = 0; ii < txn->gti_current_snapshot.sn_xcnt; ii++) - { - elog (LOG, " sn_xip[%d]: %d", ii, txn->gti_current_snapshot.sn_xip[ii]); - } -#endif elog(LOG, " gti_snapshot_set: %d", txn->gti_snapshot_set); elog(LOG, " gti_vacuum: %d", txn->gti_vacuum); diff --git a/src/gtm/common/mcxt.c b/src/gtm/common/mcxt.c index 592c135..bf27499 100644 --- a/src/gtm/common/mcxt.c +++ b/src/gtm/common/mcxt.c @@ -760,18 +760,4 @@ pgport_pfree(void *pointer) pfree(pointer); } - #endif - -#include "gen_alloc.h" - -void *current_memcontext(void); - -void *current_memcontext() -{ - - return((void *)CurrentMemoryContext); -} - -Gen_Alloc genAlloc_class = {MemoryContextAlloc, MemoryContextAllocZero, repalloc, pfree, current_memcontext}; - diff --git a/src/include/gen_alloc.h b/src/include/gen_alloc.h deleted file mode 100644 index 708752d..0000000 --- a/src/include/gen_alloc.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef GEN_ALLOC_H -#define GEN_ALLOC_H - -/* - * Common memory allocation binary interface both for Postgres and GTM processes. - * - * Especially needed by gtm_serialize.c and gtm_serialize_debug.c - */ - -typedef struct Gen_Alloc -{ - void * (* alloc) (void *, size_t); - void * (* alloc0) (void *, size_t); - void * (* realloc) (void *, size_t); - void (* free) (void *); - void * (* current_memcontext) (void); -} Gen_Alloc; - -extern Gen_Alloc genAlloc_class; - -#define genAlloc(x) genAlloc_class.alloc(genAlloc_class.current_memcontext(), x) -#define genRealloc(x, y) genAlloc_class.realloc(x, y); -#define genFree(x) genAlloc_class.free(x); -#define genAlloc0(x) genAlloc_class.alloc0(genAlloc_class.current_memcontext(), x) - -#endif /* GEN_ALLOC_H */ diff --git a/src/include/gtm/palloc.h b/src/include/gtm/palloc.h index 33416a2..2efaaa4 100644 --- a/src/include/gtm/palloc.h +++ b/src/include/gtm/palloc.h @@ -87,12 +87,4 @@ extern char *pgport_pstrdup(const char *str); extern void pgport_pfree(void *pointer); #endif -#ifdef PGXC -/* - * The following part provides common palloc binary interface. This - * is needed especially for gtm_serialize.c and gtm_serialize_debug.c. - */ -#include "gen_alloc.h" -#endif - #endif /* PALLOC_H */ diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h index 88e1396..e504ffa 100644 --- a/src/include/utils/palloc.h +++ b/src/include/utils/palloc.h @@ -105,12 +105,4 @@ extern char *pgport_pstrdup(const char *str); extern void pgport_pfree(void *pointer); #endif -#ifdef PGXC -/* - * The following part provides common palloc binary interface. This - * is needed especially for gtm_serialize.c and gtm_serialize_debug.c. - */ -#include "gen_alloc.h" -#endif - #endif /* PALLOC_H */ diff --git a/src/pgxc/pgxc_clean/common.c b/src/pgxc/pgxc_clean/common.c index 4b9c96f..3f01f67 100644 --- a/src/pgxc/pgxc_clean/common.c +++ b/src/pgxc/pgxc_clean/common.c @@ -50,17 +50,17 @@ dispmsg(errlevel el, const char *format, ...) switch (el) { case lvl_info: - fprintf(stdout, "%s", lvlstr[el]); + fprintf(stdout, lvlstr[el]); break; case lvl_warn: case lvl_error: - fprintf(stderr, "%s", lvlstr[el]); + fprintf(stderr, lvlstr[el]); break; case lvl_debug: - fprintf(stdout, "%s", lvlstr[el]); + fprintf(stdout, lvlstr[el]); break; default: - fprintf(stdout, "%s", lvlstr[0]); + fprintf(stdout, lvlstr[0]); break; } @@ -79,49 +79,3 @@ dispmsg(errlevel el, const char *format, ...) fflush(stdout); } } - -/* - * Now, every gtm-interface user has to provide it's own memory context. - * GTM and Postgres (postmaster) already provide this as their own mcxt.c. - * pgxc_clean provide this here. - */ - -#include "gen_alloc.h" - -static void *my_malloc(void * context, size_t size); -static void *get_mycontext(void); -static void *my_realloc(void * ptr, size_t size); -static void my_free(void *ptr); -static void *my_malloc0(void *context, size_t size); - -static void *my_malloc(void * context, size_t size) -{ - return(malloc(size)); -} - -static void *get_mycontext() -{ - return(NULL); -} - -static void *my_realloc(void * ptr, size_t size) -{ - return(realloc(ptr, size)); -} - -static void my_free(void *ptr) -{ - free(ptr); -} - -static void *my_malloc0(void *context, size_t size) -{ - void *rv; - rv = malloc(size); - if (rv == NULL) - return(rv); - memset(rv, 0, size); - return(rv); -} - -Gen_Alloc genAlloc_class = {my_malloc, my_malloc0, my_realloc, my_free, get_mycontext}; commit 4f179ba15eac0e6416cc76693fc6c432e432488c Author: Koichi Suzuki <koichi@ks-ubuntu-notepc.(none)> Date: Tue May 3 13:09:59 2011 +0900 This is to add "virtual class" memory allocation/deallocation especially for gtm/client submodules. Beckground: GTN-Standby backs up GTM-ACT data in synchronous way. gtm/client submodule do this work. Because this submodule takes care of send/receive current GTM-ACT status, gtm/clinet occasionally has to allocate the memory as needed. Because gtm/client should run as a part of GTM/GTM-Standby, GTM-Proxy, independent application (such as pgxc_clean) and postgres, famous "palloc" series of utility calls has to be different routine depending upon its running environment. Implemnetation can be done by asking the environment (mcxt.c or correspoinding source) to provide entries of such memory allocation functions. Framework of this virtualization can be found in gen_alloc.h. Postgres (e.g.coordinator and datanode) implementation is in src/backend/utils/mmgr/mcxt.c. GTM/GTM-Standby/GTM-Proxy implementation is in gtm/common/mcxt.c. pgxc_clean implmentation is in src/pgxc/pgxc_clean/common.c. palloc.h's are modified to reflect these changes. gtm_serialize.c and gtm_serialize_debug.c modifications are to include memory allocation in transaction information deserialization (need to allocate memory dynamically for each snapshot). Files modified are: modified: src/backend/utils/mmgr/mcxt.c modified: src/gtm/common/gtm_serialize.c modified: src/gtm/common/gtm_serialize_debug.c modified: src/gtm/common/mcxt.c new file: src/include/gen_alloc.h modified: src/include/gtm/palloc.h modified: src/include/utils/palloc.h modified: src/pgxc/pgxc_clean/common.c diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index ae4ed73..64f2dc6 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -702,7 +702,7 @@ pgport_palloc(Size sz) char * pgport_pstrdup(const char *str) { - return pstrdup(str); +< return pstrdup(str); } @@ -714,3 +714,17 @@ pgport_pfree(void *pointer) } #endif + +#ifdef PGXC +#include "gen_alloc.h" + +void *current_memcontext(void); + +void *current_memcontext() +{ + return((void *)CurrentMemoryContext); +} + +Gen_Alloc genAlloc_class = {MemoryContextAlloc, MemoryContextAllocZero, repalloc, pfree, current_memcontext}; + +#endif diff --git a/src/gtm/common/gtm_serialize.c b/src/gtm/common/gtm_serialize.c index cdd9cdd..0e4843f 100644 --- a/src/gtm/common/gtm_serialize.c +++ b/src/gtm/common/gtm_serialize.c @@ -2,7 +2,7 @@ #include "gtm/gtm_c.h" #include "gtm/elog.h" -#include "gtm/palloc.h" +// #include "gtm/palloc.h" #include "gtm/gtm.h" #include "gtm/gtm_txn.h" #include "gtm/gtm_seq.h" @@ -13,6 +13,8 @@ #include "gtm/pqformat.h" #include "gtm/gtm_msg.h" +#include "gen_alloc.h" + #include "gtm/gtm_serialize.h" //#include "gtm/gtm_list.h" @@ -68,8 +70,19 @@ gtm_serialize_snapshotdata(GTM_SnapshotData *data, char *buf, size_t buflen) len += sizeof(uint32); /* GTM_SnapshotData.sn_xip */ +#if 0 + /* + * This block of code seems to be wrong. data->sn_xip is an array of GlobalTransacionIDs + * and the number of elements are indicated by sn_xcnt. + */ memcpy(buf+len, &(data->sn_xip), sizeof(GlobalTransactionId)); len += sizeof(GlobalTransactionId); +#else + if(data->sn_xcnt > 0) + { + memcpy(buf+len, data->sn_xip, sizeof(GlobalTransactionId) * data->sn_xcnt); + } +#endif return len; } @@ -100,8 +113,25 @@ gtm_deserialize_snapshotdata(GTM_SnapshotData *data, const char *buf, size_t buf len += sizeof(uint32); /* GTM_SnapshotData.sn_xip */ +#if 0 + /* + * As pointed out in gtm_serialize_snapshotdata(), the following block of codes + * is wrong either. + */ memcpy(&(data->sn_xip), buf+len, sizeof(GlobalTransactionId)); len += sizeof(GlobalTransactionId); +#else + if (data->sn_xcnt > 0) + { + data->sn_xip = genAlloc(sizeof(GlobalTransactionId) * data->sn_xcnt); + memcpy(data->sn_xip, buf+len, sizeof(GlobalTransactionId) * data->sn_xcnt); + len += sizeof(GlobalTransactionId) * data->sn_xcnt; + } + else + { + data->sn_xip = NULL; + } +#endif return len; } @@ -321,8 +351,21 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size len += sizeof(uint32); /* GTM_TransactionInfo.gti_datanodes */ +#if 0 + /* + * The following block of code is harmful because data->gti_datanodes can be zero + */ data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); - +#else + if (data->gti_datanodes > 0) + { + data->gti_datanodes = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_datanodecount ); + } + else + { + data->gti_datanodes = NULL; + } +#endif for (i=0 ; i<data->gti_datanodecount ; i++) { memcpy(&(data->gti_datanodes[i]), buf+len, sizeof(PGXC_NodeId)); @@ -334,7 +377,21 @@ gtm_deserialize_transactioninfo(GTM_TransactionInfo *data, const char *buf, size len += sizeof(uint32); /* GTM_TransactionInfo.gti_coordinators */ +#if 0 + /* + * The following block of code is harmful because data->gti_coordinators can be zero + */ data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); +#else + if (data->gti_coordinators > 0) + { + data->gti_coordinators = (PGXC_NodeId *)malloc( sizeof(PGXC_NodeId) * data->gti_coordcount ); + } + else + { + data->gti_coordinators = NULL; + } +#endif for (i=0 ; i<data->gti_coordcount ; i++) { diff --git a/src/gtm/common/gtm_serialize_debug.c b/src/gtm/common/gtm_serialize_debug.c index d9d689e..e1dd854 100644 --- a/src/gtm/common/gtm_serialize_debug.c +++ b/src/gtm/common/gtm_serialize_debug.c @@ -17,6 +17,8 @@ void dump_transactioninfo_elog(GTM_TransactionInfo *txn) { + int ii; + elog(LOG, " ========= GTM_TransactionInfo ========="); elog(LOG, " gti_handle: %d", txn->gti_handle); elog(LOG, " gti_thread_id: %ld", txn->gti_thread_id); @@ -38,7 +40,15 @@ dump_transactioninfo_elog(GTM_TransactionInfo *txn) elog(LOG, " sn_xmax: %d", txn->gti_current_snapshot.sn_xmax); elog(LOG, " sn_recent_global_xmin: %d", txn->gti_current_snapshot.sn_recent_global_xmin); elog(LOG, " sn_xcnt: %d", txn->gti_current_snapshot.sn_xcnt); +#if 0 + /* The next code is wrong. */ elog(LOG, " sn_xip: %d", *(txn->gti_current_snapshot.sn_xip)); +#else + for(ii = 0; ii < txn->gti_current_snapshot.sn_xcnt; ii++) + { + elog (LOG, " sn_xip[%d]: %d", ii, txn->gti_current_snapshot.sn_xip[ii]); + } +#endif elog(LOG, " gti_snapshot_set: %d", txn->gti_snapshot_set); elog(LOG, " gti_vacuum: %d", txn->gti_vacuum); diff --git a/src/gtm/common/mcxt.c b/src/gtm/common/mcxt.c index bf27499..592c135 100644 --- a/src/gtm/common/mcxt.c +++ b/src/gtm/common/mcxt.c @@ -760,4 +760,18 @@ pgport_pfree(void *pointer) pfree(pointer); } + #endif + +#include "gen_alloc.h" + +void *current_memcontext(void); + +void *current_memcontext() +{ + + return((void *)CurrentMemoryContext); +} + +Gen_Alloc genAlloc_class = {MemoryContextAlloc, MemoryContextAllocZero, repalloc, pfree, current_memcontext}; + diff --git a/src/include/gen_alloc.h b/src/include/gen_alloc.h new file mode 100644 index 0000000..708752d --- /dev/null +++ b/src/include/gen_alloc.h @@ -0,0 +1,26 @@ +#ifndef GEN_ALLOC_H +#define GEN_ALLOC_H + +/* + * Common memory allocation binary interface both for Postgres and GTM processes. + * + * Especially needed by gtm_serialize.c and gtm_serialize_debug.c + */ + +typedef struct Gen_Alloc +{ + void * (* alloc) (void *, size_t); + void * (* alloc0) (void *, size_t); + void * (* realloc) (void *, size_t); + void (* free) (void *); + void * (* current_memcontext) (void); +} Gen_Alloc; + +extern Gen_Alloc genAlloc_class; + +#define genAlloc(x) genAlloc_class.alloc(genAlloc_class.current_memcontext(), x) +#define genRealloc(x, y) genAlloc_class.realloc(x, y); +#define genFree(x) genAlloc_class.free(x); +#define genAlloc0(x) genAlloc_class.alloc0(genAlloc_class.current_memcontext(), x) + +#endif /* GEN_ALLOC_H */ diff --git a/src/include/gtm/palloc.h b/src/include/gtm/palloc.h index 2efaaa4..33416a2 100644 --- a/src/include/gtm/palloc.h +++ b/src/include/gtm/palloc.h @@ -87,4 +87,12 @@ extern char *pgport_pstrdup(const char *str); extern void pgport_pfree(void *pointer); #endif +#ifdef PGXC +/* + * The following part provides common palloc binary interface. This + * is needed especially for gtm_serialize.c and gtm_serialize_debug.c. + */ +#include "gen_alloc.h" +#endif + #endif /* PALLOC_H */ diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h index e504ffa..88e1396 100644 --- a/src/include/utils/palloc.h +++ b/src/include/utils/palloc.h @@ -105,4 +105,12 @@ extern char *pgport_pstrdup(const char *str); extern void pgport_pfree(void *pointer); #endif +#ifdef PGXC +/* + * The following part provides common palloc binary interface. This + * is needed especially for gtm_serialize.c and gtm_serialize_debug.c. + */ +#include "gen_alloc.h" +#endif + #endif /* PALLOC_H */ diff --git a/src/pgxc/pgxc_clean/common.c b/src/pgxc/pgxc_clean/common.c index 3f01f67..4b9c96f 100644 --- a/src/pgxc/pgxc_clean/common.c +++ b/src/pgxc/pgxc_clean/common.c @@ -50,17 +50,17 @@ dispmsg(errlevel el, const char *format, ...) switch (el) { case lvl_info: - fprintf(stdout, lvlstr[el]); + fprintf(stdout, "%s", lvlstr[el]); break; case lvl_warn: case lvl_error: - fprintf(stderr, lvlstr[el]); + fprintf(stderr, "%s", lvlstr[el]); break; case lvl_debug: - fprintf(stdout, lvlstr[el]); + fprintf(stdout, "%s", lvlstr[el]); break; default: - fprintf(stdout, lvlstr[0]); + fprintf(stdout, "%s", lvlstr[0]); break; } @@ -79,3 +79,49 @@ dispmsg(errlevel el, const char *format, ...) fflush(stdout); } } + +/* + * Now, every gtm-interface user has to provide it's own memory context. + * GTM and Postgres (postmaster) already provide this as their own mcxt.c. + * pgxc_clean provide this here. + */ + +#include "gen_alloc.h" + +static void *my_malloc(void * context, size_t size); +static void *get_mycontext(void); +static void *my_realloc(void * ptr, size_t size); +static void my_free(void *ptr); +static void *my_malloc0(void *context, size_t size); + +static void *my_malloc(void * context, size_t size) +{ + return(malloc(size)); +} + +static void *get_mycontext() +{ + return(NULL); +} + +static void *my_realloc(void * ptr, size_t size) +{ + return(realloc(ptr, size)); +} + +static void my_free(void *ptr) +{ + free(ptr); +} + +static void *my_malloc0(void *context, size_t size) +{ + void *rv; + rv = malloc(size); + if (rv == NULL) + return(rv); + memset(rv, 0, size); + return(rv); +} + +Gen_Alloc genAlloc_class = {my_malloc, my_malloc0, my_realloc, my_free, get_mycontext}; ----------------------------------------------------------------------- Summary of changes: src/backend/utils/mmgr/mcxt.c | 16 ++++++++- src/gtm/common/gtm_serialize.c | 61 ++++++++++++++++++++++++++++++++- src/gtm/common/gtm_serialize_debug.c | 10 +++++ src/gtm/common/mcxt.c | 14 ++++++++ src/include/gen_alloc.h | 26 ++++++++++++++ src/include/gtm/palloc.h | 8 ++++ src/include/utils/palloc.h | 8 ++++ src/pgxc/pgxc_clean/common.c | 54 +++++++++++++++++++++++++++-- 8 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 src/include/gen_alloc.h hooks/post-receive -- Postgres-XC |