From patchwork Mon Aug 7 18:51:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 13344739 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A9DD2C001DB for ; Mon, 7 Aug 2023 18:51:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229991AbjHGSvt (ORCPT ); Mon, 7 Aug 2023 14:51:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40142 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229865AbjHGSvq (ORCPT ); Mon, 7 Aug 2023 14:51:46 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C0A28171E for ; Mon, 7 Aug 2023 11:51:44 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-4fe28e4671dso7865537e87.0 for ; Mon, 07 Aug 2023 11:51:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691434303; x=1692039103; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=EWK128KV/FPC578HhVA3Ufgz0FEGPzPqKqZtsyfJpNs=; b=IbTAXrIN62E2DqxjVIXE9PPDSUgObIFg2SvjRUfPbccs36ku1Z/hG/xfo+9/l8jpe9 KP+b6mlqH6fjeQebmuW0azH60j/4dUoLvTf/ZBcxcWhB3p+7wLLYTPTn6a+rQeRSIrJy u9STxR3v+74QHC+yWZIRPBPM5a+2H4r9VRDMd/czWBI6yJYXulgucnmg2zwEnC8KLRsN izjezhdd6C0wZDgvjKx31AJJC9tkdPrQGf9ZWOecDR0ko1fy22TyX9DQlrD0tUEpavwY zzeWOe3m7FtdoYeVh52ZD1d2ynnBuSjRdQJxLZy2xdf2jgEA8X8411gbbeZNP8dx1XfI 63IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691434303; x=1692039103; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EWK128KV/FPC578HhVA3Ufgz0FEGPzPqKqZtsyfJpNs=; b=RTOKXnHN/sT7bAsC3WVmzgdbCD5IkqPGYfpE1wtK5jN20wsodvfinz2bcYhR56MUw0 A3rUbnrEiaDCKUoQ4jx87TSKPzMiON9rzYFeeExbtHxA5KgLtW4ALV81TO70g3vFKleF iHoZUmMLNmEV+Uyumzoce6c5ZMCPRkZwJXosaEl6FRpvyS/2sjNnsmudRPD7tLPZp7ac QWGWBQoP4UboNAJCWlQs3lbXfd1w0CnjdNaeLm1/h0UTVTWUUl6OSyzsS3l0OI3VRWkg GIbVxZ6u6Rm3TOO3qZk1u3nS0DUdEQy1PZMaw3HR6QINYqtnyl9LzU0nMqoylLZHTMKa TV0w== X-Gm-Message-State: AOJu0YzePOyQOlKyFf/yFY0TkrqQT9VZnZfOozBphRDcVKBPghACXrQY rpJGxXfrtrq9ROlVxJW6shw+ooczXPc= X-Google-Smtp-Source: AGHT+IGuPVsKUQkNfNUVvVuX031xgyrfyd9m42ATkCcm8chxY+we0bTYLPmPOfX4jDkw7mE/MQn8kA== X-Received: by 2002:a2e:9b09:0:b0:2b4:6e21:637e with SMTP id u9-20020a2e9b09000000b002b46e21637emr7257949lji.16.1691434302476; Mon, 07 Aug 2023 11:51:42 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id v8-20020adfe4c8000000b00317046f21f9sm11287015wrm.114.2023.08.07.11.51.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Aug 2023 11:51:42 -0700 (PDT) Message-ID: In-Reply-To: References: Date: Mon, 07 Aug 2023 18:51:35 +0000 Subject: [PATCH 1/6] maintenance: add get_random_minute() Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, sandals@crustytoothpaste.net, lenaic@lhuard.fr, Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee When we initially created background maintenance -- with its hourly, daily, and weekly schedules -- we considered the effects of all clients launching fetches to the server every hour on the hour. The worry of DDoSing server hosts was noted, but left as something we would consider for a future update. As background maintenance has gained more adoption over the past three years, our worries about DDoSing the big Git hosts has been unfounded. Those systems, especially those serving public repositories, are already resilient to thundering herds of much smaller scale. However, sometimes organizations spin up specific custom server infrastructure either in addition to or on top of their Git host. Some of these technologies are built for a different range of scale, and can hit concurrency limits sooner. Organizations with such custom infrastructures are more likely to recommend tools like `scalar` which furthers their adoption of background maintenance. To help solve for this, create get_random_minute() as a method to help Git select a random minute when creating schedules in the future. The integrations with this method do not yet exist, but will follow in future changes. One thing that is important for testability is that we notice when we are under a test scenario and return a predictable result. The schedules themselves are not checked for this value, but at least one launchctl test checks that we do not unnecessarily reboot the schedule if it has not changed from a previous version. Signed-off-by: Derrick Stolee Signed-off-by: Taylor Blau --- builtin/gc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/builtin/gc.c b/builtin/gc.c index f3942188a61..66a972bc292 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -1708,6 +1708,23 @@ static int get_schedule_cmd(const char **cmd, int *is_available) return 1; } +MAYBE_UNUSED +static int get_random_minute(void) +{ + static int random_initialized = 0; + + /* Use a static value when under tests. */ + if (!getenv("GIT_TEST_MAINTENANCE_SCHEDULER")) + return 13; + + if (!random_initialized) { + srand((unsigned int)getpid()); + random_initialized = 1; + } + + return rand() % 60; +} + static int is_launchctl_available(void) { const char *cmd = "launchctl"; From patchwork Mon Aug 7 18:51:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 13344738 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93681C04A6A for ; Mon, 7 Aug 2023 18:51:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229759AbjHGSvr (ORCPT ); Mon, 7 Aug 2023 14:51:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40140 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229847AbjHGSvq (ORCPT ); Mon, 7 Aug 2023 14:51:46 -0400 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B18C7171C for ; Mon, 7 Aug 2023 11:51:44 -0700 (PDT) Received: by mail-wr1-x42d.google.com with SMTP id ffacd0b85a97d-317e427488aso1397140f8f.1 for ; Mon, 07 Aug 2023 11:51:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691434303; x=1692039103; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=t+BtuboBjFPEmV67Rer1J24wk6zjGENS1FELhnkdM3w=; b=rekL1sBlxd2Hcyb5HRKsLWwYrM9bZ23G+YxWS+qBcoCmbbRNqDhfLUwUwmod0qTyIp nTwdS7xVHuKEAzz1qCTvvsKbjADKIa0g4qOB1vCOTUKmdPIGFratFrK6iBCsg4htqYkx sqZXOHHpKom8nujHnMLAN9JkVSWPYa2SziHuSt1pZ9Ijd9hVI6P0vb2wJ950djtYPLow ydu8wy6dMOom6ceLGX+GCx1eFO4hJe/m+82sP6PBzcvpQVQwowgEt/Nyc6fuatFrtVF9 g1yx/u6d6MIWrbKItbI/zoIy30HrXNbY3gGQvlY7sd0lfhrw0cQZgETjoaRWvTauez04 iZsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691434303; x=1692039103; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=t+BtuboBjFPEmV67Rer1J24wk6zjGENS1FELhnkdM3w=; b=KS8tarvErWskmRSRNrQoEy0OoFMNysuplxGEJmYsjA1+RbkcGOUy1QYs1Nujf3aVk0 KH7Eh/uEMez1SCHGIFfNGql8LW4fV5jmBp3KbMF+vj1fnG4c5FUV1j3o/roSAR8kUCnn O7z9Abzak2kF8xzIjhqbjgnfEuTY1OqUzEd5EKW39CFcFJaRp1cXGTuRpWYSldPiZDsS cRWn6BkWGG0b1dkyhwHjBW761doiUZtC9r0LjWFAXalcf/kVJbxVyLrkwvk7jsXyHS6w /HSCQOnRc6KZMA0Jfl3f15hmNRpUdXxHRpjE/P3EhN576Nh6nHruEbHwM7/vKng45Rhj DfXQ== X-Gm-Message-State: AOJu0YyAHHNJ52J7aifZs/PeuZX0qm/fejpzhD8gmZUxo4JcKjXuG3aJ V5CxRoF2b0i2qrsFmvha8OjMGRKAicM= X-Google-Smtp-Source: AGHT+IGZc/2ud9mx1lRfQHrFFhAXBtzbledBbXqASC4tse0Znv35yxV9VobL+Rq6B+3MDOJtjE3qQA== X-Received: by 2002:a5d:420e:0:b0:317:6f08:8371 with SMTP id n14-20020a5d420e000000b003176f088371mr7431941wrq.48.1691434303000; Mon, 07 Aug 2023 11:51:43 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id u3-20020adfed43000000b0031759e6b43fsm11297769wro.39.2023.08.07.11.51.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Aug 2023 11:51:42 -0700 (PDT) Message-ID: In-Reply-To: References: Date: Mon, 07 Aug 2023 18:51:36 +0000 Subject: [PATCH 2/6] maintenance: use random minute in launchctl scheduler Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, sandals@crustytoothpaste.net, lenaic@lhuard.fr, Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The get_random_minute() method was created to allow maintenance schedules to be fixed to a random minute of the hour. This randomness is only intended to spread out the load from a number of clients, but each client should have an hour between each maintenance cycle. Use get_random_minute() when constructing the schedules for launchctl. The format already includes a 'Minute' key which is modified from 0 to the random minute. Signed-off-by: Derrick Stolee --- builtin/gc.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/builtin/gc.c b/builtin/gc.c index 66a972bc292..51d6c7620ff 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -1708,7 +1708,6 @@ static int get_schedule_cmd(const char **cmd, int *is_available) return 1; } -MAYBE_UNUSED static int get_random_minute(void) { static int random_initialized = 0; @@ -1837,6 +1836,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit struct strbuf plist = STRBUF_INIT, plist2 = STRBUF_INIT; struct stat st; const char *cmd = "launchctl"; + int minute = get_random_minute(); get_schedule_cmd(&cmd, NULL); preamble = "\n" @@ -1862,29 +1862,30 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit case SCHEDULE_HOURLY: repeat = "\n" "Hour%d\n" - "Minute0\n" + "Minute%d\n" "\n"; for (i = 1; i <= 23; i++) - strbuf_addf(&plist, repeat, i); + strbuf_addf(&plist, repeat, i, minute); break; case SCHEDULE_DAILY: repeat = "\n" "Day%d\n" "Hour0\n" - "Minute0\n" + "Minute%d\n" "\n"; for (i = 1; i <= 6; i++) - strbuf_addf(&plist, repeat, i); + strbuf_addf(&plist, repeat, i, minute); break; case SCHEDULE_WEEKLY: - strbuf_addstr(&plist, - "\n" - "Day0\n" - "Hour0\n" - "Minute0\n" - "\n"); + strbuf_addf(&plist, + "\n" + "Day0\n" + "Hour0\n" + "Minute%d\n" + "\n", + minute); break; default: From patchwork Mon Aug 7 18:51:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 13344740 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6BA9C001DB for ; Mon, 7 Aug 2023 18:51:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230120AbjHGSvx (ORCPT ); Mon, 7 Aug 2023 14:51:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40156 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229942AbjHGSvr (ORCPT ); Mon, 7 Aug 2023 14:51:47 -0400 Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AC6A1722 for ; Mon, 7 Aug 2023 11:51:45 -0700 (PDT) Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-3fe24dd8898so41782685e9.2 for ; Mon, 07 Aug 2023 11:51:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691434303; x=1692039103; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=IwyFLOWeSTzKIMd3976gguwZWIzMKJF0Jjqe1sR02Ok=; b=LiiG9dSj5rjwLnO7HSzEaeCTekDMcwCCnn5fqgtJfjOZ1nbh9xbQlb2g3SlJj0/7uw /a5+P7PdzxR14Cml2Em7isnsANgy3KhArdzj7b4BvtdmKI0ft71LfQQtKYkGxr2ELaBC vRM56SGgnrx1PX4t3FzoeEqShOOOV0pgFDO/Ar1eoxWGYO4GwqySoh2GIXgLpe3ZXqkv 15FOUkxjqO1r3307X5zhBk0q6LvNkEV2tNOBUqPDSxlYOQCd+5ZmD8/4ecdGSJq4FWqa V0Mmai/zerTxJn2AlDvOWhmcUu7LBuy03Hpxa+8YL6K0u+q37SENtje7Y9UjvAC+CxLP Z/Hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691434303; x=1692039103; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IwyFLOWeSTzKIMd3976gguwZWIzMKJF0Jjqe1sR02Ok=; b=KCLx/ODMmdEKlBLuUSaOXpyP1skvSr3Ttffh87/tjPe58N/x6qrrP+NBPE3E3hxjIS 3oRZF7P7zhWt+YLv1rbif4n5KkTss+zcSLTKtXbseo5vCLUqHNdyyS9akQ4S3x3ZU/uR lw38Le6q9ldKCNt62TPYK1CoCNIC5MJ1F0v1S9oJpQ929MQ1pAGlNKHeIQQ0X14QjBt6 NkXj4bwycefWmns+OqMZmzPtqpMVlM+YYieuBj0oQr8i42eQc64IqnLe4by/GIdxrk2v DRgiFCn9PYguVBm73k3uKv6CDg9ytbi1mdGMT/+gEG1JO9gj+nqWG6TYTSvDeknGQHpa CNtw== X-Gm-Message-State: AOJu0YzOAM8nC4b6cw1L+q5I9jG8wGcKiR6BMy/sNfAk/KAMWPRva0yN ncOG/cD/EQIQVtWqnHqZVauzLtTWyqM= X-Google-Smtp-Source: AGHT+IE3IQI1CyvT+pcbr2WNtO6u7BIT86M5zNE0jGX7A/FXM+wSGm3ijou7ZLfMYDtvGsWtJ47yGw== X-Received: by 2002:adf:e5d0:0:b0:314:10d8:b482 with SMTP id a16-20020adfe5d0000000b0031410d8b482mr5707015wrn.65.1691434303682; Mon, 07 Aug 2023 11:51:43 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id z9-20020a5d4c89000000b00317f3fd21b7sm1118651wrs.80.2023.08.07.11.51.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Aug 2023 11:51:43 -0700 (PDT) Message-ID: <1048dff1d3a241effe7235716b1f5d9c46f7478b.1691434300.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Mon, 07 Aug 2023 18:51:37 +0000 Subject: [PATCH 3/6] maintenance: use random minute in Windows scheduler Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, sandals@crustytoothpaste.net, lenaic@lhuard.fr, Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The get_random_minute() method was created to allow maintenance schedules to be fixed to a random minute of the hour. This randomness is only intended to spread out the load from a number of clients, but each client should have an hour between each maintenance cycle. Add this random minute to the Windows scheduler integration. We need only to modify the minute value for the 'StartBoundary' tag across the three schedules. Signed-off-by: Derrick Stolee --- builtin/gc.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/builtin/gc.c b/builtin/gc.c index 51d6c7620ff..f059c9f89d5 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -2002,6 +2002,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority const char *frequency = get_frequency(schedule); char *name = schtasks_task_name(frequency); struct strbuf tfilename = STRBUF_INIT; + int minute = get_random_minute(); get_schedule_cmd(&cmd, NULL); @@ -2022,7 +2023,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority switch (schedule) { case SCHEDULE_HOURLY: fprintf(tfile->fp, - "2020-01-01T01:00:00\n" + "2020-01-01T01:%02d:00\n" "true\n" "\n" "1\n" @@ -2031,12 +2032,13 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority "PT1H\n" "PT23H\n" "false\n" - "\n"); + "\n", + minute); break; case SCHEDULE_DAILY: fprintf(tfile->fp, - "2020-01-01T00:00:00\n" + "2020-01-01T00:%02d:00\n" "true\n" "\n" "\n" @@ -2048,19 +2050,21 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority "\n" "\n" "1\n" - "\n"); + "\n", + minute); break; case SCHEDULE_WEEKLY: fprintf(tfile->fp, - "2020-01-01T00:00:00\n" + "2020-01-01T00:%02d:00\n" "true\n" "\n" "\n" "\n" "\n" "1\n" - "\n"); + "\n", + minute); break; default: From patchwork Mon Aug 7 18:51:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 13344741 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0D673C04A6A for ; Mon, 7 Aug 2023 18:51:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230128AbjHGSvy (ORCPT ); Mon, 7 Aug 2023 14:51:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40158 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229847AbjHGSvr (ORCPT ); Mon, 7 Aug 2023 14:51:47 -0400 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1DCE5E68 for ; Mon, 7 Aug 2023 11:51:46 -0700 (PDT) Received: by mail-wr1-x42a.google.com with SMTP id ffacd0b85a97d-317716a4622so3835314f8f.1 for ; Mon, 07 Aug 2023 11:51:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691434304; x=1692039104; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=re/fkMTHo/0BCJ7Q11r5cRvbEJ98ymR9C0zXJbJryKM=; b=BPHN/aj5pq7DhJ9oLGktesnP0ZQ5iXFvvhIjsQRN2X+XaF7sDrnyOdAv+peYqvO0bh yJnuhMFu2kpU9mg4mNbdyMytOhExOXy6GZm39dWWQqp4cOT2ir002z8TohGn5w0ulAcn dMQJwnQwVeymas77aa+679dWFe7YpYIZ8U+fdsVgnVMIzIl8KQ+Q/aBSfhMdkEPX4BLu b82Gn5Ezp28hQs5Pfc6I7D5aesuoYWoaTavow8xQOfkhKjLc5lbIr8PBlWVza8F58JNV D+49d4rInXBbxY2EvOmiHQqK9qFQYtTjIjMh13C/Vuh3zndlaEJkWZwdL7sdnC5Nv5fr fReQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691434304; x=1692039104; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=re/fkMTHo/0BCJ7Q11r5cRvbEJ98ymR9C0zXJbJryKM=; b=imqkC4UUGIj/VIsy1AIhAHhe9wv0ea0CsXdYoWXj+7gZ+dkMzGyLFlqJLtly3FtF37 ExnIll6uBn/W5TFA0zQIZ/TiZd9u+iOyhNgL4uBAscjbxRVb6LkNo0sHs5hvcWBR3zvx xMJlEbPBdyBME+BfjzYiRkflpe2jTPU4uqJLRYb+3hX8fTMlmSp4JQYOsftd3Ctq3sgf gWA4GsfSjzRPLLBJ1rjR2qSM7DqApbXH0r0RAqflxG5uJwvodPhi0wFaGdNiFe4LoFvg s2sosUeWAjDeQ+ki6Q5HCEQ7CS3vmQMwx33+J34lR386+mFacmQprd0VmiQ/z+L3+B1G dBDg== X-Gm-Message-State: AOJu0YwbwhriffUps/bNXpocgktVswXNCYdA1x3R/ZBbANqP3Y1B0wl0 eSpq3Wn3zZ3XDw4pSqNHfk6kdprS7Yg= X-Google-Smtp-Source: AGHT+IHo/J/ZXmra6ytPk6C/TBIS8l3s5w/3iBvGfxahqKkxN+H5uKHCOz7A4VQOcwnjHgNkTPXccQ== X-Received: by 2002:a5d:4605:0:b0:317:60a8:f3a7 with SMTP id t5-20020a5d4605000000b0031760a8f3a7mr5973480wrq.10.1691434304377; Mon, 07 Aug 2023 11:51:44 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id i1-20020adfe481000000b00317e77106dbsm4592401wrm.48.2023.08.07.11.51.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Aug 2023 11:51:43 -0700 (PDT) Message-ID: <3ef3cf0861ffcb86dc8dbb075a17265d4c23d3fc.1691434300.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Mon, 07 Aug 2023 18:51:38 +0000 Subject: [PATCH 4/6] maintenance: use random minute in cron scheduler Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, sandals@crustytoothpaste.net, lenaic@lhuard.fr, Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The get_random_minute() method was created to allow maintenance schedules to be fixed to a random minute of the hour. This randomness is only intended to spread out the load from a number of clients, but each client should have an hour between each maintenance cycle. Add this random minute to the cron integration. The cron schedule specification starts with a minute indicator, which was previously inserted as the "0" string but now takes the given minute as an integer parameter. Signed-off-by: Derrick Stolee --- builtin/gc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/builtin/gc.c b/builtin/gc.c index f059c9f89d5..be47000ed36 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -2181,6 +2181,7 @@ static int crontab_update_schedule(int run_maintenance, int fd) FILE *cron_list, *cron_in; struct strbuf line = STRBUF_INIT; struct tempfile *tmpedit = NULL; + int minute = get_random_minute(); get_schedule_cmd(&cmd, NULL); strvec_split(&crontab_list.args, cmd); @@ -2235,11 +2236,11 @@ static int crontab_update_schedule(int run_maintenance, int fd) "# replaced in the future by a Git command.\n\n"); strbuf_addf(&line_format, - "%%s %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%%s\n", + "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%%s\n", exec_path, exec_path); - fprintf(cron_in, line_format.buf, "0", "1-23", "*", "hourly"); - fprintf(cron_in, line_format.buf, "0", "0", "1-6", "daily"); - fprintf(cron_in, line_format.buf, "0", "0", "0", "weekly"); + fprintf(cron_in, line_format.buf, minute, "1-23", "*", "hourly"); + fprintf(cron_in, line_format.buf, minute, "0", "1-6", "daily"); + fprintf(cron_in, line_format.buf, minute, "0", "0", "weekly"); strbuf_release(&line_format); fprintf(cron_in, "\n%s\n", END_LINE); From patchwork Mon Aug 7 18:51:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 13344742 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23DDFC001DB for ; Mon, 7 Aug 2023 18:52:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230351AbjHGSv7 (ORCPT ); Mon, 7 Aug 2023 14:51:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229989AbjHGSvs (ORCPT ); Mon, 7 Aug 2023 14:51:48 -0400 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D746F171C for ; Mon, 7 Aug 2023 11:51:46 -0700 (PDT) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-3fe4b95c371so18599605e9.1 for ; Mon, 07 Aug 2023 11:51:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691434305; x=1692039105; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=Una1H32ohwMz7Z87OhdeB+5FsTi1i+P9igdRRxpApuw=; b=Lmf1RvlW4uIJcyeYmBnCbnkyHR+MdP4CW+4l2wLUbV+sZlLOsR/C8wkHQGG2K9RrN1 LXt+keECmCUpjlY1fzyWrpH8KS6ONvgYrvayfYISGLvlNtjIZFHVEl3AGKxEFg1ih1u3 tUpzd8GVe9xdiQOo8oPIvsHpjqUm2PVkrsxXdV5UhjiCMjqnIbJD7n+Jk7je64/Dysiu qQuWHfhIh8BuRsG0rsuCurUexrz+xfGI+GF5+fv+7VBroeEPzWMOdQnQaEBzr9H/gYFj bLRvMJX9Ajcytm1BZMWgb0M2ihkDhgQBXp8zeFettpcmyj2Wx5XylkimWgIbg2gbNh9b DOWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691434305; x=1692039105; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Una1H32ohwMz7Z87OhdeB+5FsTi1i+P9igdRRxpApuw=; b=gARzIp2mvK9HMf6W/sqr0O86DYoANv97RejneZy1EcCe6O00xep9sHU95iKkL3xFdn qtf60OAe2xbuaSv4nSeAV9iRTI0lLxlNEizxtFmnpT6JxbqHeBg0IvBW+MjAT+FD2dsW kV2hZygG3c4hhG2pWJxwqp9kdwvucvWhaSrTno7e7ukD3AnkjI445tmfBwgWOYBv2ZdM nBaYQ+ofMFNhN8/kNpv+lVxP48Yi+gNyUFYsYqaQhwH3zqEyi1M4VZfj2v+kE/vbDRUH wVLXzZlnwPoafuCEJroimvOR56m+8+wVnHtvQK/WM/BxXSFksix1ewAkyYXZm9ZH/1pN iFLg== X-Gm-Message-State: AOJu0YxblAzYUBOO/WgJPAiJevoF2bctOdzNiN9Z7b34rSyq8gnwlvc7 +wOVaxU8yiXvnMOgIiadZjpHH6C7HIQ= X-Google-Smtp-Source: AGHT+IGQKif1oOCj6l+ocyok4+g9vYQ6/w0aKROhHVzpRZGQX+R6wn2bUbk2erqDnQe3ah7+RqShTw== X-Received: by 2002:a7b:c8c4:0:b0:3fe:1c57:3be with SMTP id f4-20020a7bc8c4000000b003fe1c5703bemr6414722wml.8.1691434305091; Mon, 07 Aug 2023 11:51:45 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b7-20020a5d40c7000000b0031423a8f4f7sm11361229wrq.56.2023.08.07.11.51.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Aug 2023 11:51:44 -0700 (PDT) Message-ID: <37f96b6b619d2d3eecd9c2b35483b2d61083603b.1691434300.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Mon, 07 Aug 2023 18:51:39 +0000 Subject: [PATCH 5/6] maintenance: swap method locations Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, sandals@crustytoothpaste.net, lenaic@lhuard.fr, Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The systemd_timer_write_unit_templates() method writes a single template that is then used to start the hourly, daily, and weekly schedules with systemd. However, in order to schedule systemd maintenance on a given minute, these templates need to be replaced with specific schedules for each of these jobs. Before modifying the schedules, move the writing method above the systemd_timer_enable_unit() method, so we can write a specific schedule for each unit. The diff is computed smaller by showing systemd_timer_enable_unit() move instead of systemd_timer_write_unit_templates(). Signed-off-by: Derrick Stolee --- builtin/gc.c | 128 +++++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/builtin/gc.c b/builtin/gc.c index be47000ed36..b3ef95b10aa 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -2299,70 +2299,6 @@ static char *xdg_config_home_systemd(const char *filename) return xdg_config_home_for("systemd/user", filename); } -static int systemd_timer_enable_unit(int enable, - enum schedule_priority schedule) -{ - const char *cmd = "systemctl"; - struct child_process child = CHILD_PROCESS_INIT; - const char *frequency = get_frequency(schedule); - - /* - * Disabling the systemd unit while it is already disabled makes - * systemctl print an error. - * Let's ignore it since it means we already are in the expected state: - * the unit is disabled. - * - * On the other hand, enabling a systemd unit which is already enabled - * produces no error. - */ - if (!enable) - child.no_stderr = 1; - - get_schedule_cmd(&cmd, NULL); - strvec_split(&child.args, cmd); - strvec_pushl(&child.args, "--user", enable ? "enable" : "disable", - "--now", NULL); - strvec_pushf(&child.args, "git-maintenance@%s.timer", frequency); - - if (start_command(&child)) - return error(_("failed to start systemctl")); - if (finish_command(&child)) - /* - * Disabling an already disabled systemd unit makes - * systemctl fail. - * Let's ignore this failure. - * - * Enabling an enabled systemd unit doesn't fail. - */ - if (enable) - return error(_("failed to run systemctl")); - return 0; -} - -static int systemd_timer_delete_unit_templates(void) -{ - int ret = 0; - char *filename = xdg_config_home_systemd("git-maintenance@.timer"); - if (unlink(filename) && !is_missing_file_error(errno)) - ret = error_errno(_("failed to delete '%s'"), filename); - FREE_AND_NULL(filename); - - filename = xdg_config_home_systemd("git-maintenance@.service"); - if (unlink(filename) && !is_missing_file_error(errno)) - ret = error_errno(_("failed to delete '%s'"), filename); - - free(filename); - return ret; -} - -static int systemd_timer_delete_units(void) -{ - return systemd_timer_enable_unit(0, SCHEDULE_HOURLY) || - systemd_timer_enable_unit(0, SCHEDULE_DAILY) || - systemd_timer_enable_unit(0, SCHEDULE_WEEKLY) || - systemd_timer_delete_unit_templates(); -} - static int systemd_timer_write_unit_templates(const char *exec_path) { char *filename; @@ -2444,6 +2380,70 @@ error: return -1; } +static int systemd_timer_enable_unit(int enable, + enum schedule_priority schedule) +{ + const char *cmd = "systemctl"; + struct child_process child = CHILD_PROCESS_INIT; + const char *frequency = get_frequency(schedule); + + /* + * Disabling the systemd unit while it is already disabled makes + * systemctl print an error. + * Let's ignore it since it means we already are in the expected state: + * the unit is disabled. + * + * On the other hand, enabling a systemd unit which is already enabled + * produces no error. + */ + if (!enable) + child.no_stderr = 1; + + get_schedule_cmd(&cmd, NULL); + strvec_split(&child.args, cmd); + strvec_pushl(&child.args, "--user", enable ? "enable" : "disable", + "--now", NULL); + strvec_pushf(&child.args, "git-maintenance@%s.timer", frequency); + + if (start_command(&child)) + return error(_("failed to start systemctl")); + if (finish_command(&child)) + /* + * Disabling an already disabled systemd unit makes + * systemctl fail. + * Let's ignore this failure. + * + * Enabling an enabled systemd unit doesn't fail. + */ + if (enable) + return error(_("failed to run systemctl")); + return 0; +} + +static int systemd_timer_delete_unit_templates(void) +{ + int ret = 0; + char *filename = xdg_config_home_systemd("git-maintenance@.timer"); + if (unlink(filename) && !is_missing_file_error(errno)) + ret = error_errno(_("failed to delete '%s'"), filename); + FREE_AND_NULL(filename); + + filename = xdg_config_home_systemd("git-maintenance@.service"); + if (unlink(filename) && !is_missing_file_error(errno)) + ret = error_errno(_("failed to delete '%s'"), filename); + + free(filename); + return ret; +} + +static int systemd_timer_delete_units(void) +{ + return systemd_timer_enable_unit(0, SCHEDULE_HOURLY) || + systemd_timer_enable_unit(0, SCHEDULE_DAILY) || + systemd_timer_enable_unit(0, SCHEDULE_WEEKLY) || + systemd_timer_delete_unit_templates(); +} + static int systemd_timer_setup_units(void) { const char *exec_path = git_exec_path(); From patchwork Mon Aug 7 18:51:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Derrick Stolee X-Patchwork-Id: 13344743 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BBB1EC04A6A for ; Mon, 7 Aug 2023 18:52:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230153AbjHGSwB (ORCPT ); Mon, 7 Aug 2023 14:52:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40234 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230021AbjHGSvw (ORCPT ); Mon, 7 Aug 2023 14:51:52 -0400 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E6CD1172B for ; Mon, 7 Aug 2023 11:51:47 -0700 (PDT) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-3fe1d9a8ec6so34440095e9.1 for ; Mon, 07 Aug 2023 11:51:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1691434306; x=1692039106; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc:subject:date :message-id:reply-to; bh=xQwFDcO2xXtiSTm+D4GflRxpp/4sU5imxOBud5LQH9Y=; b=b4nnqtcQYM+P8rNcAGL23DIwZQmaAF797VARtRsWkApiXkoU6XtFXXjBiE+Ax10thQ ntBiVeX+fPgZK32ckmdUOXuKsL6T8nr9yV4jwaXEoUQhWpjLI3mMpwztni8jyxOSqJz2 7fGsqZ/k/LcKhadiDa08czvu71BFsXbBwZb9uJGpv/kpvV788WtgDwjJJxEUl9yDVwBE BjeyD+e4bj+kuYC6nhnxI7k/q2VrbHMSBqavuv4co1Hjms1V+16iTqk4A9bUPiR8Uoci DOOAE3nKz0U4LaJ98O1Npo+S7roASV4+KGuNUAYvhj+UbvJCirw7kh6GanPU+BluBy9C b5/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691434306; x=1692039106; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xQwFDcO2xXtiSTm+D4GflRxpp/4sU5imxOBud5LQH9Y=; b=TLXqPzAkPFhxULqSzYEYxNdYSuWoRQ59D3Jua3V3SI4q2JXGL7HBz6JULWil3u89sz h75J3XWOHX2JIFykmwV53sDCJGHawcuUUxTQ5zq3RB2SRDjpd9xzKItOQOZWLAJL+nWZ IeFsFFaW9V+0ZQZ+F4VAabvtL41Y+IOkP5i0NLqQcwlM0o0nA6vMw6QCe6P/e1Fo3X5+ jCHf2KANqsqQMg+BOqvB7zH8TWnwOY+2pJQh5h0jRRfbtK1j/ft9qdI05cf2Xbv4FSPt 8lvCtnQCykqG0ozNn6rCGtPddEkylvSobNbkMLVBQB7ACfb4i6jVAD8u+zox3eXMyp39 ONQQ== X-Gm-Message-State: AOJu0YwLJ7ldpvpAPuQe4Cp986oyqn9yVI9CTDa1sSNGc0N7boAllKkI JTXd8Yg5hWOb6Vdcik0+VnwHZKicwz4= X-Google-Smtp-Source: AGHT+IHTA2gM3Wka6vMdyTNI9AQQo6WDOfnJJw477bp/DJ424jkqvjlrLFBZTTC2JS+LxnYtpXsZTA== X-Received: by 2002:a05:600c:3799:b0:3fe:20f1:fb2 with SMTP id o25-20020a05600c379900b003fe20f10fb2mr6296145wmr.6.1691434305820; Mon, 07 Aug 2023 11:51:45 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id n8-20020a1c7208000000b003fe11148055sm11422648wmc.27.2023.08.07.11.51.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Aug 2023 11:51:45 -0700 (PDT) Message-ID: <14e340b75faaa66980479f42fec14c457aea5c74.1691434300.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Mon, 07 Aug 2023 18:51:40 +0000 Subject: [PATCH 6/6] maintenance: use random minute in systemd scheduler Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: gitster@pobox.com, sandals@crustytoothpaste.net, lenaic@lhuard.fr, Derrick Stolee , Derrick Stolee Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Derrick Stolee From: Derrick Stolee The get_random_minute() method was created to allow maintenance schedules to be fixed to a random minute of the hour. This randomness is only intended to spread out the load from a number of clients, but each client should have an hour between each maintenance cycle. Add this random minute to the systemd integration. This integration is more complicated than similar changes for other schedulers because of a neat trick that systemd allows: templating. The previous implementation generated two template files with names of the form 'git-maintenance@.(timer|service)'. The '.timer' or '.service' indicates that this is a template that is picked up when we later specify '...@.timer' or '...@.service'. The '' string is then used to insert into the template both the 'OnCalendar' schedule setting and the '--schedule' parameter of the 'git maintenance run' command. In order to set these schedules to a given minute, we can no longer use the 'hourly', 'daily', or 'weekly' strings for '' and instead need to abandon the template model. Modify the template with a custom schedule in the 'OnCalendar' setting. This schedule has some interesting differences from cron-like patterns, but is relatively easy to figure out from context. The one that might be confusing is that '*-*-*' is a date-based pattern, but this must be omitted when using 'Mon' to signal that we care about the day of the week. Monday is used since that matches the day used for the 'weekly' schedule used previously. The rest of the change involves making sure we are writing these .timer and .service files before initializing the schedule with 'systemctl' and deleting the files when we are done. Some changes are also made to share the random minute along with a single computation of the execution path of the current Git executable. Signed-off-by: Derrick Stolee --- builtin/gc.c | 82 ++++++++++++++++++++++++++++++++---------- t/t7900-maintenance.sh | 4 ++- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/builtin/gc.c b/builtin/gc.c index b3ef95b10aa..5f5bb95641f 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -2299,13 +2299,20 @@ static char *xdg_config_home_systemd(const char *filename) return xdg_config_home_for("systemd/user", filename); } -static int systemd_timer_write_unit_templates(const char *exec_path) +static int systemd_timer_write_unit_template(enum schedule_priority schedule, + const char *exec_path, + int minute) { char *filename; FILE *file; const char *unit; + char *schedule_pattern = NULL; + const char *frequency = get_frequency(schedule); + char *local_timer_name = xstrfmt("git-maintenance@%s.timer", frequency); + char *local_service_name = xstrfmt("git-maintenance@%s.service", frequency); + + filename = xdg_config_home_systemd(local_timer_name); - filename = xdg_config_home_systemd("git-maintenance@.timer"); if (safe_create_leading_directories(filename)) { error(_("failed to create directories for '%s'"), filename); goto error; @@ -2314,6 +2321,23 @@ static int systemd_timer_write_unit_templates(const char *exec_path) if (!file) goto error; + switch (schedule) { + case SCHEDULE_HOURLY: + schedule_pattern = xstrfmt("*-*-* *:%02d:00", minute); + break; + + case SCHEDULE_DAILY: + schedule_pattern = xstrfmt("*-*-* 0:%02d:00", minute); + break; + + case SCHEDULE_WEEKLY: + schedule_pattern = xstrfmt("Mon 0:%02d:00", minute); + break; + + default: + BUG("Unhandled schedule_priority"); + } + unit = "# This file was created and is maintained by Git.\n" "# Any edits made in this file might be replaced in the future\n" "# by a Git command.\n" @@ -2322,12 +2346,12 @@ static int systemd_timer_write_unit_templates(const char *exec_path) "Description=Optimize Git repositories data\n" "\n" "[Timer]\n" - "OnCalendar=%i\n" + "OnCalendar=%s\n" "Persistent=true\n" "\n" "[Install]\n" "WantedBy=timers.target\n"; - if (fputs(unit, file) == EOF) { + if (fprintf(file, unit, schedule_pattern) < 0) { error(_("failed to write to '%s'"), filename); fclose(file); goto error; @@ -2338,7 +2362,7 @@ static int systemd_timer_write_unit_templates(const char *exec_path) } free(filename); - filename = xdg_config_home_systemd("git-maintenance@.service"); + filename = xdg_config_home_systemd(local_service_name); file = fopen_or_warn(filename, "w"); if (!file) goto error; @@ -2352,7 +2376,7 @@ static int systemd_timer_write_unit_templates(const char *exec_path) "\n" "[Service]\n" "Type=oneshot\n" - "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%%i\n" + "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s\n" "LockPersonality=yes\n" "MemoryDenyWriteExecute=yes\n" "NoNewPrivileges=yes\n" @@ -2362,7 +2386,7 @@ static int systemd_timer_write_unit_templates(const char *exec_path) "RestrictSUIDSGID=yes\n" "SystemCallArchitectures=native\n" "SystemCallFilter=@system-service\n"; - if (fprintf(file, unit, exec_path, exec_path) < 0) { + if (fprintf(file, unit, exec_path, exec_path, frequency) < 0) { error(_("failed to write to '%s'"), filename); fclose(file); goto error; @@ -2375,13 +2399,16 @@ static int systemd_timer_write_unit_templates(const char *exec_path) return 0; error: + free(schedule_pattern); + free(local_timer_name); free(filename); - systemd_timer_delete_unit_templates(); return -1; } static int systemd_timer_enable_unit(int enable, - enum schedule_priority schedule) + enum schedule_priority schedule, + const char *exec_path, + int minute) { const char *cmd = "systemctl"; struct child_process child = CHILD_PROCESS_INIT; @@ -2398,6 +2425,8 @@ static int systemd_timer_enable_unit(int enable, */ if (!enable) child.no_stderr = 1; + else if (systemd_timer_write_unit_template(schedule, exec_path, minute)) + return -1; get_schedule_cmd(&cmd, NULL); strvec_split(&child.args, cmd); @@ -2420,38 +2449,53 @@ static int systemd_timer_enable_unit(int enable, return 0; } -static int systemd_timer_delete_unit_templates(void) +static int systemd_timer_delete_unit_template(enum schedule_priority priority) { + const char *frequency = get_frequency(priority); + char *local_timer_name = xstrfmt("git-maintenance@%s.timer", frequency); + char *local_service_name = xstrfmt("git-maintenance@%s.service", frequency); int ret = 0; - char *filename = xdg_config_home_systemd("git-maintenance@.timer"); + char *filename = xdg_config_home_systemd(local_timer_name); if (unlink(filename) && !is_missing_file_error(errno)) ret = error_errno(_("failed to delete '%s'"), filename); FREE_AND_NULL(filename); - filename = xdg_config_home_systemd("git-maintenance@.service"); + filename = xdg_config_home_systemd(local_service_name); if (unlink(filename) && !is_missing_file_error(errno)) ret = error_errno(_("failed to delete '%s'"), filename); free(filename); + free(local_timer_name); + free(local_service_name); return ret; } +static int systemd_timer_delete_unit_templates(void) +{ + /* Purposefully not short-circuited to make sure all are called. */ + return systemd_timer_delete_unit_template(SCHEDULE_HOURLY) | + systemd_timer_delete_unit_template(SCHEDULE_DAILY) | + systemd_timer_delete_unit_template(SCHEDULE_WEEKLY); +} + static int systemd_timer_delete_units(void) { - return systemd_timer_enable_unit(0, SCHEDULE_HOURLY) || - systemd_timer_enable_unit(0, SCHEDULE_DAILY) || - systemd_timer_enable_unit(0, SCHEDULE_WEEKLY) || + int minute = get_random_minute(); + const char *exec_path = git_exec_path(); + return systemd_timer_enable_unit(0, SCHEDULE_HOURLY, exec_path, minute) || + systemd_timer_enable_unit(0, SCHEDULE_DAILY, exec_path, minute) || + systemd_timer_enable_unit(0, SCHEDULE_WEEKLY, exec_path, minute) || systemd_timer_delete_unit_templates(); } static int systemd_timer_setup_units(void) { + int minute = get_random_minute(); const char *exec_path = git_exec_path(); - int ret = systemd_timer_write_unit_templates(exec_path) || - systemd_timer_enable_unit(1, SCHEDULE_HOURLY) || - systemd_timer_enable_unit(1, SCHEDULE_DAILY) || - systemd_timer_enable_unit(1, SCHEDULE_WEEKLY); + int ret = systemd_timer_enable_unit(1, SCHEDULE_HOURLY, exec_path, minute) || + systemd_timer_enable_unit(1, SCHEDULE_DAILY, exec_path, minute) || + systemd_timer_enable_unit(1, SCHEDULE_WEEKLY, exec_path, minute); if (ret) systemd_timer_delete_units(); return ret; diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index 487e326b3fa..f5a93f5aecf 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -744,7 +744,9 @@ test_expect_success 'start and stop Linux/systemd maintenance' ' # start registers the repo git config --get --global --fixed-value maintenance.repo "$(pwd)" && - test_systemd_analyze_verify "systemd/user/git-maintenance@.service" && + test_systemd_analyze_verify "systemd/user/git-maintenance@hourly.service" && + test_systemd_analyze_verify "systemd/user/git-maintenance@daily.service" && + test_systemd_analyze_verify "systemd/user/git-maintenance@weekly.service" && printf -- "--user enable --now git-maintenance@%s.timer\n" hourly daily weekly >expect && test_cmp expect args &&