PortBuilder.pm 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. # ex:ts=8 sw=4:
  2. # $OpenBSD: PortBuilder.pm,v 1.77 2017/05/07 14:50:14 espie Exp $
  3. #
  4. # Copyright (c) 2010-2013 Marc Espie <espie@openbsd.org>
  5. #
  6. # Permission to use, copy, modify, and distribute this software for any
  7. # purpose with or without fee is hereby granted, provided that the above
  8. # copyright notice and this permission notice appear in all copies.
  9. #
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. use strict;
  18. use warnings;
  19. # this object is responsible for launching the build of ports
  20. # which mostly includes starting the right jobs
  21. package DPB::PortBuilder;
  22. use File::Path;
  23. use DPB::Util;
  24. use DPB::Job::Port;
  25. use DPB::Serialize;
  26. sub new
  27. {
  28. my ($class, $state) = @_;
  29. if ($state->opt('R')) {
  30. require DPB::PortBuilder::Rebuild;
  31. $class = $class->rebuild_class;
  32. }
  33. my $self = bless {
  34. state => $state,
  35. clean => $state->opt('c'),
  36. dontclean => $state->{dontclean},
  37. fetch => $state->opt('f'),
  38. wantsize => $state->{wantsize},
  39. fullrepo => $state->fullrepo,
  40. realfullrepo => $state->anchor($state->fullrepo),
  41. sizer => $state->sizer,
  42. heuristics => $state->heuristics}, $class;
  43. if ($state->opt('u') || $state->opt('U')) {
  44. $self->{update} = 1;
  45. }
  46. if ($state->opt('U')) {
  47. $self->{forceupdate} = 1;
  48. }
  49. if ($self->{fetch} && $state->defines('NO_CHECKSUM')) {
  50. $self->{nochecksum} = 1;
  51. }
  52. $self->init;
  53. return $self;
  54. }
  55. sub want_size
  56. {
  57. my ($self, $v, $core) = @_;
  58. if (!$self->{wantsize}) {
  59. return 0;
  60. }
  61. # always show for inmem
  62. if ($core->{inmem}) {
  63. return 1;
  64. }
  65. # do we already have this stats ? don't run it every time
  66. if ($self->{sizer}->match_pkgname($v)) {
  67. return rand(10) < 1;
  68. } else {
  69. return 1;
  70. }
  71. }
  72. sub rebuild_class
  73. { 'DPB::PortBuilder::Rebuild' }
  74. sub ports
  75. {
  76. my $self = shift;
  77. return $self->{state}->ports;
  78. }
  79. sub logger
  80. {
  81. my $self = shift;
  82. return $self->{state}->logger;
  83. }
  84. sub locker
  85. {
  86. my $self = shift;
  87. return $self->{state}->locker;
  88. }
  89. sub dontjunk
  90. {
  91. my ($self, $v) = @_;
  92. $self->{dontjunk}{$v->fullpkgname} = 1;
  93. }
  94. sub make
  95. {
  96. my $self = shift;
  97. return $self->{state}->make;
  98. }
  99. sub make_args
  100. {
  101. my $self = shift;
  102. return $self->{state}->make_args;
  103. }
  104. sub init
  105. {
  106. my $self = shift;
  107. $self->{state}{build_user}->make_path($self->{realfullrepo});
  108. $self->{global} = $self->logger->append("build");
  109. $self->{lockperf} =
  110. DPB::Util->make_hot($self->logger->append("awaiting-locks"));
  111. if ($self->{wantsize}) {
  112. $self->{logsize} =
  113. DPB::Util->make_hot($self->logger->append("size"));
  114. }
  115. if ($self->{state}->defines("WRAP_MAKE")) {
  116. $self->{rsslog} = $self->logger->logfile("rss");
  117. $self->{wrapper} = $self->{state}->defines("WRAP_MAKE");
  118. }
  119. }
  120. sub pkgfile
  121. {
  122. my ($self, $v) = @_;
  123. my $name = $v->fullpkgname;
  124. return "$self->{realfullrepo}/$name.tgz";
  125. }
  126. sub check
  127. {
  128. my ($self, $v) = @_;
  129. return $self->{state}{build_user}->run_as(
  130. sub {
  131. return -f $self->pkgfile($v);
  132. });
  133. }
  134. sub end_check
  135. {
  136. &check;
  137. }
  138. sub checks_rebuild
  139. {
  140. }
  141. sub register_package
  142. {
  143. }
  144. sub report
  145. {
  146. my ($self, $v, $job, $core) = @_;
  147. return if $job->{signature_only};
  148. my $pkgpath = $v->fullpkgpath;
  149. my $host = $core->fullhostname;
  150. if ($core->{realjobs}) {
  151. $host .= '*'.$core->{realjobs};
  152. }
  153. my $log = $self->{global};
  154. my $sz = $self->logger->run_as(
  155. sub {
  156. return (stat $self->logger->log_pkgpath($v))[7];
  157. });
  158. if (defined $job->{offset}) {
  159. $sz -= $job->{offset};
  160. }
  161. print $log "$pkgpath $host ", $job->totaltime, " ", $sz, " ",
  162. $job->timings;
  163. if ($job->{failed}) {
  164. my $fh = $self->logger->open('>>', $job->{log});
  165. print $fh "Error: job failed with $job->{failed} on ",
  166. $core->hostname, "\n";
  167. print $log "!\n";
  168. } else {
  169. print $log "\n";
  170. return unless defined $self->{state}{permanent_log};
  171. my $fh = $self->logger->open('>>',
  172. $self->{state}{permanent_log});
  173. return unless defined $fh;
  174. print $fh DPB::Serialize::Build->write({
  175. pkgpath => $pkgpath,
  176. host => $host,
  177. time => $job->totaltime,
  178. size => $sz,
  179. ts => CORE::time }), "\n";
  180. }
  181. }
  182. sub get
  183. {
  184. my $self = shift;
  185. return DPB::Core->get;
  186. }
  187. sub end_lock
  188. {
  189. my ($self, $lock, $core, $job) = @_;
  190. my $end = time();
  191. print $lock "status=$core->{status}\n";
  192. print $lock "todo=", $job->current_task, "\n";
  193. print $lock "end=$end (", DPB::Util->time2string($end), ")\n";
  194. close $lock;
  195. }
  196. sub build
  197. {
  198. my ($self, $v, $core, $lock, $final_sub) = @_;
  199. my $start = time();
  200. my ($log, $fh) = $self->logger->make_logs($v);
  201. my $memsize = $self->{sizer}->build_in_memory($fh, $core, $v);
  202. my $meminfo;
  203. if ($memsize) {
  204. print $lock "mem=$memsize\n";
  205. $meminfo = " in memory";
  206. $core->{inmem} = $memsize;
  207. } else {
  208. $meminfo = "";
  209. $core->{inmem} = 0;
  210. }
  211. if ($v->{info}->has_property('tag')) {
  212. print $lock "tag=".$v->{info}->has_property('tag')."\n";
  213. }
  214. print $fh ">>> Building on ", $core->hostname;
  215. print $fh $meminfo, " under ";
  216. $v->quick_dump($fh);
  217. my $job;
  218. $job = DPB::Job::Port->new($log, $fh, $v, $lock, $self, $memsize, $core,
  219. sub {
  220. close($fh);
  221. $self->end_lock($lock, $core, $job);
  222. $self->report($v, $job, $core);
  223. &$final_sub($job->{failed});
  224. });
  225. $core->start_job($job, $v);
  226. if ($job->{parallel}) {
  227. $core->can_swallow($job->{parallel}-1);
  228. }
  229. print $lock "host=", $core->hostname, "\n",
  230. "pid=$core->{pid}\n",
  231. "start=$start (", DPB::Util->time2string($start), ")\n";
  232. $job->set_watch($self->logger, $v);
  233. }
  234. sub force_junk
  235. {
  236. my ($self, $v, $core, $final_sub) = @_;
  237. my $start = time();
  238. my $log = $self->logger->log_pkgpath($v);
  239. my $fh = $self->logger->open('>>', $log);
  240. print $fh ">>> Force junking on ", $core->hostname;
  241. my $job;
  242. $job = DPB::Job::Port->new_junk_only($log, $fh, $v, undef, $self,
  243. 0,$core,
  244. sub {
  245. close($fh);
  246. &$final_sub($job->{failed});
  247. $core->mark_ready;
  248. });
  249. $core->start_job($job, $v);
  250. }
  251. sub test
  252. {
  253. my ($self, $v, $core, $lock, $final_sub) = @_;
  254. my $start = time();
  255. my $log = $self->logger->make_test_logs($v);
  256. my $memsize = $self->{sizer}->build_in_memory($core, $v);
  257. open my $fh, ">>", $log or DPB::Util->die_bang("can't open $log");
  258. if ($memsize) {
  259. print $lock "mem=$memsize\n";
  260. print $fh ">>> Building in memory under ";
  261. $core->{inmem} = $memsize;
  262. } else {
  263. print $fh ">>> Building under ";
  264. $core->{inmem} = 0;
  265. }
  266. if ($v->{info}->has_property('tag')) {
  267. print $lock "tag=".$v->{info}->has_property('tag')."\n";
  268. }
  269. $v->quick_dump($fh);
  270. my $job;
  271. $job = DPB::Job::Port::Test->new($log, $fh, $v, $lock, $self,
  272. $memsize, $core,
  273. sub {
  274. close($fh);
  275. $self->end_lock($lock, $core, $job);
  276. $self->report($v, $job, $core);
  277. &$final_sub($job->{failed});
  278. });
  279. $core->start_job($job, $v);
  280. print $lock "host=", $core->hostname, "\n",
  281. "pid=$core->{pid}\n",
  282. "start=$start (", DPB::Util->time2string($start), ")\n";
  283. }
  284. sub install
  285. {
  286. my ($self, $v, $core) = @_;
  287. my ($log, $fh) = $self->logger->make_logs($v);
  288. print $fh ">>> Installing under ";
  289. $v->quick_dump($fh);
  290. my $job = DPB::Job::Port::Install->new($log, $fh, $v, $self,
  291. sub {
  292. close($fh);
  293. $core->mark_ready;
  294. });
  295. $core->start_job($job, $v);
  296. return $core;
  297. }
  298. 1;