/* * truncates / compresses the node key * cpf_length .. common prefix length */ static GBT_VARKEY * gbt_var_node_truncate(const GBT_VARKEY *node, int32 cpf_length, const gbtree_vinfo *tinfo) { GBT_VARKEY *out = NULL; GBT_VARKEY_R r = gbt_var_key_readable(node); int32 len1 = VARSIZE(r.lower) - VARHDRSZ; int32 len2 = VARSIZE(r.upper) - VARHDRSZ; int32 si; char *out2; len1 = Min(len1, (cpf_length + 1)); len2 = Min(len2, (cpf_length + 1)); si = 2 * VARHDRSZ + INTALIGN(len1 + VARHDRSZ) + len2; out = (GBT_VARKEY *) palloc(si); SET_VARSIZE(out, si); memcpy(VARDATA(out), r.lower, len1 + VARHDRSZ); SET_VARSIZE(VARDATA(out), len1 + VARHDRSZ); out2 = VARDATA(out) + INTALIGN(len1 + VARHDRSZ); memcpy(out2, r.upper, len2 + VARHDRSZ); SET_VARSIZE(out2, len2 + VARHDRSZ); return out; }
/* * Create an entry to store in the index, from lower and upper bound. */ GBT_VARKEY * gbt_var_key_copy(const GBT_VARKEY_R *u) { int32 lowersize = VARSIZE(u->lower); int32 uppersize = VARSIZE(u->upper); GBT_VARKEY *r; r = (GBT_VARKEY *) palloc0(INTALIGN(lowersize) + uppersize + VARHDRSZ); memcpy(VARDATA(r), u->lower, lowersize); memcpy(VARDATA(r) + INTALIGN(lowersize), u->upper, uppersize); SET_VARSIZE(r, INTALIGN(lowersize) + uppersize + VARHDRSZ); return r; }
static void BgwPoolMainLoop(Datum arg) { BgwPoolExecutorCtx* ctx = (BgwPoolExecutorCtx*)arg; int id = ctx->id; BgwPool* pool = ctx->constructor(); int size; void* work; BackgroundWorkerUnblockSignals(); BackgroundWorkerInitializeConnection(pool->dbname, NULL); while(true) { PGSemaphoreLock(&pool->available); SpinLockAcquire(&pool->lock); size = *(int*)&pool->queue[pool->head]; Assert(size < pool->size); work = malloc(size); pool->pending -= 1; pool->active += 1; if (pool->lastPeakTime == 0 && pool->active == pool->nWorkers && pool->pending != 0) { pool->lastPeakTime = MtmGetSystemTime(); } if (pool->head + size + 4 > pool->size) { memcpy(work, pool->queue, size); pool->head = INTALIGN(size); } else { memcpy(work, &pool->queue[pool->head+4], size); pool->head += 4 + INTALIGN(size); } if (pool->size == pool->head) { pool->head = 0; } if (pool->producerBlocked) { pool->producerBlocked = false; PGSemaphoreUnlock(&pool->overflow); pool->lastPeakTime = 0; } SpinLockRelease(&pool->lock); pool->executor(id, work, size); free(work); SpinLockAcquire(&pool->lock); pool->active -= 1; pool->lastPeakTime = 0; SpinLockRelease(&pool->lock); } }
void BgwPoolExecute(BgwPool* pool, void* work, size_t size) { if (size+4 > pool->size) { /* * Size of work is larger than size of shared buffer: * run it immediately */ pool->executor(0, work, size); return; } SpinLockAcquire(&pool->lock); while (true) { if ((pool->head <= pool->tail && pool->size - pool->tail < size + 4 && pool->head < size) || (pool->head > pool->tail && pool->head - pool->tail < size + 4)) { if (pool->lastPeakTime == 0) { pool->lastPeakTime = MtmGetSystemTime(); } pool->producerBlocked = true; SpinLockRelease(&pool->lock); PGSemaphoreLock(&pool->overflow); SpinLockAcquire(&pool->lock); } else { pool->pending += 1; if (pool->lastPeakTime == 0 && pool->active == pool->nWorkers && pool->pending != 0) { pool->lastPeakTime = MtmGetSystemTime(); } *(int*)&pool->queue[pool->tail] = size; if (pool->size - pool->tail >= size + 4) { memcpy(&pool->queue[pool->tail+4], work, size); pool->tail += 4 + INTALIGN(size); } else { memcpy(pool->queue, work, size); pool->tail = INTALIGN(size); } if (pool->tail == pool->size) { pool->tail = 0; } PGSemaphoreUnlock(&pool->available); break; } } SpinLockRelease(&pool->lock); }
Datum domainname_parts(PG_FUNCTION_ARGS) { text *in = PG_GETARG_TEXT_P(0); const char *s = VARDATA(in); const char *b = s, *p = s, *e = s + VARSIZE_ANY_EXHDR(in); int nelems = 0; int nbytes = ARR_OVERHEAD_NONULLS(1); ArrayType *r; char *o; while (p < e) { b = p; STRSEARCH(p, e-p, *p == '.'); nelems ++; nbytes += VARHDRSZ + (p-b); nbytes = INTALIGN(nbytes); p ++; } r = (ArrayType *)palloc(nbytes); SET_VARSIZE(r, nbytes); r->ndim = 1; r->dataoffset = 0; r->elemtype = TEXTOID; *ARR_DIMS(r) = nelems; *ARR_LBOUND(r) = 1; p = s; o = ARR_DATA_PTR(r); while (p < e) { b = p; STRSEARCH(p, e-p, *p == '.'); SET_VARSIZE(o, VARHDRSZ+(p-b)); o = VARDATA(o); memcpy(o, b, p-b); o += INTALIGN(p-b); p ++; } PG_FREE_IF_COPY(in, 0); PG_RETURN_ARRAYTYPE_P(r); }
static bytea * gbt_bit_xfrm(bytea *leaf) { bytea *out = leaf; int s = INTALIGN(VARBITBYTES(leaf) + VARHDRSZ); out = palloc(s); SET_VARSIZE(out, s); memcpy((void *) VARDATA(out), (void *) VARBITS(leaf), VARBITBYTES(leaf)); return out; }
GBT_VARKEY * gbt_var_key_copy(const GBT_VARKEY_R *u, bool force_node) { GBT_VARKEY *r = NULL; if (u->lower == u->upper && !force_node) { /* leaf key mode */ r = (GBT_VARKEY *) palloc(VARSIZE(u->lower) + VARHDRSZ); memcpy(VARDATA(r), u->lower, VARSIZE(u->lower)); SET_VARSIZE(r, VARSIZE(u->lower) + VARHDRSZ); } else { /* node key mode */ r = (GBT_VARKEY *) palloc(INTALIGN(VARSIZE(u->lower)) + VARSIZE(u->upper) + VARHDRSZ); memcpy(VARDATA(r), u->lower, VARSIZE(u->lower)); memcpy(VARDATA(r) + INTALIGN(VARSIZE(u->lower)), u->upper, VARSIZE(u->upper)); SET_VARSIZE(r, INTALIGN(VARSIZE(u->lower)) + VARSIZE(u->upper) + VARHDRSZ); } return r; }
GBT_VARKEY_R gbt_var_key_readable(const GBT_VARKEY *k) { GBT_VARKEY_R r; r.lower = (bytea *) &(((char *) k)[VARHDRSZ]); if (VARSIZE(k) > (VARHDRSZ + (VARSIZE(r.lower)))) r.upper = (bytea *) &(((char *) k)[VARHDRSZ + INTALIGN(VARSIZE(r.lower))]); else r.upper = r.lower; return r; }
static bytea * gbt_bit_xfrm(bytea *leaf) { bytea *out = leaf; int sz = VARBITBYTES(leaf) + VARHDRSZ; int padded_sz = INTALIGN(sz); out = (bytea *) palloc(padded_sz); /* initialize the padding bytes to zero */ while (sz < padded_sz) ((char *) out)[sz++] = 0; SET_VARSIZE(out, padded_sz); memcpy((void *) VARDATA(out), (void *) VARBITS(leaf), VARBITBYTES(leaf)); return out; }
static PCPATCH * pcpatch_from_point_array(ArrayType *array, FunctionCallInfoData *fcinfo) { int nelems; bits8 *bitmap; int bitmask; size_t offset = 0; int i; uint32 pcid = 0; PCPATCH *pa; PCPOINTLIST *pl; PCSCHEMA *schema = 0; /* How many things in our array? */ nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); /* PgSQL supplies a bitmap of which array entries are null */ bitmap = ARR_NULLBITMAP(array); /* Empty array? Null return */ if ( nelems == 0 ) return NULL; /* Make our holder */ pl = pc_pointlist_make(nelems); offset = 0; bitmap = ARR_NULLBITMAP(array); bitmask = 1; for ( i = 0; i < nelems; i++ ) { /* Only work on non-NULL entries in the array */ if ( ! array_get_isnull(bitmap, i) ) { SERIALIZED_POINT *serpt = (SERIALIZED_POINT *)(ARR_DATA_PTR(array)+offset); PCPOINT *pt; if ( ! schema ) { schema = pc_schema_from_pcid(serpt->pcid, fcinfo); } if ( ! pcid ) { pcid = serpt->pcid; } else if ( pcid != serpt->pcid ) { elog(ERROR, "pcpatch_from_point_array: pcid mismatch (%d != %d)", serpt->pcid, pcid); } pt = pc_point_deserialize(serpt, schema); if ( ! pt ) { elog(ERROR, "pcpatch_from_point_array: point deserialization failed"); } pc_pointlist_add_point(pl, pt); offset += INTALIGN(VARSIZE(serpt)); } } if ( pl->npoints == 0 ) return NULL; pa = pc_patch_from_pointlist(pl); pc_pointlist_free(pl); return pa; }
static PCPATCH * pcpatch_from_patch_array(ArrayType *array, FunctionCallInfoData *fcinfo) { int nelems; bits8 *bitmap; int bitmask; size_t offset = 0; int i; uint32 pcid = 0; PCPATCH *pa; PCPATCH **palist; int numpatches = 0; PCSCHEMA *schema = 0; /* How many things in our array? */ nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); /* PgSQL supplies a bitmap of which array entries are null */ bitmap = ARR_NULLBITMAP(array); /* Empty array? Null return */ if ( nelems == 0 ) return NULL; /* Make our temporary list of patches */ palist = pcalloc(nelems*sizeof(PCPATCH*)); /* Read the patches out of the array and deserialize */ offset = 0; bitmap = ARR_NULLBITMAP(array); bitmask = 1; for ( i = 0; i < nelems; i++ ) { /* Only work on non-NULL entries in the array */ if ( ! array_get_isnull(bitmap, i) ) { SERIALIZED_PATCH *serpatch = (SERIALIZED_PATCH *)(ARR_DATA_PTR(array)+offset); if ( ! schema ) { schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); } if ( ! pcid ) { pcid = serpatch->pcid; } else if ( pcid != serpatch->pcid ) { elog(ERROR, "pcpatch_from_patch_array: pcid mismatch (%d != %d)", serpatch->pcid, pcid); } pa = pc_patch_deserialize(serpatch, schema); if ( ! pa ) { elog(ERROR, "pcpatch_from_patch_array: patch deserialization failed"); } palist[numpatches++] = pa; offset += INTALIGN(VARSIZE(serpatch)); } } /* Can't do anything w/ NULL */ if ( numpatches == 0 ) return NULL; /* Pass to the lib to build the output patch from the list */ pa = pc_patch_from_patchlist(palist, numpatches); /* Free the temporary patch list */ for ( i = 0; i < numpatches; i++ ) { pc_patch_free(palist[i]); } pcfree(palist); return pa; }
static int32 array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value) { HeapTuple typ_tuple; TypeTupleForm typ_struct; bool typbyval; int typlen; func_ptr proc_fn; int pronargs; int nitems, i, result; int ndim, *dim; char *p; /* Sanity checks */ if ((array == (ArrayType *) NULL) || (ARR_IS_LO(array) == true)) { /* elog(NOTICE, "array_iterator: array is null"); */ return (0); } ndim = ARR_NDIM(array); dim = ARR_DIMS(array); nitems = getNitems(ndim, dim); if (nitems == 0) { /* elog(NOTICE, "array_iterator: nitems = 0"); */ return (0); } /* Lookup element type information */ typ_tuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(elemtype),0,0,0); if (!HeapTupleIsValid(typ_tuple)) { elog(WARN,"array_iterator: cache lookup failed for type %d", elemtype); return 0; } typ_struct = (TypeTupleForm) GETSTRUCT(typ_tuple); typlen = typ_struct->typlen; typbyval = typ_struct->typbyval; /* Lookup the function entry point */ proc_fn == (func_ptr) NULL; fmgr_info(proc, &proc_fn, &pronargs); if ((proc_fn == NULL) || (pronargs != 2)) { elog(WARN, "array_iterator: fmgr_info lookup failed for oid %d", proc); return (0); } /* Scan the array and apply the operator to each element */ result = 0; p = ARR_DATA_PTR(array); for (i = 0; i < nitems; i++) { if (typbyval) { switch(typlen) { case 1: result = (int) (*proc_fn)(*p, value); break; case 2: result = (int) (*proc_fn)(* (int16 *) p, value); break; case 3: case 4: result = (int) (*proc_fn)(* (int32 *) p, value); break; } p += typlen; } else { result = (int) (*proc_fn)(p, value); if (typlen > 0) { p += typlen; } else { p += INTALIGN(* (int32 *) p); } } if (result) { if (!and) { return (1); } } else { if (and) { return (0); } } } if (and && result) { return (1); } else { return (0); } }