/* * Create a new file set * type is the WorkFileType for the files: BUFFILE or BFZ * can_be_reused: if set to false, then we don't insert this set into the cache, * since the caller is telling us there is no point. This can happen for * example when spilling during index creation. * ps is the PlanState for the subtree rooted at the operator * snapshot contains snapshot information for the current transaction * */ workfile_set * workfile_mgr_create_set(enum ExecWorkFileType type, bool can_be_reused, PlanState *ps) { Assert(NULL != workfile_mgr_cache); Plan *plan = NULL; if (ps != NULL) { plan = ps->plan; } AssertImply(can_be_reused, plan != NULL); NodeTag node_type = T_Invalid; if (ps != NULL) { node_type = ps->type; } char *dir_path = create_workset_directory(node_type, currentSliceId); if (!workfile_sets_resowner_callback_registered) { RegisterResourceReleaseCallback(workfile_set_free_callback, NULL); workfile_sets_resowner_callback_registered = true; } /* Create parameter info for the populate function */ workset_info set_info; set_info.file_type = type; set_info.nodeType = node_type; set_info.dir_path = dir_path; set_info.session_start_time = GetCurrentTimestamp(); set_info.operator_work_mem = get_operator_work_mem(ps); CacheEntry *newEntry = Cache_AcquireEntry(workfile_mgr_cache, &set_info); if (NULL == newEntry) { /* Clean up the directory we created. */ workfile_mgr_delete_set_directory(dir_path); /* Could not acquire another entry from the cache - we filled it up */ ereport(ERROR, (errmsg("could not create workfile manager entry: exceeded number of concurrent spilling queries"))); } /* Path has now been copied to the workfile_set. We can free it */ pfree(dir_path); /* Complete initialization of the entry with post-acquire actions */ Assert(NULL != newEntry); workfile_set *work_set = CACHE_ENTRY_PAYLOAD(newEntry); Assert(work_set != NULL); elog(gp_workfile_caching_loglevel, "new spill file set. key=0x%x prefix=%s opMemKB=" INT64_FORMAT, work_set->key, work_set->path, work_set->metadata.operator_work_mem); return work_set; }
/** * execute_fopen() * * refactor the fopen code for execute into this routine */ URL_FILE * url_execute_fopen(char *url, bool forwrite, extvar_t *ev, CopyState pstate) { URL_EXECUTE_FILE *file; int save_errno; struct itimers savetimers; pqsigfunc save_SIGPIPE; char *cmd; /* Execute command */ Assert(strncmp(url, EXEC_URL_PREFIX, strlen(EXEC_URL_PREFIX)) == 0); cmd = url + strlen(EXEC_URL_PREFIX); file = palloc0(sizeof(URL_EXECUTE_FILE)); file->common.type = CFTYPE_EXEC; /* marked as a EXEC */ file->common.url = pstrdup(url); file->shexec = make_command(cmd, ev); /* Execute command */ /* Clear process interval timers */ resetTimers(&savetimers); if (!execute_resowner_callback_registered) { RegisterResourceReleaseCallback(execute_abort_callback, NULL); execute_resowner_callback_registered = true; } file->handle = create_execute_handle(); /* * Preserve the SIGPIPE handler and set to default handling. This * allows "normal" SIGPIPE handling in the command pipeline. Normal * for PG is to *ignore* SIGPIPE. */ save_SIGPIPE = pqsignal(SIGPIPE, SIG_DFL); /* execute the user command */ file->handle->pid = popen_with_stderr(file->handle->pipes, file->shexec, forwrite); save_errno = errno; /* Restore the SIGPIPE handler */ pqsignal(SIGPIPE, save_SIGPIPE); /* Restore process interval timers */ restoreTimers(&savetimers); if (file->handle->pid == -1) { errno = save_errno; pfree(file->common.url); pfree(file); ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), errmsg("cannot start external table command: %m"), errdetail("Command: %s", cmd))); } return (URL_FILE *) file; }
int px_find_digest(const char *name, PX_MD **res) { const EVP_MD *md; EVP_MD_CTX *ctx; PX_MD *h; OSSLDigest *digest; if (!px_openssl_initialized) { px_openssl_initialized = 1; OpenSSL_add_all_algorithms(); } if (!resowner_callback_registered) { RegisterResourceReleaseCallback(digest_free_callback, NULL); resowner_callback_registered = true; } md = EVP_get_digestbyname(name); if (md == NULL) return PXE_NO_HASH; /* * Create an OSSLDigest object, an OpenSSL MD object, and a PX_MD object. * The order is crucial, to make sure we don't leak anything on * out-of-memory or other error. */ digest = MemoryContextAlloc(TopMemoryContext, sizeof(*digest)); ctx = EVP_MD_CTX_create(); if (!ctx) { pfree(digest); return -1; } if (EVP_DigestInit_ex(ctx, md, NULL) == 0) { pfree(digest); return -1; } digest->algo = md; digest->ctx = ctx; digest->owner = CurrentResourceOwner; digest->next = open_digests; digest->prev = NULL; open_digests = digest; /* The PX_MD object is allocated in the current memory context. */ h = px_alloc(sizeof(*h)); h->result_size = digest_result_size; h->block_size = digest_block_size; h->reset = digest_reset; h->update = digest_update; h->finish = digest_finish; h->free = digest_free; h->p.ptr = (void *) digest; *res = h; return 0; }