Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

system: Keep DBus connection to tuned open over service state changes #21115

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 54 additions & 50 deletions pkg/systemd/overview-cards/tuned-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import cockpit from "cockpit";
import React, { useState, useEffect, useCallback } from 'react';
import React, { useState, useEffect, useRef } from 'react';

import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
import { Modal } from "@patternfly/react-core/dist/esm/components/Modal/index.js";
Expand All @@ -31,7 +31,7 @@ import { EmptyStatePanel } from 'cockpit-components-empty-state.jsx';
import { ModalError } from 'cockpit-components-inline-notification.jsx';
import { ProfilesMenuDialogBody } from './profiles-menu-dialog-body.jsx';
import { superuser } from 'superuser';
import { useObject, useEvent } from "hooks";
import { useObject, useEvent, useInit } from "hooks";
import { useDialogs } from "dialogs.jsx";

const _ = cockpit.gettext;
Expand All @@ -41,15 +41,29 @@ export const TunedPerformanceProfile = () => {
const [btnText, setBtnText] = useState();
const [state, setState] = useState();
const [status, setStatus] = useState();
const oldServiceState = useRef(null);

const tunedService = useInit(() => service.proxy("tuned.service"));
const tunedDbus = useObject(
() => {
const tuned = cockpit.dbus("com.redhat.tuned", { superuser: "try" });
update(tuned);
return tuned;
},
obj => obj.close(),
[superuser.allowed]);

useEvent(superuser, "reconnect");
useEvent(tunedService, "changed", () => {
// We get a flood of "changed" events sometimes without the
// state actually changing. So let's protect against that.
if (oldServiceState.current != tunedService.state) {
oldServiceState.current = tunedService.state;
update(tunedDbus);
}
});

const tunedService = useObject(() => service.proxy("tuned.service"),
null,
[]);
const tuned = useObject(() => cockpit.dbus("com.redhat.tuned", { superuser: "try" }),
obj => obj.close(),
[superuser.allowed, tunedService.state]);

const poll = useCallback(() => {
function poll(tuned) {
return Promise.all([
tuned.call('/Tuned', 'com.redhat.tuned.control', 'is_running', []),
tuned.call('/Tuned', 'com.redhat.tuned.control', 'active_profile', []),
Expand All @@ -67,48 +81,38 @@ export const TunedPerformanceProfile = () => {
else
return Promise.reject(ex);
});
}, [tunedService, tuned]);

const updateButton = useCallback(() => {
return poll()
.then(res => {
const { state, active, recommended } = res;
let status;

if (state == "not-installed")
status = _("Tuned is not available");
else if (state == "not-running")
status = _("Tuned is not running");
else if (active == "none")
status = _("Tuned is off");
else if (active == recommended)
status = _("This system is using the recommended profile");
else
status = _("This system is using a custom profile");

setBtnText(state == "running" ? active : _("none"));
setState(state);
setStatus(status);
})
.catch((ex) => {
console.warn("failed to poll tuned", ex);

setBtnText("error");
setStatus(_("Communication with tuned has failed"));
});
}, [poll, setBtnText, setState, setStatus]);

useEvent(superuser, "changed");
useEvent(tunedService, "changed", () => updateButton());

useEffect(() => {
updateButton();
}, [updateButton]);
}

async function update(tuned) {
try {
const { state, active, recommended } = await poll(tuned);
let status;

if (state == "not-installed")
status = _("Tuned is not available");
else if (state == "not-running")
status = _("Tuned is not running");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

else if (active == "none")
status = _("Tuned is off");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

else if (active == recommended)
status = _("This system is using the recommended profile");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

else
status = _("This system is using a custom profile");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

setBtnText(state == "running" ? active : _("none"));
setState(state);
setStatus(status);
} catch (ex) {
console.warn("failed to poll tuned", ex);

setBtnText("error");
setStatus(_("Communication with tuned has failed"));
}
}

const showDialog = () => {
Dialogs.show(<TunedDialog updateButton={updateButton}
poll={poll}
tunedDbus={tuned} tunedService={tunedService} />);
Dialogs.show(<TunedDialog updateButton={() => update(tunedDbus)}
poll={() => poll(tunedDbus)}
tunedDbus={tunedDbus} tunedService={tunedService} />);
Comment on lines +113 to +115
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 3 added lines are not executed by any test.

};

return (
Expand Down