@@ -140,12 +140,35 @@ RecordHost::PerfCapabilities fetchLocalPerfCapabilities(const QString& perfPath)
140
140
141
141
return capabilities;
142
142
}
143
+
144
+ RecordHost::PerfCapabilities fetchRemotePerfCapabilities (const RemoteDevice& device)
145
+ {
146
+ RecordHost::PerfCapabilities capabilities;
147
+
148
+ const auto buildOptions =
149
+ device.getProgramOutput ({QStringLiteral (" perf" ), QStringLiteral (" version" ), QStringLiteral (" --build-options" )});
150
+ const auto help = device.getProgramOutput ({QStringLiteral (" perf" ), QStringLiteral (" --help" )});
151
+
152
+ capabilities.canCompress = Zstd_FOUND && buildOptions.contains (" zszd: [ on ]" );
153
+ capabilities.canSwitchEvents = help.contains (" --switch-events" );
154
+ capabilities.canSampleCpu = help.contains (" --sample-cpu" );
155
+
156
+ // TODO: implement
157
+ capabilities.canProfileOffCpu = false ;
158
+ capabilities.privilegesAlreadyElevated = false ;
159
+
160
+ capabilities.canUseAio = false ; // AIO doesn't work with perf streaming
161
+ capabilities.canElevatePrivileges = false ; // we currently don't support this
162
+
163
+ return capabilities;
164
+ }
143
165
}
144
166
145
167
RecordHost::RecordHost (QObject* parent)
146
168
: QObject(parent)
147
169
, m_checkPerfCapabilitiesJob(this )
148
170
, m_checkPerfInstalledJob(this )
171
+ , m_remoteDevice(this )
149
172
{
150
173
connect (this , &RecordHost::errorOccurred, this , [this ](const QString& message) { m_error = message; });
151
174
@@ -160,6 +183,10 @@ RecordHost::RecordHost(QObject* parent)
160
183
connectIsReady (&RecordHost::pidsChanged);
161
184
connectIsReady (&RecordHost::currentWorkingDirectoryChanged);
162
185
186
+ connect (&m_remoteDevice, &RemoteDevice::connected, this , &RecordHost::checkRequirements);
187
+
188
+ connect (&m_remoteDevice, &RemoteDevice::connected, this , [this ] { emit isReadyChanged (isReady ()); });
189
+
163
190
setHost (QStringLiteral (" localhost" ));
164
191
}
165
192
@@ -169,7 +196,13 @@ bool RecordHost::isReady() const
169
196
{
170
197
switch (m_recordType) {
171
198
case RecordType::LaunchApplication:
172
- // client application is already validated in the setter
199
+ // client application is already validated in the setter
200
+ if (m_clientApplication.isEmpty () && m_cwd.isEmpty ())
201
+ return false ;
202
+ break ;
203
+ case RecordType::LaunchRemoteApplication:
204
+ if (!m_remoteDevice.isConnected ())
205
+ return false ;
173
206
if (m_clientApplication.isEmpty () && m_cwd.isEmpty ())
174
207
return false ;
175
208
break ;
@@ -216,35 +249,13 @@ void RecordHost::setHost(const QString& host)
216
249
m_perfCapabilities = {};
217
250
emit perfCapabilitiesChanged (m_perfCapabilities);
218
251
219
- const auto perfPath = perfBinaryPath ();
220
- m_checkPerfCapabilitiesJob.startJob ([perfPath](auto &&) { return fetchLocalPerfCapabilities (perfPath); },
221
- [this ](RecordHost::PerfCapabilities capabilities) {
222
- Q_ASSERT (QThread::currentThread () == thread ());
223
-
224
- m_perfCapabilities = capabilities;
225
- emit perfCapabilitiesChanged (m_perfCapabilities);
226
- });
227
-
228
- m_checkPerfInstalledJob.startJob (
229
- [isLocal = isLocal (), perfPath](auto &&) {
230
- if (isLocal) {
231
- if (perfPath.isEmpty ()) {
232
- return !QStandardPaths::findExecutable (QStringLiteral (" perf" )).isEmpty ();
233
- }
234
-
235
- return QFileInfo::exists (perfPath);
236
- }
237
-
238
- qWarning () << " remote is not implemented" ;
239
- return false ;
240
- },
241
- [this ](bool isInstalled) {
242
- if (!isInstalled) {
243
- emit errorOccurred (tr (" perf is not installed" ));
244
- }
245
- m_isPerfInstalled = isInstalled;
246
- emit isPerfInstalledChanged (isInstalled);
247
- });
252
+ m_remoteDevice.disconnect ();
253
+ if (isLocal ()) {
254
+ checkRequirements ();
255
+ } else {
256
+ // checkRequirements will be called via RemoteDevice::connected
257
+ m_remoteDevice.connectToDevice (m_host);
258
+ }
248
259
}
249
260
250
261
void RecordHost::setCurrentWorkingDirectory (const QString& cwd)
@@ -265,16 +276,25 @@ void RecordHost::setCurrentWorkingDirectory(const QString& cwd)
265
276
m_cwd = cwd;
266
277
emit currentWorkingDirectoryChanged (cwd);
267
278
}
268
- return ;
279
+ } else {
280
+ if (!m_remoteDevice.checkIfDirectoryExists (cwd)) {
281
+ emit errorOccurred (tr (" Working directory folder cannot be found: %1" ).arg (cwd));
282
+ } else {
283
+ emit errorOccurred ({});
284
+ m_cwd = cwd;
285
+ emit currentWorkingDirectoryChanged (m_cwd);
286
+ }
269
287
}
270
-
271
- qWarning () << " is not implemented for remote" ;
272
288
}
273
289
274
290
void RecordHost::setClientApplication (const QString& clientApplication)
275
291
{
276
292
Q_ASSERT (QThread::currentThread () == thread ());
277
293
294
+ if (m_clientApplication == clientApplication) {
295
+ return ;
296
+ }
297
+
278
298
if (isLocal ()) {
279
299
QFileInfo application (KShell::tildeExpand (clientApplication));
280
300
if (!application.exists ()) {
@@ -296,10 +316,15 @@ void RecordHost::setClientApplication(const QString& clientApplication)
296
316
if (m_cwd.isEmpty ()) {
297
317
setCurrentWorkingDirectory (application.dir ().absolutePath ());
298
318
}
299
- return ;
319
+ } else {
320
+ if (!m_remoteDevice.checkIfFileExists (clientApplication)) {
321
+ emit errorOccurred (tr (" Application file cannot be found: %1" ).arg (clientApplication));
322
+ } else {
323
+ emit errorOccurred ({});
324
+ m_clientApplication = clientApplication;
325
+ emit clientApplicationChanged (m_clientApplication);
326
+ }
300
327
}
301
-
302
- qWarning () << " is not implemented for remote" ;
303
328
}
304
329
305
330
void RecordHost::setClientApplicationArguments (const QString& arguments)
@@ -314,11 +339,11 @@ void RecordHost::setClientApplicationArguments(const QString& arguments)
314
339
315
340
void RecordHost::setOutputFileName (const QString& filePath)
316
341
{
317
- if (isLocal ()) {
318
- const auto perfDataExtension = QStringLiteral (" .data" );
342
+ const auto perfDataExtension = QStringLiteral (" .data" );
343
+ const QFileInfo file (filePath);
344
+ const QFileInfo folder (file.absolutePath ());
319
345
320
- const QFileInfo file (filePath);
321
- const QFileInfo folder (file.absolutePath ());
346
+ if (isLocal ()) {
322
347
323
348
if (!folder.exists ()) {
324
349
emit errorOccurred (tr (" Output file directory folder cannot be found: %1" ).arg (folder.path ()));
@@ -333,11 +358,18 @@ void RecordHost::setOutputFileName(const QString& filePath)
333
358
m_outputFileName = filePath;
334
359
emit outputFileNameChanged (m_outputFileName);
335
360
}
336
-
337
- return ;
361
+ } else {
362
+ // TODO: check if this really nessesary depending if the output will be saved on the device or host
363
+ if (m_remoteDevice.checkIfDirectoryExists (folder.path ())) {
364
+ emit errorOccurred (tr (" Output file directory folder cannot be found: %1" ).arg (folder.path ()));
365
+ } else if (!filePath.endsWith (perfDataExtension)) {
366
+ emit errorOccurred (tr (" Output file must end with %1" ).arg (perfDataExtension));
367
+ } else {
368
+ emit errorOccurred ({});
369
+ m_outputFileName = filePath;
370
+ emit outputFileNameChanged (m_outputFileName);
371
+ }
338
372
}
339
-
340
- qWarning () << " is not implemented for remote" ;
341
373
}
342
374
343
375
void RecordHost::setRecordType (RecordType type)
@@ -379,3 +411,44 @@ QString RecordHost::perfBinaryPath() const
379
411
}
380
412
return {};
381
413
}
414
+
415
+ void RecordHost::checkRequirements ()
416
+ {
417
+ const auto perfPath = perfBinaryPath ();
418
+ m_checkPerfCapabilitiesJob.startJob (
419
+ [isLocal = isLocal (), &remoteDevice = m_remoteDevice, perfPath](auto &&) {
420
+ if (isLocal) {
421
+ return fetchLocalPerfCapabilities (perfPath);
422
+ } else {
423
+ return fetchRemotePerfCapabilities (remoteDevice);
424
+ }
425
+ },
426
+ [this ](RecordHost::PerfCapabilities capabilities) {
427
+ Q_ASSERT (QThread::currentThread () == thread ());
428
+
429
+ m_perfCapabilities = capabilities;
430
+ emit perfCapabilitiesChanged (m_perfCapabilities);
431
+ });
432
+
433
+ m_checkPerfInstalledJob.startJob (
434
+ [isLocal = isLocal (), &remoteDevice = m_remoteDevice, perfPath](auto &&) {
435
+ if (isLocal) {
436
+ if (perfPath.isEmpty ()) {
437
+ return !QStandardPaths::findExecutable (QStringLiteral (" perf" )).isEmpty ();
438
+ }
439
+
440
+ return QFileInfo::exists (perfPath);
441
+ } else {
442
+ return remoteDevice.checkIfProgramExists (QStringLiteral (" perf" ));
443
+ }
444
+
445
+ return false ;
446
+ },
447
+ [this ](bool isInstalled) {
448
+ if (!isInstalled) {
449
+ emit errorOccurred (tr (" perf is not installed" ));
450
+ }
451
+ m_isPerfInstalled = isInstalled;
452
+ emit isPerfInstalledChanged (isInstalled);
453
+ });
454
+ }
0 commit comments