2 * Copyright (c) 2019 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * This code uses concepts and configuration based on 'synth', by
8 * John R. Marino <draco@marino.st>, which was written in ada.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
20 * 3. Neither the name of The DragonFly Project nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific, prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 typedef struct MonitorFile
{
46 char packagespath
[128];
47 char repositorypath
[128];
48 char optionspath
[128];
49 char distfilespath
[128];
61 #define SNPRINTF(buf, ctl, ...) \
62 snprintf((buf), sizeof(buf), ctl, ## __VA_ARGS__)
64 static int StatsFd
= -1;
65 static int LockFd
= -1;
66 static monitor_file_t
*RStats
;
73 mkdir(StatsBase
, 0755);
74 if (stat(StatsBase
, &st
) < 0)
75 dfatal_errno("Cannot create %s");
76 if (st
.st_uid
&& st
.st_uid
!= getuid())
77 dfatal("%s not owned by current uid", StatsBase
);
78 StatsFd
= open(StatsFilePath
, O_RDWR
|O_CREAT
|O_CLOEXEC
, 0644);
80 dfatal_errno("Cannot create %s", StatsFilePath
);
81 ftruncate(StatsFd
, sizeof(monitor_file_t
));
83 LockFd
= open(StatsLockPath
, O_RDWR
|O_CREAT
|O_NOFOLLOW
|O_CLOEXEC
,
86 dfatal_errno("Cannot create %s", StatsLockPath
);
88 RStats
= mmap(NULL
, sizeof(monitor_file_t
),
89 PROT_READ
|PROT_WRITE
, MAP_SHARED
,
91 dassert_errno(RStats
!= MAP_FAILED
, "Unable to mmap %s", StatsFilePath
);
98 if (RStats
!= MAP_FAILED
)
99 munmap(RStats
, sizeof(monitor_file_t
));
107 flock(LockFd
, LOCK_UN
);
119 flock(LockFd
, LOCK_UN
); /* may fail */
121 bzero(rs
, sizeof(*rs
));
123 SNPRINTF(rs
->version
, "%s", DSYNTH_VERSION
);
124 rs
->maxworkers
= MaxWorkers
;
125 rs
->maxjobs
= MaxJobs
;
127 SNPRINTF(rs
->packagespath
, "%s", PackagesPath
);
128 SNPRINTF(rs
->repositorypath
, "%s", RepositoryPath
);
129 SNPRINTF(rs
->optionspath
, "%s", OptionsPath
);
130 SNPRINTF(rs
->distfilespath
, "%s", DistFilesPath
);
131 SNPRINTF(rs
->buildbase
, "%s", BuildBase
);
132 SNPRINTF(rs
->logspath
, "%s", LogsPath
);
133 SNPRINTF(rs
->systempath
, "%s", SystemPath
);
134 SNPRINTF(rs
->profile
, "%s", Profile
);
136 flock(LockFd
, LOCK_EX
); /* ready */
140 MonitorUpdate(worker_t
*work
, const char *dummy __unused
)
149 copy
.pkg
= NULL
; /* safety */
151 SNPRINTF(rs
->slots
[i
].portdir
, "%s", work
->pkg
->portdir
);
153 SNPRINTF(rs
->slots
[i
].portdir
, "%s", "");
154 rs
->slots
[i
].work
= copy
;
158 MonitorUpdateTop(topinfo_t
*info
)
168 MonitorUpdateLogs(void)
177 runstats_t MonitorRunStats
= {
180 .reset
= MonitorReset
,
181 .update
= MonitorUpdate
,
182 .updateTop
= MonitorUpdateTop
,
183 .updateLogs
= MonitorUpdateLogs
,
187 /****************************************************************************
188 * MONITOR DIRECTIVE FRONTEND *
189 * (independently executed dsynth app)
190 ****************************************************************************
192 * Access the monitor file and display available information
197 MonitorDirective(const char *datfile
, const char *lkfile
)
204 bzero(©
, sizeof(copy
));
206 StatsFd
= open(datfile
, O_RDONLY
);
208 printf("dsynth is not running\n");
212 LockFd
= open(lkfile
, O_RDWR
);
214 printf("dsynth is not running\n");
219 rs
= mmap(NULL
, sizeof(monitor_file_t
),
220 PROT_READ
, MAP_SHARED
,
222 dassert_errno(rs
!= MAP_FAILED
, "Cannot mmap \"%s\"", datfile
);
225 * Expect flock() to fail, if it doesn't then dsynth i
228 if (flock(LockFd
, LOCK_SH
|LOCK_NB
) == 0) {
229 flock(LockFd
, LOCK_UN
);
230 printf("dsynth is not running\n");
237 NCursesRunStats
.init();
238 NCursesRunStats
.reset();
241 * Run until done. When we detect completion we still give the
242 * body one more chance at the logs so the final log lines are
243 * properly displayed before exiting.
248 * Expect flock() to fail, if it doesn't then dsynth i
251 if (LockFd
>= 0 && flock(LockFd
, LOCK_SH
|LOCK_NB
) == 0) {
252 flock(LockFd
, LOCK_UN
);
256 NCursesRunStats
.updateTop(&rs
->info
);
257 for (i
= 0; rs
->version
[0] && i
< rs
->maxworkers
; ++i
) {
259 if (bcmp(©.slots[i].work,
261 sizeof(copy.slots[i].work)) != 0) {
267 copy
.slots
[i
].work
= rs
->slots
[i
].work
;
268 NCursesRunStats
.update(©
.slots
[i
].work
,
269 rs
->slots
[i
].portdir
);
273 NCursesRunStats
.updateLogs();
274 NCursesRunStats
.sync();
277 NCursesRunStats
.done();
278 printf("dsynth exited\n");