|
12 | 12 | #include "storage/procarray.h"
|
13 | 13 | #include "storage/shm_toc.h"
|
14 | 14 | #include "catalog/pg_type.h"
|
| 15 | +#include "catalog/pg_authid.h" |
| 16 | +#include "utils/syscache.h" |
| 17 | +#include "access/htup_details.h" |
15 | 18 |
|
16 | 19 | #include "pgstat.h"
|
17 | 20 | #include "fmgr.h"
|
@@ -54,6 +57,7 @@ handle_sigterm(SIGNAL_ARGS)
|
54 | 57 | }
|
55 | 58 |
|
56 | 59 | errno = save_errno;
|
| 60 | + proc_exit(0); |
57 | 61 | }
|
58 | 62 |
|
59 | 63 | int read_worker_job_limit(void)
|
@@ -598,3 +602,222 @@ resubmit(PG_FUNCTION_ARGS)
|
598 | 602 |
|
599 | 603 | PG_RETURN_INT64(resubmit_current_job);
|
600 | 604 | }
|
| 605 | + |
| 606 | +/* main procedure for at command workers */ |
| 607 | + |
| 608 | +void at_executor_worker_main(Datum arg) |
| 609 | +{ |
| 610 | + schd_executor_share_t *shared; |
| 611 | + dsm_segment *seg; |
| 612 | + int result; |
| 613 | + int rc = 0; |
| 614 | + schd_executor_status_t status; |
| 615 | + bool lets_sleep = false; |
| 616 | + /* PGPROC *parent; */ |
| 617 | + double begin, elapsed; |
| 618 | + struct timeval tv; |
| 619 | + |
| 620 | + CurrentResourceOwner = ResourceOwnerCreate(NULL, "pgpro_scheduler_executor"); |
| 621 | + seg = dsm_attach(DatumGetInt32(arg)); |
| 622 | + if(seg == NULL) |
| 623 | + ereport(ERROR, |
| 624 | + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 625 | + errmsg("executor unable to map dynamic shared memory segment"))); |
| 626 | + shared = dsm_segment_address(seg); |
| 627 | + /* parent = BackendPidGetProc(MyBgworkerEntry->bgw_notify_pid); */ |
| 628 | + |
| 629 | + if(shared->status != SchdExecutorInit) |
| 630 | + { |
| 631 | + ereport(ERROR, |
| 632 | + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 633 | + errmsg("executor corrupted dynamic shared memory segment"))); |
| 634 | + } |
| 635 | + |
| 636 | + SetConfigOption("application_name", "pgp-s at executor", PGC_USERSET, PGC_S_SESSION); |
| 637 | + pgstat_report_activity(STATE_RUNNING, "initialize"); |
| 638 | + init_worker_mem_ctx("ExecutorMemoryContext"); |
| 639 | + BackgroundWorkerInitializeConnection(shared->database, NULL); |
| 640 | + |
| 641 | + pqsignal(SIGTERM, handle_sigterm); |
| 642 | + pqsignal(SIGHUP, worker_spi_sighup); |
| 643 | + BackgroundWorkerUnblockSignals(); |
| 644 | + |
| 645 | + while(1) |
| 646 | + { |
| 647 | + if(got_sighup) |
| 648 | + { |
| 649 | + got_sighup = false; |
| 650 | + ProcessConfigFile(PGC_SIGHUP); |
| 651 | + } |
| 652 | + CHECK_FOR_INTERRUPTS(); |
| 653 | + gettimeofday(&tv, NULL); |
| 654 | + begin = ((double)tv.tv_sec)*1000 + ((double)tv.tv_usec)/1000; |
| 655 | + result = process_one_job(shared, &status); |
| 656 | + gettimeofday(&tv, NULL); |
| 657 | + elapsed = ((double)tv.tv_sec)*1000 + ((double)tv.tv_usec)/1000 - begin; |
| 658 | + elog(LOG, "job done %d = %f", result, elapsed); |
| 659 | + |
| 660 | + if(result == 0) |
| 661 | + { |
| 662 | + lets_sleep = true; |
| 663 | + } |
| 664 | + else if(result < 0) |
| 665 | + { |
| 666 | + delete_worker_mem_ctx(); |
| 667 | + dsm_detach(seg); |
| 668 | + proc_exit(1); |
| 669 | + } |
| 670 | + CHECK_FOR_INTERRUPTS(); |
| 671 | + |
| 672 | + if(lets_sleep) |
| 673 | + { |
| 674 | + elog(LOG, "sleeping"); |
| 675 | + pgstat_report_activity(STATE_IDLE, "waiting for a job"); |
| 676 | + rc = WaitLatch(MyLatch, |
| 677 | + WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT, 1000L); |
| 678 | + ResetLatch(MyLatch); |
| 679 | + if(rc && rc & WL_POSTMASTER_DEATH) break; |
| 680 | + } |
| 681 | + } |
| 682 | + |
| 683 | + delete_worker_mem_ctx(); |
| 684 | + dsm_detach(seg); |
| 685 | + proc_exit(0); |
| 686 | +} |
| 687 | + |
| 688 | +int process_one_job(schd_executor_share_t *shared, schd_executor_status_t *status) |
| 689 | +{ |
| 690 | + char *error = NULL; |
| 691 | + job_t *job; |
| 692 | + int ret; |
| 693 | + char buff[512]; |
| 694 | + double begin, elapsed; |
| 695 | + struct timeval tv; |
| 696 | + |
| 697 | + *status = shared->status = SchdExecutorWork; |
| 698 | + shared->message[0] = 0; |
| 699 | + |
| 700 | + pgstat_report_activity(STATE_RUNNING, "initialize job"); |
| 701 | + START_SPI_SNAP(); |
| 702 | + |
| 703 | + gettimeofday(&tv, NULL); |
| 704 | + begin = ((double)tv.tv_sec)*1000 + ((double)tv.tv_usec)/1000; |
| 705 | + |
| 706 | + job = get_next_at_job_with_lock(shared->nodename, &error); |
| 707 | + |
| 708 | + gettimeofday(&tv, NULL); |
| 709 | + elapsed = ((double)tv.tv_sec)*1000 + ((double)tv.tv_usec)/1000 - begin; |
| 710 | + elog(LOG, "got jobs = %f", elapsed); |
| 711 | + |
| 712 | + if(!job) |
| 713 | + { |
| 714 | + STOP_SPI_SNAP(); |
| 715 | + if(error) |
| 716 | + { |
| 717 | + shared->status = SchdExecutorIdling; |
| 718 | + snprintf(shared->message, PGPRO_SCHEDULER_EXECUTOR_MESSAGE_MAX, |
| 719 | + "Cannot get job: %s", error); |
| 720 | + pfree(error); |
| 721 | + return -1; |
| 722 | + } |
| 723 | + shared->status = SchdExecutorIdling; |
| 724 | + return 0; |
| 725 | + } |
| 726 | + current_job_id = job->cron_id; |
| 727 | + pgstat_report_activity(STATE_RUNNING, "job initialized"); |
| 728 | + |
| 729 | + ResetAllOptions(); |
| 730 | + if(set_session_authorization_by_name(job->executor, &error) == InvalidOid) |
| 731 | + { |
| 732 | + if(error) |
| 733 | + { |
| 734 | + set_at_job_done(job, error, 0); |
| 735 | + snprintf(shared->message, PGPRO_SCHEDULER_EXECUTOR_MESSAGE_MAX, |
| 736 | + "Cannot set session auth: %s", error); |
| 737 | + pfree(error); |
| 738 | + } |
| 739 | + else |
| 740 | + { |
| 741 | + set_at_job_done(job, "Unknown set session auth error", 0); |
| 742 | + snprintf(shared->message, PGPRO_SCHEDULER_EXECUTOR_MESSAGE_MAX, |
| 743 | + "Cannot set session auth: unknown error"); |
| 744 | + } |
| 745 | + shared->status = SchdExecutorIdling; |
| 746 | + STOP_SPI_SNAP(); |
| 747 | + return 1; |
| 748 | + } |
| 749 | + |
| 750 | + pgstat_report_activity(STATE_RUNNING, "process job"); |
| 751 | + CHECK_FOR_INTERRUPTS(); |
| 752 | + SetConfigOption("schedule.transaction_state", "running", PGC_INTERNAL, PGC_S_SESSION); |
| 753 | + |
| 754 | + if(job->timelimit) |
| 755 | + { |
| 756 | +#ifdef HAVE_LONG_INT_64 |
| 757 | + sprintf(buff, "%ld", job->timelimit * 1000); |
| 758 | +#else |
| 759 | + sprintf(buff, "%lld", job->timelimit * 1000); |
| 760 | +#endif |
| 761 | + SetConfigOption("statement_timeout", buff, PGC_SUSET, PGC_S_OVERRIDE); |
| 762 | + } |
| 763 | + |
| 764 | + if(job->sql_params_n > 0) |
| 765 | + { |
| 766 | + ret = execute_spi_params_prepared(job->dosql[0], job->sql_params_n, job->sql_params, &error); |
| 767 | + } |
| 768 | + else |
| 769 | + { |
| 770 | + ret = execute_spi(job->dosql[0], &error); |
| 771 | + } |
| 772 | + ResetAllOptions(); |
| 773 | + SetConfigOption("enable_seqscan", "off", PGC_USERSET, PGC_S_SESSION); |
| 774 | + SetSessionAuthorization(BOOTSTRAP_SUPERUSERID, true); |
| 775 | + if(ret < 0) |
| 776 | + { |
| 777 | + if(error) |
| 778 | + { |
| 779 | + set_at_job_done(job, error, resubmit_current_job); |
| 780 | + pfree(error); |
| 781 | + } |
| 782 | + else |
| 783 | + { |
| 784 | + sprintf(buff, "error in command: code: %d", ret); |
| 785 | + set_at_job_done(job, buff, resubmit_current_job); |
| 786 | + } |
| 787 | + |
| 788 | + } |
| 789 | + else |
| 790 | + { |
| 791 | + set_at_job_done(job, NULL, resubmit_current_job); |
| 792 | + } |
| 793 | + STOP_SPI_SNAP(); |
| 794 | + |
| 795 | + resubmit_current_job = 0; |
| 796 | + current_job_id = -1; |
| 797 | + pgstat_report_activity(STATE_RUNNING, "finish job processing"); |
| 798 | + |
| 799 | + return 1; |
| 800 | +} |
| 801 | + |
| 802 | +Oid set_session_authorization_by_name(char *rolename, char **error) |
| 803 | +{ |
| 804 | + HeapTuple roleTup; |
| 805 | + Form_pg_authid rform; |
| 806 | + char buffer[512]; |
| 807 | + Oid roleoid; |
| 808 | + |
| 809 | + roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename)); |
| 810 | + if(!HeapTupleIsValid(roleTup)) |
| 811 | + { |
| 812 | + snprintf(buffer, 512, "There is no user name: %s", rolename); |
| 813 | + *error = _copy_string(buffer); |
| 814 | + return InvalidOid; |
| 815 | + } |
| 816 | + rform = (Form_pg_authid) GETSTRUCT(roleTup); |
| 817 | + roleoid = HeapTupleGetOid(roleTup); |
| 818 | + SetSessionAuthorization(roleoid, rform->rolsuper); |
| 819 | + ReleaseSysCache(roleTup); |
| 820 | + |
| 821 | + return roleoid; |
| 822 | +} |
| 823 | + |
0 commit comments