void print_exception(VM *vm, VALUE result) { // TODO: fprintf to stderr and teach dump_titled to optionally fprintf to stderr too printf("====== Exception of type '%s' ======\n", obj_to_cstring(NGS_TYPE_NAME(NORMAL_TYPE_INSTANCE_TYPE(result)))); // TODO: maybe macro to iterate attributes VALUE fields = NGS_TYPE_FIELDS(NORMAL_TYPE_INSTANCE_TYPE(result)); HASH_OBJECT_ENTRY *e; for(e=HASH_HEAD(fields); e; e=e->insertion_order_next) { if(obj_is_of_type(ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)], vm->Backtrace)) { printf("=== [ backtrace ] ===\n"); // Backtrace.frames = [{"closure": ..., "ip": ...}, ...] VALUE backtrace = ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)]; VALUE frames; assert(get_normal_type_instace_attribute(backtrace, make_string("frames"), &frames) == METHOD_OK); unsigned int i; for(i = 0; i < OBJ_LEN(frames); i++) { VALUE frame, resolved_ip, ip; frame = ARRAY_ITEMS(frames)[i]; H(ip, frame, "ip"); resolved_ip = resolve_ip(vm, (IP)(GET_INT(ip) - 1)); if(IS_HASH(resolved_ip)) { VALUE file, first_line, first_column, last_line, last_column; HASH_OBJECT_ENTRY *closure_entry; char *closure_name = "<anonymous>"; H(file, resolved_ip, "file"); H(first_line, resolved_ip, "first_line"); H(first_column, resolved_ip, "first_column"); H(last_line, resolved_ip, "last_line"); H(last_column, resolved_ip, "last_column"); closure_entry = get_hash_key(frame, make_string("closure")); if(closure_entry && IS_CLOSURE(closure_entry->val) && (IS_HASH(CLOSURE_OBJ_ATTRS(closure_entry->val)))) { HASH_OBJECT_ENTRY *name_entry; name_entry = get_hash_key(CLOSURE_OBJ_ATTRS(closure_entry->val), make_string("name")); if(name_entry) { closure_name = obj_to_cstring(name_entry->val); } } // TODO: fix types printf("[Frame #%u] %s:%d:%d - %d:%d [in %s]\n", i, obj_to_cstring(file), (int) GET_INT(first_line), (int) GET_INT(first_column), (int) GET_INT(last_line), (int) GET_INT(last_column), closure_name); } else { printf("[Frame #%u] (no source location)\n", i); } } continue; } if(obj_is_of_type(ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)], vm->Exception)) { assert(IS_STRING(e->key)); printf("---8<--- %s - start ---8<---\n", obj_to_cstring(e->key)); print_exception(vm, ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)]); printf("---8<--- %s - end ---8<---\n", obj_to_cstring(e->key)); continue; } if(IS_STRING(e->key)) { dump_titled(obj_to_cstring(e->key), ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)]); } else { // Should not happen dump_titled("attribute key", e->key); dump_titled("attribute value", ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(result))[GET_INT(e->val)]); } } }
//_________________________________________________________________________ void graph_molloy_hash::depth_isolated(int v, long &calls, int &left_to_explore, int dmax, int * &Kbuff, bool *visited) { if(left_to_explore==0) return; // if(yapido) fprintf(stderr,"%d ",deg[v]); if(--left_to_explore == 0) return; if(deg[v]+1>=dmax) { left_to_explore = 0; return; } *(Kbuff++) = v; visited[v] = true; // print(); // fflush(stdout); calls++; int *copy = NULL; int *w = neigh[v]; if(IS_HASH(deg[v])) { copy = new int[deg[v]]; H_copy(copy,w,deg[v]); w = copy; } qsort(deg, w, deg[v]); w+=deg[v]; for(int i=deg[v]; i--; ) { if(visited[*--w]) calls++; else depth_isolated(*w, calls, left_to_explore, dmax, Kbuff, visited); if(left_to_explore==0) break; } if(copy!=NULL) delete[] copy; }
ImmT c_rt_lib0exec(ImmT ___nl__func, ImmT *___ref___arrI){ if(!IS_HASH(___nl__func) && !IS_ARRHASH(___nl__func)) nl_die_internal("function struct must by a hash", NAME(___nl__func)); NlFunction *func = (NlFunction*)c_rt_lib0hash_get_value_dec(___nl__func, c_rt_lib0string_new("name")); if(!IS_FUNC(func)) nl_die_internal("can call only function: %s", NAME(func)); if(!IS_ARR(*___ref___arrI)) nl_die_internal("expected array: %s", NAME(*___ref___arrI)); NlArray *arr = priv_arr_to_change(___ref___arrI); ImmT (*f)(int n, ImmT *arg) = func->f; dec_ref((ImmT*)func); return (*f)(arr->size, arr->arr); }
/* ------------------------------------------------------ * pgstathashindex() * * Usage: SELECT * FROM pgstathashindex('hashindex'); * ------------------------------------------------------ */ Datum pgstathashindex(PG_FUNCTION_ARGS) { Oid relid = PG_GETARG_OID(0); BlockNumber nblocks; BlockNumber blkno; Relation rel; HashIndexStat stats; BufferAccessStrategy bstrategy; HeapTuple tuple; TupleDesc tupleDesc; Datum values[8]; bool nulls[8]; Buffer metabuf; HashMetaPage metap; float8 free_percent; uint64 total_space; rel = index_open(relid, AccessShareLock); /* index_open() checks that it's an index */ if (!IS_HASH(rel)) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("relation \"%s\" is not a HASH index", RelationGetRelationName(rel)))); /* * Reject attempts to read non-local temporary relations; we would be * likely to get wrong data since we have no visibility into the owning * session's local buffers. */ if (RELATION_IS_OTHER_TEMP(rel)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot access temporary indexes of other sessions"))); /* Get the information we need from the metapage. */ memset(&stats, 0, sizeof(stats)); metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE); metap = HashPageGetMeta(BufferGetPage(metabuf)); stats.version = metap->hashm_version; stats.space_per_page = metap->hashm_bsize; _hash_relbuf(rel, metabuf); /* Get the current relation length */ nblocks = RelationGetNumberOfBlocks(rel); /* prepare access strategy for this index */ bstrategy = GetAccessStrategy(BAS_BULKREAD); /* Start from blkno 1 as 0th block is metapage */ for (blkno = 1; blkno < nblocks; blkno++) { Buffer buf; Page page; CHECK_FOR_INTERRUPTS(); buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy); LockBuffer(buf, BUFFER_LOCK_SHARE); page = (Page) BufferGetPage(buf); if (PageIsNew(page)) stats.unused_pages++; else if (PageGetSpecialSize(page) != MAXALIGN(sizeof(HashPageOpaqueData))) ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("index \"%s\" contains corrupted page at block %u", RelationGetRelationName(rel), BufferGetBlockNumber(buf)))); else { HashPageOpaque opaque; int pagetype; opaque = (HashPageOpaque) PageGetSpecialPointer(page); pagetype = opaque->hasho_flag & LH_PAGE_TYPE; if (pagetype == LH_BUCKET_PAGE) { stats.bucket_pages++; GetHashPageStats(page, &stats); } else if (pagetype == LH_OVERFLOW_PAGE) { stats.overflow_pages++; GetHashPageStats(page, &stats); } else if (pagetype == LH_BITMAP_PAGE) stats.bitmap_pages++; else if (pagetype == LH_UNUSED_PAGE) stats.unused_pages++; else ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("unexpected page type 0x%04X in HASH index \"%s\" block %u", opaque->hasho_flag, RelationGetRelationName(rel), BufferGetBlockNumber(buf)))); } UnlockReleaseBuffer(buf); } /* Done accessing the index */ index_close(rel, AccessShareLock); /* Count unused pages as free space. */ stats.free_space += stats.unused_pages * stats.space_per_page; /* * Total space available for tuples excludes the metapage and the bitmap * pages. */ total_space = (nblocks - (stats.bitmap_pages + 1)) * stats.space_per_page; if (total_space == 0) free_percent = 0.0; else free_percent = 100.0 * stats.free_space / total_space; /* * Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); tupleDesc = BlessTupleDesc(tupleDesc); /* * Build and return the tuple */ MemSet(nulls, 0, sizeof(nulls)); values[0] = Int32GetDatum(stats.version); values[1] = Int64GetDatum((int64) stats.bucket_pages); values[2] = Int64GetDatum((int64) stats.overflow_pages); values[3] = Int64GetDatum((int64) stats.bitmap_pages); values[4] = Int64GetDatum((int64) stats.unused_pages); values[5] = Int64GetDatum(stats.live_items); values[6] = Int64GetDatum(stats.dead_items); values[7] = Float8GetDatum(free_percent); tuple = heap_form_tuple(tupleDesc, values, nulls); PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); }
/* ------------------------------------------------ * hash_bitmap_info() * * Get bitmap information for a particular overflow page * * Usage: SELECT * FROM hash_bitmap_info('con_hash_index'::regclass, 5); * ------------------------------------------------ */ Datum hash_bitmap_info(PG_FUNCTION_ARGS) { Oid indexRelid = PG_GETARG_OID(0); uint64 ovflblkno = PG_GETARG_INT64(1); HashMetaPage metap; Buffer metabuf, mapbuf; BlockNumber bitmapblkno; Page mappage; bool bit = false; TupleDesc tupleDesc; Relation indexRel; uint32 ovflbitno; int32 bitmappage, bitmapbit; HeapTuple tuple; int i, j; Datum values[3]; bool nulls[3]; uint32 *freep; if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw page functions")))); indexRel = index_open(indexRelid, AccessShareLock); if (!IS_HASH(indexRel)) elog(ERROR, "relation \"%s\" is not a hash index", RelationGetRelationName(indexRel)); if (RELATION_IS_OTHER_TEMP(indexRel)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot access temporary tables of other sessions"))); if (ovflblkno >= RelationGetNumberOfBlocks(indexRel)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("block number " UINT64_FORMAT " is out of range for relation \"%s\"", ovflblkno, RelationGetRelationName(indexRel)))); /* Read the metapage so we can determine which bitmap page to use */ metabuf = _hash_getbuf(indexRel, HASH_METAPAGE, HASH_READ, LH_META_PAGE); metap = HashPageGetMeta(BufferGetPage(metabuf)); /* * Reject attempt to read the bit for a metapage or bitmap page; this is * only meaningful for overflow pages. */ if (ovflblkno == 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid overflow block number %u", (BlockNumber) ovflblkno))); for (i = 0; i < metap->hashm_nmaps; i++) if (metap->hashm_mapp[i] == ovflblkno) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid overflow block number %u", (BlockNumber) ovflblkno))); /* * Identify overflow bit number. This will error out for primary bucket * pages, and we've already rejected the metapage and bitmap pages above. */ ovflbitno = _hash_ovflblkno_to_bitno(metap, (BlockNumber) ovflblkno); bitmappage = ovflbitno >> BMPG_SHIFT(metap); bitmapbit = ovflbitno & BMPG_MASK(metap); if (bitmappage >= metap->hashm_nmaps) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid overflow block number %u", (BlockNumber) ovflblkno))); bitmapblkno = metap->hashm_mapp[bitmappage]; _hash_relbuf(indexRel, metabuf); /* Check the status of bitmap bit for overflow page */ mapbuf = _hash_getbuf(indexRel, bitmapblkno, HASH_READ, LH_BITMAP_PAGE); mappage = BufferGetPage(mapbuf); freep = HashPageGetBitmap(mappage); bit = ISSET(freep, bitmapbit) != 0; _hash_relbuf(indexRel, mapbuf); index_close(indexRel, AccessShareLock); /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); tupleDesc = BlessTupleDesc(tupleDesc); MemSet(nulls, 0, sizeof(nulls)); j = 0; values[j++] = Int64GetDatum((int64) bitmapblkno); values[j++] = Int32GetDatum(bitmapbit); values[j++] = BoolGetDatum(bit); tuple = heap_form_tuple(tupleDesc, values, nulls); PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); }
static void _dump(VALUE v, int level) { char **symbols; void *symbols_buffer[1]; VALUE *ptr; size_t i; HASH_OBJECT_ENTRY *e; HASH_OBJECT_ENTRY **buckets; if(IS_NULL(v)) { printf("%*s* null\n", level << 1, ""); goto exit; } if(IS_TRUE(v)) { printf("%*s* true\n", level << 1, ""); goto exit; } if(IS_FALSE(v)) { printf("%*s* false\n", level << 1, ""); goto exit; } if(IS_UNDEF(v)) { printf("%*s* undef\n", level << 1, ""); goto exit; } if(IS_KWARGS_MARKER(v)){ printf("%*s* kwargs marker\n", level << 1, ""); goto exit; } if(IS_INT(v)) { printf("%*s* int %" VALUE_NUM_FMT "\n", level << 1, "", GET_INT(v)); goto exit; } if(IS_REAL(v)) { printf("%*s* real %g\n", level << 1, "", REAL_OBJECT_VAL(v)); goto exit; } if(IS_STRING(v)) { // TODO: properly handle // 1. non-printable characters // 2. zero character printf("%*s* string(len=%zu) %.*s\n", level << 1, "", OBJ_LEN(v), (int) OBJ_LEN(v), (char *)OBJ_DATA_PTR(v)); goto exit; } if(IS_NATIVE_METHOD(v)) { symbols_buffer[0] = OBJ_DATA_PTR(v); symbols = backtrace_symbols(symbols_buffer, 1); printf("%*s* native method %s at %p req_params=%d\n", level << 1, "", symbols[0], OBJ_DATA_PTR(v), NATIVE_METHOD_OBJ_N_REQ_PAR(v)); for(i=0; i<NATIVE_METHOD_OBJ_N_REQ_PAR(v); i++) { printf("%*s* required parameter %zu\n", (level+1) << 1, "", i+1); _dump(NATIVE_METHOD_OBJ_PARAMS(v)[i*2+0], level+2); _dump(NATIVE_METHOD_OBJ_PARAMS(v)[i*2+1], level+2); } goto exit; } if(IS_CLOSURE(v)) { printf("%*s* closure name=%s ip=%zu locals_including_params=%d req_params=%d opt_params=%d n_uplevels=%d params_flags=%d\n", level << 1, "", IS_NULL(CLOSURE_OBJ_NAME(v)) ? "(none)" : obj_to_cstring(CLOSURE_OBJ_NAME(v)), CLOSURE_OBJ_IP(v), CLOSURE_OBJ_N_LOCALS(v), CLOSURE_OBJ_N_REQ_PAR(v), CLOSURE_OBJ_N_OPT_PAR(v), CLOSURE_OBJ_N_UPLEVELS(v), CLOSURE_OBJ_PARAMS_FLAGS(v) ); for(i=0; i<CLOSURE_OBJ_N_REQ_PAR(v); i++) { printf("%*s* required parameter %zu (name and type follow)\n", (level+1) << 1, "", i+1); _dump(CLOSURE_OBJ_PARAMS(v)[i*2+0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[i*2+1], level+2); } for(i=0; i<CLOSURE_OBJ_N_OPT_PAR(v); i++) { printf("%*s* optional parameter %zu (name, type and default value follow)\n", (level+1) << 1, "", i+1); _dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 1], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 2], level+2); } i = CLOSURE_OBJ_N_REQ_PAR(v)*2 + CLOSURE_OBJ_N_OPT_PAR(v)*3; if(CLOSURE_OBJ_PARAMS_FLAGS(v) & PARAMS_FLAG_ARR_SPLAT) { printf("%*s* array splat parameter\n", (level+1) << 1, ""); _dump(CLOSURE_OBJ_PARAMS(v)[i+0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[i+1], level+2); i+=3; } if(CLOSURE_OBJ_PARAMS_FLAGS(v) & PARAMS_FLAG_HASH_SPLAT) { printf("%*s* hash splat parameter\n", (level+1) << 1, ""); _dump(CLOSURE_OBJ_PARAMS(v)[i+0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[i+1], level+2); i+=3; } goto exit; } if(IS_ARRAY(v)) { printf("%*s* array of length %zu\n", level << 1, "", OBJ_LEN(v)); for(i=0, ptr=(VALUE *)OBJ_DATA_PTR(v); i<OBJ_LEN(v); i++, ptr++) { _dump(*ptr, level+1); } goto exit; } if(IS_HASH(v)) { printf("%*s* hash with total of %zu items in %zu buckets at %p\n", level << 1, "", OBJ_LEN(v), HASH_BUCKETS_N(v), OBJ_DATA_PTR(v)); buckets = OBJ_DATA_PTR(v); for(i=0; i<HASH_BUCKETS_N(v); i++) { if(!buckets[i]) { continue; } printf("%*s* bucket # %zu\n", (level+1) << 1, "", i); for(e=buckets[i]; e; e=e->bucket_next) { printf("%*s* item at %p with hash() of %u insertion_order_prev=%p insertion_order_next=%p \n", (level+2) << 1, "", (void *)e, e->hash, (void *)e->insertion_order_prev, (void *)e->insertion_order_next); printf("%*s* key\n", (level+3) << 1, ""); _dump(e->key, level+4); printf("%*s* value\n", (level+3) << 1, ""); _dump(e->val, level+4); } } goto exit; } if(IS_NGS_TYPE(v)) { printf("%*s* type (name and optionally constructors and parents follow) id=%" PRIdPTR " ptr=%p\n", level << 1, "", NGS_TYPE_ID(v), IS_NORMAL_TYPE(v) ? v.ptr : 0); _dump(NGS_TYPE_NAME(v), level + 1); if(level < 3) { _dump(NGS_TYPE_FIELDS(v), level + 1); _dump(NGS_TYPE_CONSTRUCTORS(v), level + 1); _dump(NGS_TYPE_PARENTS(v), level + 1); } goto exit; } if(IS_CLIB(v)) { printf("%*s* C library (name follows) ptr=%p\n", level << 1, "", OBJ_DATA_PTR(v)); _dump(CLIB_OBJECT_NAME(v), level + 1); goto exit; } if(IS_CSYM(v)) { printf("%*s* C symbol (name and libraray follow) ptr=%p\n", level << 1, "", OBJ_DATA_PTR(v)); _dump(CSYM_OBJECT_NAME(v), level + 1); _dump(CSYM_OBJECT_LIB(v), level + 1); goto exit; } if(IS_NORMAL_TYPE_CONSTRUCTOR(v)) { printf("%*s* user type constructor (type optionally follows)\n", level << 1, ""); if(level < 3) { _dump(OBJ_DATA(v), level + 1); } goto exit; } if(IS_NORMAL_TYPE_INSTANCE(v)) { printf("%*s* user type instance (type and fields optionally follow)\n", level << 1, ""); // level < 4 so that uncaught exception ImplNotFound could display the type of the arguments if(level < 4) { _dump(NORMAL_TYPE_INSTANCE_TYPE(v), level + 1); _dump(NORMAL_TYPE_INSTANCE_FIELDS(v), level + 1); } goto exit; } printf("%*s* (dump not implemented for the object at %p)\n", level << 1, "", OBJ_DATA_PTR(v)); exit: return; }