Changes In Branch v1.80 Through [34fa77c2e3] Excluding Merge-Ins
This is equivalent to a diff from abb42df5ef to 34fa77c2e3
2023-03-16
| ||
06:13 | Beginnings of dual ck5/ck4 build support. check-in: fdfdc48e5f user: matt tags: v1.80 | |
2023-03-15
| ||
10:03 | I saw a couple tcp errors with threads in flight of 500. Reducing to 200 and got clean sixtyfivek fast run. check-in: 34fa77c2e3 user: matt tags: v1.80 | |
2023-03-14
| ||
21:42 | This combo seemed about as robust as any check-in: 80c20a647d user: matt tags: v1.80 | |
2022-12-02
| ||
11:57 | new version branch check-in: 6cb6675102 user: mmgraham tags: v1.80 | |
2022-11-23
| ||
20:16 | Merged in nohomehost since multi-area dashboard will depend on nohomehost Leaf check-in: aac724292e user: matt tags: v1.70-ndboard | |
2022-11-22
| ||
09:06 | Turn the handler for opening server info files back on since those files can disappear without warning. Closed-Leaf check-in: abb42df5ef user: matt tags: v1.70-nohomehost | |
08:59 | Some more tweaks and output reduction. Still get crashes due to db lock but system seems to keep going pretty well. This is with 300 tests running on one machine. check-in: 4dcb84418f user: matt tags: v1.70-nohomehost | |
Modified Makefile from [2a2c13125c] to [7a836bf2ef].
26 27 28 29 30 31 32 | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | - + + + + + + + + + + + + | process.scm runs.scm tasks.scm tests.scm genexample.scm \ http-transport.scm tdb.scm client.scm mt.scm \ ezsteps.scm lock-queue.scm rmt.scm api.scm \ subrun.scm portlogger.scm archive.scm env.scm \ diff-report.scm cgisetup/models/pgdb.scm # module source files |
94 95 96 97 98 99 100 | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | - - + + | showmtesthash: @echo $(MTESTHASH) dboard : $(OFILES) $(GOFILES) dashboard.scm $(MOFILES) $(MOIMPFILES) megatest-version.scm megatest-fossil-hash.scm csc $(CSCOPTS) $(OFILES) dashboard.scm $(GOFILES) $(MOFILES) $(MOIMPFILES) -o dboard |
357 358 359 360 361 362 363 | 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 | - + - + | if [[ $(ARCHSTR) == 12.5 ]]; then \ mkdir -p $(PREFIX)/bin/.$(ARCHSTR)/lib; \ $(INSTALL) lib/libxcb-xlib.so.0 $(PREFIX)/bin/.$(ARCHSTR)/lib/libxcb-xlib.so.0; \ fi install : $(PREFIX)/bin/.$(ARCHSTR) $(PREFIX)/bin/.$(ARCHSTR)/mtest $(PREFIX)/bin/megatest \ $(PREFIX)/bin/.$(ARCHSTR)/dboard $(PREFIX)/bin/dashboard $(HELPERS) $(PREFIX)/bin/nbfake \ |
Modified TODO from [da5eae4898] to [fa3d981ca6].
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | + + + | # # You should have received a copy of the GNU General Public License # along with Megatest. If not, see <http://www.gnu.org/licenses/>. TODO ==== 23WW07 . Remove use of *dbstruct-dbs* WW15 . fill newview matrix with data, filter pipeline gui elements . improve [script], especially indent handling WW16 . split db into megatest.db (runs etc.) db/<something>.db . release basic newview implementation |
Modified api.scm from [e629c948c8] to [21d89cbc2e].
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | - - - - + + + + + + + + - - + + |
|
139 140 141 142 143 144 145 | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 | - + - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - + - - - + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - | ;; TASKS tasks-add tasks-set-state-given-param-key )) (define *db-write-mutexes* (make-hash-table)) |
Modified archive.scm from [25e6383e3d] to [220e8f084a].
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | + + | ;; strftime('%m/%d/%Y %H:%M:%S','now','localtime') (use (prefix sqlite3 sqlite3:) srfi-1 posix regex regex-case srfi-69 format md5 message-digest srfi-18) (declare (unit archive)) (declare (uses db)) (declare (uses common)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (include "db_records.scm") ;;====================================================================== ;; ;;====================================================================== |
Added artifacts.scm version [2d0631d1c4].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | + + + + + + + + + + + + + + + + + + + + + + + + | ;;====================================================================== ;; Copyright 2019, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit artifacts)) (include "artifacts/artifacts.scm") |
Added artifacts/README version [f734b55b91].
1 | + | NOTE: keep megatest/artifacts/ in sync with datastore/artifacts |
Added artifacts/artifacts.meta version [9ccf727941].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | + + + + + + + + + + + + + + + + + + + + + | ;; -*- scheme -*- ( ; Your egg's license: (license "BSD") ; Pick one from the list of categories (see below) for your egg and enter it ; here. (category db) ; A list of eggs pkts depends on. If none, you can omit this declaration ; altogether. If you are making an egg for chicken 3 and you need to use ; procedures from the `files' unit, be sure to include the `files' egg in the ; `needs' section (chicken versions < 3.4.0 don't provide the `files' unit). ; `depends' is an alias to `needs'. ;; (needs (autoload "3.0")) ; A list of eggs required for TESTING ONLY. See the `Tests' section. (test-depends test) (author "Matt Welland") (synopsis "A sha1-chain based datastore similar to the data format in fossil scm, consisting of artifacts of single line cards.")) |
Added artifacts/artifacts.release-info version [fbbc2937bb].
1 2 3 | + + + | (repo fossil "http://www.kiatoa.com/cgi-bin/fossils/{egg-name}") (uri zip "http://www.kiatoa.com/cgi-bin/fossils/{egg-name}/zip/{egg-name}.zip?uuid={egg-release}") (release "1.0") |
Added artifacts/artifacts.scm version [b5b4746c14].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ;; Copyright 2006-2017, Matthew Welland. ;; ;; This file is part of artifacts ;; ;; Pkts is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Pkts is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with Pkts. If not, see <http://www.gnu.org/licenses/>. ;; ;; CARDS: ;; ;; A card is a line of text, the first two characters are a letter followed by a ;; space. The letter is the card type. ;; ;; artifact: ;; ;; An artifact is a sorted list of cards with a final card Z that contains the shar1 hash ;; of all of the preceding cards. ;; ;; AARTIFACT: ;; ;; An alist mapping card types to card data ;; '((T . "artifacttype") ;; (a . "some content")) ;; ;; EARTIFACT: ;; ;; Extended packet using friendly keys. Must use a artifactspec to convert to/from eartifacts ;; '((ptype . "artifacttype") ;; (adata . "some content)) ;; ;; DARTIFACT: ;; ;; artifacts pulled from the database have this format: ;; ;;((aartifact (Z . "7de89c09ac024b3832c93e16cd78d11e2e28733b") <= this is a the alist ;; (t . "v1.63/tip/dev") ;; (c . "QUICKPATT") ;; (T . "runstart") ;; (P . "354eeb67120a921e3e33155ecab1b522ac10b6bd") ;; (D . "1488995096.0")) ;; (id . 8) ;; (group-id . 0) ;; (uuid . "7de89c09ac024b3832c93e16cd78d11e2e28733b") ;; (parent . "") ;; (artifact-type . "runstart") ;; (artifact . "D 1488995096.0\nP 354eeb67120a921e3e33155ecab1b522ac10b6bd\nT runstart\nc QUICKPATT\nt v1.63/tip/dev\nZ 7de89c09ac024b3832c93e16cd78d11e2e28733b")) ;; ;; artifactspec is alist of alists mapping types and nicekeys to keys ;; ;; '((posting . ((title . t) ;; (url . u) ;; (blurb . b))) ;; (comment . ((comment . c) ;; (score . s)))) ;; Reserved cards: ;; P : artifact parent ;; R : reference artifact containing mapping of short string -> sha1sum strings ;; T : artifact type ;; D : current time from (current-time), unless provided ;; Z : shar1 hash of the packet ;; Example usage: ;; ;; Create a artifact: ;; ;; (use artifacts) ;; (define-values (uuid artifact) ;; (alist->artifact ;; '((fruit . "apple") (meat . "beef")) ;; this is the data to convert ;; '((foods (fruit . f) (meat . m))) ;; this is the artifact spec ;; ptype: ;; 'foods)) ;; ;; Add to artifact queue: ;; ;; (define db (open-queue-db "/tmp/artifacts" "artifacts.db")) ;; (add-to-queue db artifact uuid 'foods #f 0) ;; no parent and use group_id of 0 ;; ;; Retrieve the packet from the db and extract a value: ;; ;; (alist-ref ;; 'meat ;; (dartifact->alist ;; (car (get-dartifacts db #f 0 #f)) ;; '((foods (fruit . f) ;; (meat . m))))) ;; => "beef" ;; (module artifacts ( ;; cards, util and misc ;; sort-cards ;; calc-sha1 ;; ;; low-level constructor procs, exposed only for development/testing, will be removed construct-sdat construct-artifact card->type/value add-z-card ;; queue database procs open-queue-db add-to-queue create-and-queue ;; lookup-by-uuid lookup-by-id get-dartifacts get-not-processed-artifacts get-related find-artifacts process-artifacts get-descendents get-ancestors get-artifacts ;; get-last-descendent ;; with-queue-db ;; load-artifacts-to-db ;; procs that operate directly on artifacts, sdat, aartifacts, dartifacts etc. artifact->alist ;; artifact -> aartifact (i.e. alist) artifact->sdat ;; artifact -> '("a aval" "b bval" ...) sdat->alist ;; '("a aval" "b bval"...) -> ((a . "aval")(b . "bval") ...) dblst->dartifacts ;; convert list of tuples from queue db into dartifacts dartifact->alist ;; flatten a dartifact into an alist containing all db fields and the artifact alist dartifacts->alists ;; apply dartifact->alist to a list of alists using a artifact-spec alist->artifact ;; returns two values uuid, artifact get-value ;; looks up a value given a key in a dartifact flatten-all ;; merge the list of values from a query which includes a artifact into a flat alist <== really useful! check-artifact ;; artifact alists write-alist->artifact read-artifact->alist ;; archive database ;; archive-open-db ;; write-archive-artifacts ;; archive-artifacts ;; mark-processed ;; artifactsdb artifactdb-conn ;; useful artifactdb-fname artifactsdb-open artifactsdb-close artifactsdb-add-record ;; temporary artifactdb-artifactspec ;; utility procs increment-string ;; used to get indexes for strings in ref artifacts make-report ;; make a .dot file calc-sha1 uuid-first-two-letters uuid-remaining-letters ;; file and directory utils multi-glob capture-dir file-get-sha1 check-same link-or-copy same-partition? link-if-same-partition archive-copy write-to-archive artifact-rollup read-artifacts-into-hash hash-of-artifacts->bundle archive-dest ;; pathname-full-filename ;; minimal artifact functions minimal-artifact-read minimal-artifact->alist afact-get-D afact-get-Z afact-get-T afact-get afact-get-number/default ;; bundles write-bundle read-bundle ;; new artifacts db with-todays-adb get-all-artifacts refresh-artifacts-db ) (import (chicken base) scheme (chicken process) (chicken time posix) (chicken io) (chicken file) (chicken pathname) chicken.process-context.posix (chicken string) (chicken time) (chicken sort) (chicken file posix) (chicken condition) srfi-1 regex srfi-13 srfi-69 (chicken port) (chicken process-context) crypt sha1 matchable message-digest sqlite3 typed-records directory-utils scsh-process) ;;====================================================================== ;; DATA MANIPULATION UTILS ;;====================================================================== (define-inline (unescape-data data) (string-translate* data '(("\\n" . "\n") ("\\\\" . "\\")))) (define-inline (escape-data data) (string-translate* data '(("\n" . "\\n") ("\\" . "\\\\")))) (define-inline (make-card type data) (conc type " " (escape-data (->string data)))) ;; reverse an alist for doing artifactkey -> external key conversions ;; (define-inline (reverse-aspec aspec) (map (lambda (dat) (cons (cdr dat)(car dat))) aspec)) ;; add a card to the list of cards, sdat ;; if type is #f return only sdat ;; if data is #f return only sdat ;; (define-inline (add-card sdat type data) (if (and type data) (cons (make-card type data) sdat) sdat)) ;;====================================================================== ;; STRING AS FUNKY NUMBER ;;====================================================================== ;; NOTE: PTDZ are removed as they are reserved. NB// the R card is not used in a ;; ref, instead the P parent card is used. ;; Question: Why does it matter to remove PTDZ? ;; To make the ref easier to use the ref strings will be the keys ;; so we cannot have overlap with any actual keys. But this is a ;; bit silly. What we need to do instead is reject keys of length ;; one where the char is in PTDZ ;; ;; This is basically base92 ;; (define string-num-chars (string->list "!#$%&'()*+,-./0123456789:;<=>?@ABCEFGHIJKLMNOQRSUVWXY[\\]^_abcdefghijklmnopqrstuvwxyz{|}~")) ;; "0123456789abcdefghijklmnopqrstuvwxyzABCEFGHIJKLMNOQSUVWXY!#$%&'()*+,-./[]:;<=>?\\^_{}|")) (define (char-incr inchar) (let* ((carry #f) (next-char (let ((rem (member inchar string-num-chars))) (if (eq? (length rem) 1) ;; we are at the last character in our string-num-chars list (begin (set! carry #t) (car string-num-chars)) (cadr rem))))) (values next-char carry))) (define (increment-string str) (if (string-null? str) "0" (let ((strlst (reverse (string->list str)))) ;; need to process the string from the lsd (list->string (let loop ((hed (car strlst)) (tal (cdr strlst)) (res '())) (let-values (((newhed carry)(char-incr hed))) ;; (print "newhed: " newhed " carry: " carry " tal: " tal) (let ((newres (cons newhed res))) (if carry ;; we'll have to propagate the carry (if (null? tal) ;; at the end, tack on "0" (which is really a "1") (cons (car string-num-chars) newres) (loop (car tal)(cdr tal) newres)) (append (reverse tal) newres))))))))) ;;====================================================================== ;; P K T S D B I N T E R F A C E ;; ;; INTEGER, REAL, TEXT ;;====================================================================== ;; ;; spec ;; ( (tablename1 . (field1name L1 TYPE) ;; (field2name L2 TYPE) ... ) ;; (tablename2 ... )) ;; ;; Example: (tests (testname n TEXT) ;; (rundir r TEXT) ;; ... ) ;; ;; artifact keys are taken from the first letter, if that is not unique ;; then look at the next letter and so on ;; ;; simplify frequent need to get one result with default ;; (define (get-one db default qry . params) (apply fold-row car default db qry params)) (define (get-rows db qry . params) (apply fold-row cons db qry params)) ;; use this struct to hold the artifactspec and the db handle ;; (defstruct artifactdb (fname #f) (artifactsdb-spec #f) (artifactspec #f) ;; cache the artifactspec (field-keys #f) ;; cache the field->key mapping (field1 . k1) ... (key-fields #f) ;; cache the key->field mapping (conn #f) ) ;; WARNING: There is a simplification in the artifactsdb spec w.r.t. artifactspec. ;; The field specs are the cdr of the table list - not a full ;; list. The extra list level in artifactspec is gratuitous and should ;; be removed. ;; (define (artifactsdb-spec->artifactspec tables-spec) (map (lambda (tablespec) (list (car tablespec) (map (lambda (field-spec) (cons (car field-spec)(cadr field-spec))) (cdr tablespec)))) tables-spec)) (define (artifactsdb-open dbfname artifactsdb-spec) (let* ((pdb (make-artifactdb)) (dbexists (file-exists? dbfname)) (db (open-database dbfname))) (artifactdb-artifactsdb-spec-set! pdb artifactsdb-spec) (artifactdb-artifactspec-set! pdb (artifactsdb-spec->artifactspec artifactsdb-spec)) (artifactdb-fname-set! pdb dbfname) (artifactdb-conn-set! pdb db) (if (not dbexists) (artifactsdb-init pdb)) pdb)) (define (artifactsdb-init artifactsdb) (let* ((db (artifactdb-conn artifactsdb)) (artifactsdb-spec (artifactdb-artifactsdb-spec artifactsdb))) ;; create a table for the artifacts themselves (execute db "CREATE TABLE IF NOT EXISTS artifacts (id INTEGER PRIMARY KEY, zkey TEXT, record_id INTEGER, artifact TEXT);") (for-each (lambda (table) (let* ((table-name (car table)) (fields (cdr table)) (stmt (conc "CREATE TABLE IF NOT EXISTS " table-name " (id INTEGER PRIMARY KEY," (string-intersperse (map (lambda (fieldspec) (conc (car fieldspec) " " (caddr fieldspec))) fields) ",") ");"))) (execute db stmt))) artifactsdb-spec))) ;; create artifact from the data and insert into artifacts table ;; ;; data is assoc list of (field . value) ... ;; tablename is a symbol matching the table name ;; (define (artifactsdb-add-record artifactsdb tablename data #!optional (parent #f)) (let*-values (((zkey artifact) (alist->artifact data (artifactdb-artifactspec artifactsdb) ptype: tablename))) ;; have the data as alist so insert it into appropriate table also (let* ((db (artifactdb-conn artifactsdb))) ;; TODO: Address collisions (execute db "INSERT INTO artifacts (zkey,artifact,record_id) VALUES (?,?,?);" zkey artifact -1) (let* (;; (artifactid (artifactsdb-artifactkey->artifactid artifactsdb artifactkey)) (record-id (artifactsdb-insert artifactsdb tablename data))) (execute db "UPDATE artifacts SET record_id=? WHERE zkey=?;" record-id zkey) )))) ;; (define (artifactsdb-insert artifactsdb tablename data) (let* ((db (artifactdb-conn artifactsdb)) (stmt (conc "INSERT INTO " tablename " (" (string-intersperse (map conc (map car data)) ",") ") VALUES ('" ;; TODO: Add lookup of data type and do not ;; wrap integers with quotes (string-intersperse (map conc (map cdr data)) "','") "');"))) (print "stmt: " stmt) (execute db stmt) ;; lookup the record-id and return it )) (define (artifactsdb-close artifactsdb) (finalize! (artifactdb-conn artifactsdb))) ;; (let loop ((s "0")(n 0))(print s)(if (< n 5000)(loop (increment-string s)(+ n 1)))) ;;====================================================================== ;; CARDS, MISC and UTIL ;;====================================================================== ;; given string (likely multi-line) "dat" return shar1 hash ;; (define (calc-sha1 instr) (message-digest-string (sha1-primitive) instr)) ;; given a single card return its type and value ;; (define (card->type/value card) (let ((ctype (substring card 0 1)) (cval (substring card 2 (string-length card)))) (values (string->symbol ctype) cval))) ;;====================================================================== ;; SDAT procs ;; sdat is legacy/internal usage. Intention is to remove sdat calls from ;; the exposed calls. ;;====================================================================== ;; sort list of cards ;; (define-inline (sort-cards sdat) (sort sdat string<=?)) ;; artifact rules ;; 1. one card per line ;; 2. at least one card ;; 3. no blank lines ;; given sdat, a list of cards return uuid, packet (as sdat) ;; (define (add-z-card sdat) (let* ((sorted-sdat (sort-cards sdat)) (dat (string-intersperse sorted-sdat "\n")) (uuid (calc-sha1 dat))) (values uuid (conc dat "\nZ " uuid)))) (define (check-artifact artifact) (handle-exceptions exn #f ;; anything goes wrong - call it a crappy artifact (let* ((sdat (string-split artifact "\n")) (rdat (reverse sdat)) ;; reversed (zdat (car rdat)) (Z (cadr (string-split zdat))) (cdat (string-intersperse (reverse (cdr rdat)) "\n"))) (equal? Z (calc-sha1 cdat))))) ;;====================================================================== ;; AARTIFACTs ;;====================================================================== ;; convert a sdat (list of cards) to an alist ;; (define (sdat->alist sdat) (let loop ((hed (car sdat)) (tal (cdr sdat)) (res '())) (let-values (( (ctype cval)(card->type/value hed) )) ;; if this card is not one of the common ones tack it on to rem (let* ((oldval (alist-ref ctype res)) (newres (cons (cons ctype (if oldval ;; list or string (if (list? oldval) (cons cval oldval) (cons cval (list oldval))) cval)) res))) (if (null? tal) newres (loop (car tal)(cdr tal) newres)))))) ;;((aartifact (Z . "7de89c09ac024b3832c93e16cd78d11e2e28733b") <= this is a the alist ;; (t . "v1.63/tip/dev") ;; (c . "QUICKPATT") ;; (T . "runstart") ;; (P . "354eeb67120a921e3e33155ecab1b522ac10b6bd") ;; (D . "1488995096.0")) ;; (id . 8) ;; (group-id . 0) ;; (uuid . "7de89c09ac024b3832c93e16cd78d11e2e28733b") ;; (parent . "") ;; (artifact-type . "runstart") ;; (artifact . "D 1488995096.0\nP 354eeb67120a921e3e33155ecab1b522ac10b6bd\nT runstart\nc QUICKPATT\nt v1.63/tip/dev\nZ 7de89c09ac024b3832c93e16cd78d11e2e28733b")) ;; ;; artifactspec is alist of alists mapping types and nicekeys to keys ;; ;; '((posting . ((title . t) ;; (url . u) ;; (blurb . b))) ;; (comment . ((comment . c) ;; (score . s)))) ;; DON'T USE? ;; (define (get-value field dartifact . spec-in) (if (null? spec-in) (alist-ref field dartifact) (let* ((spec (car spec-in)) (aartifact (alist-ref 'aartifact dartifact))) ;; get the artifact alist (if (and aartifact spec) (let* ((ptype (alist-ref 'artifact-type dartifact)) (pspec (alist-ref (string->symbol ptype) spec))) ;; do we have a spec for this type of artifact (and pspec (let* ((key (alist-ref field pspec))) (and key (alist-ref key aartifact))))) #f)))) ;; convert a dartifact to a pure alist given a artifactspec ;; this flattens out the alist to include the data from ;; the queue database record ;; (define (dartifact->alist dartifact artifactspec) (let* ((aartifact (alist-ref 'aartifact dartifact)) (artifact-type (or (alist-ref 'artifact-type dartifact) ;; artifact-type is from the database field artifact_type (alist-ref 'T aartifact))) (artifact-fields (alist-ref (string->symbol artifact-type) artifactspec)) (rev-fields (if artifact-fields (reverse-aspec artifact-fields) '()))) (append (map (lambda (entry) (let* ((artifact-key (car entry)) (new-key (or (alist-ref artifact-key rev-fields) artifact-key))) `(,new-key . ,(cdr entry)))) aartifact) dartifact))) ;; convert a list of dartifacts into a list of alists using artifact-spec ;; (define (dartifacts->alists dartifacts artifact-spec) (map (lambda (x) (dartifact->alist x artifact-spec)) dartifacts)) ;; Generic flattener, make the tuple and artifact into a single flat alist ;; ;; qry-result-spec is a list of symbols corresponding to each field ;; (define (flatten-all inlst artifactspec . qry-result-spec) (map (lambda (tuple) (dartifact->alist (apply dblst->dartifacts tuple qry-result-spec) artifactspec)) inlst)) ;; call like this: ;; (construct-sdat 'a "a data" 'S "S data" ...) ;; returns list of cards ;; ( "A a value" "D 12345678900" ...) ;; (define (construct-sdat . alldat) (let ((have-D-card #f)) ;; flag (if (even? (length alldat)) (let loop ((type (car alldat)) (data (cadr alldat)) (tail (cddr alldat)) (res '())) (if (eq? type 'D)(set! have-D-card #t)) (if (null? tail) (if have-D-card ;; return the constructed artifact, add a D card if none found (add-card res type data) (add-card (add-card res 'D (current-seconds)) type data)) (loop (car tail) (cadr tail) (cddr tail) (add-card res type data)))) #f))) ;; #f means it failed to create the sdat (define (construct-artifact . alldat) (add-z-card (apply construct-sdat alldat))) ;;====================================================================== ;; CONVERTERS ;;====================================================================== (define (artifact->sdat artifact) (map unescape-data (string-split artifact "\n"))) ;; given a pure artifact return an alist ;; (define (artifact->alist artifact #!key (artifactspec #f)) (let ((sdat (cond ((string? artifact) (artifact->sdat artifact)) ((list? artifact) artifact) (else #f)))) (if artifact (if artifactspec (dartifact->alist (list (cons 'aartifact (sdat->alist sdat))) artifactspec) (sdat->alist sdat)) #f))) ;; convert an alist to an sdat ;; in: '((a . "blah")(b . "foo")) ;; out: '("a blah" "b foo") ;; (define (alist->sdat adat) (map (lambda (dat) (conc (car dat) " " (cdr dat))) adat)) ;; adat is the incoming alist, aspec is the mapping ;; from incoming key to the artifact key (usually one ;; letter to keep data tight) see the artifactspec at the ;; top of this file ;; ;; NOTE: alists can contain multiple instances of the same key (supported fine by artifacts) ;; but you (obviously I suppose) cannot use alist-ref to access those entries. ;; (define (alist->artifact adat aspec #!key (ptype #f)(no-d #f)) (let* ((artifact-type (or ptype (alist-ref 'T adat) ;; can provide in the incoming alist #f)) (artifact-spec (if artifact-type ;; alist of external-key -> key (or (alist-ref artifact-type aspec) '()) (if (null? aspec) '() (cdar aspec)))) ;; default to first one if nothing specified (new-alist (map (lambda (dat) (let* ((key (car dat)) (val (cdr dat)) (newkey (or (alist-ref key artifact-spec) key))) (cons newkey (escape-data (conc val))))) ;; convert all incoming data (symbols, numbers etc.) to a string and then escape newlines. adat)) (new-with-type (if (alist-ref 'T new-alist) new-alist (cons `(T . ,artifact-type) new-alist))) (with-d-card (if (or no-d ;; no timestamp wanted (alist-ref 'D new-with-type)) new-with-type (cons `(D . ,(current-seconds)) new-with-type)))) (add-z-card (alist->sdat with-d-card)))) ;;====================================================================== ;; D B Q U E U E I N T E R F A C E ;;====================================================================== ;; artifacts ( ;; id SERIAL PRIMARY KEY, ;; uuid TEXT NOT NULL, ;; parent_uuid TEXT default '', ;; artifact_type INTEGER DEFAULT 0, ;; group_id INTEGER NOT NULL, ;; artifact TEXT NOT NULL ;; schema is list of SQL statements - can be used to extend db with more tables ;; (define (open-queue-db dbpath dbfile #!key (schema '())) (let* ((dbfname (conc dbpath "/" dbfile)) (dbexists (if (file-exists? dbfname) #t (begin (create-directory dbpath #t) #f))) (db (open-database dbfname))) ;; (set-busy-handler! (dbi:db-conn db) (busy-timeout 10000)) (if (not dbexists) ;; NOTE: In the archive we allow duplicates and other messiness. (for-each (lambda (stmt) (execute db stmt)) (cons "CREATE TABLE IF NOT EXISTS artifacts (id INTEGER PRIMARY KEY, group_id INTEGER NOT NULL, uuid TEXT NOT NULL, parent_uuid TEXT TEXT DEFAULT '', artifact_type TEXT NOT NULL, artifact TEXT NOT NULL, processed INTEGER DEFAULT 0)" schema))) ;; 0=not processed, 1=processed, 2... for expansion db)) (define (add-to-queue db artifact uuid artifact-type parent-uuid group-id) (execute db "INSERT INTO artifacts (uuid,parent_uuid,artifact_type,artifact,group_id) VALUES(?,?,?,?,?);" ;; $1,$2,$3,$4,$5);" uuid (if parent-uuid parent-uuid "");; use null string as placeholder for no parent uuid. (if artifact-type (conc artifact-type) "") artifact group-id)) ;; given all needed parameters create a artifact and store it in the queue ;; procs is an alist that maps artifact-type to a function that takes a list of artifact params ;; in data and returns the uuid and artifact ;; (define (create-and-queue conn procs artifact-type parent-uuid group-id data) (let ((proc (alist-ref artifact-type procs))) (if proc (let-values (( (uuid artifact) (proc data) )) (add-to-queue conn artifact uuid artifact-type parent-uuid group-id) uuid) #f))) ;; given uuid get artifact, if group-id is specified use it (reduces probablity of ;; being messed up by a uuid collision) ;; (define (lookup-by-uuid db artifact-uuid group-id) (if group-id (get-one db "SELECT artifact FROM artifacts WHERE group_id=? AND uuid=?;" group-id artifact-uuid) (get-one db "SELECT artifact FROM artifacts WHERE uuid=?;" artifact-uuid))) ;; find a packet by its id ;; (define (lookup-by-id db id) (get-one db "SELECT artifact FROM artifacts WHERE id=?;" id)) ;;====================================================================== ;; P R O C E S S P K T S ;;====================================================================== ;; given a list of field values pulled from the queue db generate a list ;; of dartifact's ;; (define (dblst->dartifacts lst . altmap) (let* ((maplst (if (null? altmap) '(id group-id uuid parent artifact-type artifact processed) altmap)) (res (map cons maplst lst))) ;; produces list of pairs, i.e an alist (cons `(aartifact . ,(artifact->alist (alist-ref 'artifact res))) res))) ;; NB// ptypes is a list of symbols, '() or #f find all types ;; (define (get-dartifacts db ptypes group-id parent-uuid #!key (uuid #f)) (let* ((ptype-qry (if (and ptypes (not (null? ptypes))) (conc " IN ('" (string-intersperse (map conc ptypes) "','") "')") (conc " LIKE '%' "))) (rows (get-rows db (conc "SELECT id,group_id,uuid,parent_uuid,artifact_type,artifact,processed FROM artifacts WHERE artifact_type " ptype-qry " AND group_id=? AND processed=0 " (if parent-uuid (conc "AND parent_uuid='" parent-uuid "' ") "") (if uuid (conc "AND uuid='" uuid "' ") "") "ORDER BY id DESC;") group-id))) (map dblst->dartifacts (map vector->list rows)))) ;; get N artifacts not yet processed for group-id ;; (define (get-not-processed-artifacts db group-id artifact-type limit offset) (map dblst->dartifacts (map vector->list (get-rows db "SELECT id,group_id,uuid,parent_uuid,artifact_type,artifact,processed FROM artifacts WHERE artifact_type = ? AND group_id = ? AND processed=0 LIMIT ? OFFSET ?;" (conc artifact-type) ;; convert symbols to string group-id limit offset )))) ;; given a uuid, get not processed child artifacts ;; (define (get-related db group-id uuid) (map dblst->dartifacts (get-rows db "SELECT id,group_id,uuid,parent_uuid,artifact_type,artifact,processed FROM artifacts WHERE parent_uuid=? AND group_id=? AND processed=0;" uuid group-id))) ;; generic artifact processor ;; ;; find all packets in group-id of type in ptypes and apply proc to artifactdat ;; (define (process-artifacts conn group-id ptypes parent-uuid proc) (let* ((artifacts (get-dartifacts conn ptypes group-id parent-uuid))) (map proc artifacts))) ;; criteria is an alist ((k . valpatt) ...) ;; - valpatt is a regex ;; - ptypes is a list of types (symbols expected) ;; match-type: 'any or 'all ;; (define (find-artifacts db ptypes criteria #!key (processed #f)(match-type 'any)(artifact-spec #f)) ;; processed=#f, don't use, else use (let* ((artifacts (get-dartifacts db ptypes 0 #f)) (match-rules (lambda (artifactdat) ;; returns a list of matching rules (filter (lambda (c) ;; (print "c: " c) (let* ((ctype (car c)) ;; card type (rx (cdr c)) ;; card pattern ;; (t (alist-ref 'artifact-type artifactdat)) (artifact (alist-ref 'artifact artifactdat)) (aartifact (artifact->alist artifact)) (cdat (alist-ref ctype aartifact))) ;; (print "cdat: " cdat) ;; " aartifact: " aartifact) (if cdat (string-match rx cdat) #f))) criteria))) (res (filter (lambda (artifactdat) (if (null? criteria) ;; looking for all artifacts #t (case match-type ((any)(not (null? (match-rules artifactdat)))) ((all)(eq? (length (match-rules artifactdat))(length criteria))) (else (print "ERROR: bad match type " match-type ", expecting any or all."))))) artifacts))) (if artifact-spec (dartifacts->alists res artifact-spec) res))) ;; get descendents of parent-uuid ;; ;; NOTE: Should be doing something like the following: ;; ;; given a uuid, get not processed child artifacts ;; processed: ;; #f => get all ;; 0 => get not processed ;; 1 => get processed ;; (define (get-ancestors db group-id uuid #!key (processed #f)) (map dblst->dartifacts (map vector->list (get-rows db (conc "SELECT id,group_id,uuid,parent_uuid,artifact_type,artifact,processed FROM artifacts WHERE uuid IN (WITH RECURSIVE tree(uuid,parent_uuid) AS ( SELECT uuid, parent_uuid FROM artifacts WHERE uuid = ? UNION ALL SELECT t.uuid, t.parent_uuid FROM artifacts t JOIN tree ON t.uuid = tree.parent_uuid ) SELECT uuid FROM tree) AND group_id=?" (if processed (conc " AND processed=" processed) "") ";") uuid group-id)))) ;; Untested ;; (define (get-descendents db group-id uuid #!key (processed #f)) (map dblst->dartifacts (map vector->list (get-rows db (conc "SELECT id,group_id,uuid,parent_uuid,artifact_type,artifact,processed FROM artifacts WHERE uuid IN (WITH RECURSIVE tree(uuid,parent_uuid) AS ( SELECT uuid, parent_uuid FROM artifacts WHERE uuid = ? UNION ALL SELECT t.uuid, t.parent_uuid FROM artifacts t JOIN tree ON t.parent_uuid = tree.uuid ) SELECT uuid FROM tree) AND group_id=?" (if processed (conc " AND processed=" processed) "") ";") uuid group-id)))) ;; look up descendents based on given info unless passed in a list via inlst ;; ;; (define (get-last-descendent db group-id uuid #!key (processed #f)(inlst #f)) ;; (let ((descendents (or inlst (get-descendents db group-id uuid processed: processed)))) ;; (if (null? descendents) ;; #f ;; (last descendents)))) ;;====================================================================== ;; A R C H I V E S - always to a sqlite3 db ;;====================================================================== ;; open an archive db ;; path: archive-dir/<year>/month.db ;; #;(define (archive-open-db archive-dir) (let* ((curr-time (seconds->local-time (current-seconds))) (dbpath (conc archive-dir "/" (time->string curr-time "%Y"))) (dbfile (conc dbpath "/" (time->string curr-time "%m") ".db")) (dbexists (if (file-exists? dbfile) #t (begin (create-directory dbpath #t) #f)))) (let ((db (open-database dbfile))) ;; (set-busy-handler! db (busy-timeout 10000)) (if (not dbexists) ;; NOTE: In the archive we allow duplicates and other messiness. (execute db "CREATE TABLE IF NOT EXISTS artifacts (id INTEGER, group_id INTEGER, uuid TEXT, parent_uuid TEXT, artifact_type TEXT, artifact TEXT, processed INTEGER DEFAULT 0)")) db))) ;; turn on transactions! otherwise this will be painfully slow ;; #;(define (write-archive-artifacts src-db db artifact-ids) (let ((artifacts (get-rows src-db (conc "SELECT id,group_id,uuid,parent_uuid,artifact_type,artifact FROM artifacts WHERE id IN (" (string-intersperse (map conc artifact-ids) ",") ")")))) ;; (dbi:with-transaction ;; db (lambda () (for-each (lambda (artifact) (apply execute db "INSERT INTO artifacts (id,group_id,uuid,parent_uuid,artifact_type,artifact) VALUES (?,?,?,?,?,?)" artifact)) artifacts)))) ;; ) ;; given a list of uuids and lists of uuids move all to ;; the sqlite3 db for the current archive period ;; #;(define (archive-artifacts conn artifact-ids archive-dir) (let ((db (archive-open-db archive-dir))) (write-archive-artifacts conn db artifact-ids) (finalize! db)) ;; (pg:with-transaction ;; conn ;; (lambda () (for-each (lambda (id) (get-one conn "DELETE FROM artifacts WHERE id=?" id)) artifact-ids)) ;; )) ;; given a list of ids mark all as processed ;; (define (mark-processed conn artifact-ids) ;; (pg:with-transaction ;; conn ;; (lambda () (for-each (lambda (id) (get-one conn "UPDATE artifacts SET processed=1 WHERE id=?;" id)) artifact-ids)) ;; x)) ;; a generic artifact getter, gets from the artifacts db ;; (define (get-artifacts conn ptypes) (let* ((ptypes-str (if (null? ptypes) "" (conc " WHERE artifact_type IN ('" (string-intersperse ptypes ",") "') "))) (qry-str (conc "SELECT id,group_id,uuid,parent_uuid,artifact_type,artifact,processed FROM artifacts" ptypes-str))) (map vector->list (get-rows conn qry-str)))) ;; make a report of the artifacts in the db ;; ptypes of '() gets all artifacts ;; display-fields ;; (define (make-report dest conn artifactspec display-fields . ptypes) (let* (;; (conn (dbi:db-conn (s:db))) (all-rows (get-artifacts conn ptypes)) (all-artifacts (flatten-all all-rows artifactspec 'id 'group-id 'uuid 'parent 'artifact-type 'artifact 'processed)) (by-uuid (let ((ht (make-hash-table))) (for-each (lambda (artifact) (let ((uuid (alist-ref 'uuid artifact))) (hash-table-set! ht uuid artifact))) all-artifacts) ht)) (by-parent (let ((ht (make-hash-table))) (for-each (lambda (artifact) (let ((parent (alist-ref 'parent artifact))) (hash-table-set! ht parent (cons artifact (hash-table-ref/default ht parent '()))))) all-artifacts) ht)) (oup (if dest (open-output-file dest) (current-output-port)))) (with-output-to-port oup (lambda () (print "digraph megatest_state_status { // ranksep=0.05 rankdir=LR; node [shape=\"box\"]; ") ;; first all the names (for-each (lambda (artifact) (let* ((uuid (alist-ref 'uuid artifact)) (shortuuid (substring uuid 0 4)) (type (alist-ref 'artifact-type artifact)) (processed (alist-ref 'processed artifact))) (print "\"" uuid "\" [label=\"" shortuuid ", (" type ", " (if processed "processed" "not processed") ")") (for-each (lambda (key-field) (let ((val (alist-ref key-field artifact))) (if val (print key-field "=" val)))) display-fields) (print "\" ];"))) all-artifacts) ;; now for parent-child relationships (for-each (lambda (artifact) (let ((uuid (alist-ref 'uuid artifact)) (parent (alist-ref 'parent artifact))) (if (not (equal? parent "")) (print "\"" parent "\" -> \"" uuid"\";")))) all-artifacts) (print "}") )) (if dest (begin (close-output-port oup) (system "dot -Tpdf out.dot -o out.pdf"))) )) ;;====================================================================== ;; Read ref artifacts into a vector < laststr hash table > ;;====================================================================== ;;====================================================================== ;; Read/write packets to files (convience functions) ;;====================================================================== ;; write alist to a artifact file ;; (define (write-alist->artifact targdir dat #!key (artifactspec '())(ptype #f)) (let-values (((uuid artifact)(alist->artifact dat artifactspec ptype: ptype))) (with-output-to-file (conc targdir "/" uuid ".artifact") (lambda () (print artifact))) uuid)) ;; return the uuid ;; read artifact into alist ;; (define (read-artifact->alist artifact-file #!key (artifactspec #f)) (artifact->alist (with-input-from-file artifact-file read-string) artifactspec: artifactspec)) ;;====================================================================== ;; File utils, stuff useful for file management ;;====================================================================== (define (file-get-sha1 fname) (let* ((sha1-res (run/strings (sha1sum ,fname)))) (car (string-split (car sha1-res))))) (define (link-or-copy srcf destf) (or (handle-exceptions exn #f (file-link srcf destf)) (if (file-exists? destf) (print "NOTE: destination already exists, skipping copy.") (copy-file srcf destf)))) ;; (define (files-diff file1 file2) ;; (let* ((diff-res (with-input-from-port ;; (run/port (diff "-q" ,file1 ,file2)) ;; (lambda () ;; (let* ((res (read-line))) ;; (read-lines) ;; res))))) ;; (car (string-split sha1-res)))) ;; (define (check-same file1 file2) (cond ((not (and (file-exists? file1)(file-exists? file2))) #f) ((not (equal? (file-size file1)(file-size file2))) #f) (else (let-values (((status run-ok process-id) (run (diff "-q" ,file1 ,file2)))) status)))) (define *pcache* (make-hash-table)) (define (get-device dir) (let ((indat (or (hash-table-ref/default *pcache* dir #f) (let* ((inp (open-input-pipe (conc "df --output=source \""dir"\""))) (res (read-lines inp))) (close-input-port inp) (hash-table-set! *pcache* dir res) res)))) (cadr indat))) (define (same-partition? dir1 dir2) (equal? (get-device dir1)(get-device dir2))) (define (link-if-same-partition file1 file2) (let* ((dir1 (pathname-directory file1)) (dir2 (pathname-directory file2)) (f1 (pathname-file file1)) (f2 (pathname-file file2))) (if (same-partition? dir1 dir2) (let* ((tmpname (conc "."f2"-"(current-seconds)))) ;; this steps needs to be executed as actual user (move-file file2 (conc dir1 "/" tmpname)) (file-link file1 file2) (delete-file (conc dir1 "/" tmpname)))))) (define (uuid-first-two-letters sha1sum) (substring sha1sum 0 2)) (define (uuid-remaining-letters sha1sum) (let ((slen (string-length sha1sum))) (substring sha1sum 2 slen))) (define (archive-dest destd sha1sum) (let* ((subdir (uuid-first-two-letters sha1sum)) ;; (substring sha1sum 0 2)) ;; (slen (string-length sha1sum)) (rem sha1sum #;(uuid-remaining-letters sha1sum)) ;; (substring sha1sum 3 slen)) (full-dest-dir (conc destd"/"subdir)) (full-dest-file (conc full-dest-dir"/"rem))) (if (not (directory-exists? full-dest-dir)) (create-directory full-dest-dir #t)) full-dest-file)) (define (write-to-archive data destd #!optional (nextnum #f)) (let* ((sha1sum (calc-sha1 data)) (full-dest (conc (archive-dest destd sha1sum) (if nextnum (conc "."nextnum) "")))) (if (file-exists? full-dest) (if (equal? (string-intersperse (with-input-from-file full-dest read-lines) "\n") data) (begin ;; (print "INFO: data already exists in "full-dest" and is identical") sha1sum) (let ((nextnum (if nextnum (+ nextnum 1) 0))) (print "WARN: data already exists in "full-dest" but is different! Trying again...") (write-to-archive data destd nextnum))) (begin (with-output-to-file full-dest (lambda () (print data))) sha1sum)))) ;; BUG? Does print munge data? ;; copy srcf with sha1sum aabc... to aa/bc... ;; (define (archive-copy srcf destd sha1sum) (let* ((full-dest-file (archive-dest destd sha1sum))) (let loop ((trynum 0)) (let ((dest-name (if (> trynum 0) (conc full-dest-file"-"trynum) full-dest-file))) (cond ((not (file-exists? srcf)) #f) ;; this should be an error? ((and (file-exists? srcf) (file-exists? dest-name)) (if (check-same srcf dest-name) (link-if-same-partition dest-name srcf) (loop (+ trynum 1)))) ;; collisions are rare, this protects against them ((not (file-exists? dest-name)) (link-or-copy srcf dest-name)) (else #f)))))) ;; multi-glob (define (multi-glob globstrs inpath) ;; (print "multi-glob: "globstrs", "inpath) (if (equal? inpath "") globstrs (let* ((parts (string-split inpath "/" #t)) (nextpart (car parts)) (remaining (string-intersperse (cdr parts) "/"))) (if (and (equal? nextpart "") ;; this must be a leading / meaning root directory (null? globstrs)) (multi-glob '("/") remaining) (begin ;; (print "nextpart="nextpart", remaining="remaining) (apply append (map (lambda (gstr) (let* ((pathstr (conc gstr"/"nextpart)) (pathstrs (glob pathstr))) ;; (print "pathstr="pathstr) (multi-glob pathstrs remaining))) globstrs))))))) ;; perm[/user:group]: ;; DDD - octal perm (future expansion) ;; - - use umask/defacto perms (i.e. don't actively do anything) ;; x - mark as executable ;; ;; Cards: ;; file: f perm fname ;; directory: d perm fname artifactid ;; link: l perm lname destpath ;; ;; NOTE: cards are kept as (C . "value") ;; ;; given a directory path, ignore list and artifact store (hash-table): ;; 1. create sha1 tree at dest (e.g. aa/b3a7 ...) ;; 2. create artifact for each dir ;; - cards for all files ;; - cards for files that are symlinks or executables ;; 3. return (artifactid . artifact) ;; ;; NOTES: ;; Use destdir of #f to not create sha1 tree ;; Hard links will be used if srcdir and destdir appear to be same partion ;; ;; (alist->artifact adat aspec #!key (ptype #f)) ;; ;; ;; (load "../../artifacts/artifacts.scm")(import big-chicken srfi-69 artifacts)(define dirdat (make-hash-table)) ;; (capture-dir ".." ".." "/tmp/junk" '() dirdat) ;; ;; [procedure] (file-type FILE [LINK [ERROR]]) ;; Returns the file-type for FILE, which should be a filename, a file-descriptor or a port object. If LINK is given and true, symbolic-links are not followed: ;; ;; regular-file ;; directory ;; fifo ;; socket ;; symbolic-link ;; character-device ;; block-device ;; Note that not all types are supported on every platform. If ERROR is given and false, then file-type returns #f if the file does not exist; otherwise, it signals an error. ;; ;; (define (capture-dir curr-dir src-dir dest-dir ignore-list artifacts all-seen) (let* ((dir-dat (directory-fold (lambda (fname res) ;; res is a list of artifact cards (let* ((fullname (conc curr-dir"/"fname))) ;; (print "INFO: processing "fullname) (if (hash-table-ref/default all-seen fullname #f) ;; something circular going on (begin (print "WARNING: possible circular link(s) "fullname) res) (let* ((ftype (file-type fullname #t #f))) (hash-table-set! all-seen fullname ftype) (cons (case ftype ;; get the card ((directory) ;; (directory? fullname) (let* ((new-curr-dir (conc curr-dir"/"fname)) (new-src-dir (conc src-dir"/"fname))) (let* ((dir-dat (capture-dir new-curr-dir new-src-dir dest-dir ignore-list artifacts all-seen)) (a-id (car dir-dat)) (artf (cdr dir-dat))) (hash-table-set! artifacts a-id artf) (cons 'd (conc "- "a-id" "fname))))) ;; the card ((symbolic-link) ;; (symbolic-link? fullname) (let ((ldest (read-symbolic-link fullname))) (cons 'l (conc "- "fname"/"ldest)))) ;; delimit link name from dest with / ((regular-file) ;; must be a file (let* ((start (current-seconds)) (sha1sum (file-get-sha1 fullname)) (perms (if (file-executable? fullname) "x" "-"))) (let ((runtime (- (current-seconds) start))) (if (> runtime 1) (print "INFO: file "fullname" took "runtime" seconds to calculate sha1."))) (if dest-dir (archive-copy fullname dest-dir sha1sum)) (cons 'f (conc perms " "sha1sum" "fname)))) (else (print "WARNING: file "fullname" of type "ftype" is NOT supported and will converted to empty file.") (let* ((sha1sum (write-to-archive "" dest-dir))) (cons 'f (conc "- "sha1sum" "fname))))) res))))) '() src-dir #:dotfiles? #t))) ;; => (values srcdir_artifact sub_artifacts_list) ;; (print "dir-dat: " dir-dat) (let-values (((a-id artf) (alist->artifact dir-dat '() ptype: 'd no-d: #t))) (hash-table-set! artifacts a-id artf) (cons a-id artf)))) ;; maybe move this into artifacts? ;; ;; currently moves *.artifact into a bundle and moves the artifacts into attic ;; future: move artifacts under 1 meg in size into bundle up to 10 meg in size ;; (define (artifact-rollup bundle-dir) ;; cfg storepath) ;; (let* ((bundle-dir (calc-bundle-dir cfg storepath))) (let* ((bundles (glob (conc bundle-dir"/*.bundle"))) (artifacts (glob (conc bundle-dir"/*.artifact")))) (if (> (length artifacts) 30) ;; rollup only if > 30 artifacts ;; if we have unbundled artifacts, bundle them (let* ((ht (read-artifacts-into-hash #f artifacts: artifacts)) (bundle (hash-of-artifacts->bundle ht))) (write-bundle bundle bundle-dir) (create-directory (conc bundle-dir"/attic") #t) (for-each (lambda (full-fname) (let* ((fname (pathname-strip-directory full-fname)) (newname (conc bundle-dir"/attic/"fname))) (move-file full-fname newname #t))) artifacts) (conc "bundled "(length artifacts))) "not enough artifacts to bundle"))) ;; if destfile is a directory then calculate the sha1sum of the bundle and store it ;; by <sha1sum>.bundle ;; ;; incoming dat is pure text (bundle already sorted and appended: ;; (define (write-bundle bdl-data destdir) (let* ((bdl-uuid (calc-sha1 bdl-data))) (with-output-to-file (conc destdir"/"bdl-uuid".bundle") (lambda () (print bdl-data))))) ;; minimal (and hopefully fast) artifact reader ;; TODO: Add check of shar sum. ;; (define (minimal-artifact-read fname) (let* ((indat (with-input-from-file fname read-lines))) (if (null? indat) (values #f (conc "did not find an artifact in "fname)) (let* ((zcard (last indat)) (cardk (substring zcard 0 1)) (cardv (substring zcard 2 (string-length zcard)))) (if (equal? cardk "Z") (values cardv (string-intersperse indat "\n")) (values #f (conc fname" is not a valid artifact"))))))) ;; read artifacts from directory into hash ;; NOTE: support for max-count not implemented yet ;; (define (read-artifacts-into-hash dir #!key (artifacts #f) (max-count #f)(ht #f)) (let* ((artifacts (or artifacts (glob (conc dir"/*.artifact")))) (ht (or ht (make-hash-table)))) (for-each (lambda (fname) (let-values (((uuid afct) (minimal-artifact-read fname))) (hash-table-set! ht uuid afct))) artifacts) ht)) ;; ht is: ;; uuid => artifact text ;; use write-bundle to put result into a bundle file ;; (define (hash-of-artifacts->bundle ht) (fold (lambda (k res) (let* ((v (hash-table-ref ht k))) (if res (conc res"\n"v) v))) #f (sort (hash-table-keys ht) string<=?))) ;; minimal artifact to alist ;; (define (minimal-artifact->alist afact) (let* ((lines (string-split afact "\n"))) (map (lambda (a) (let* ((key (string->symbol (substring a 0 1))) (sl (string-length a)) (val (if (> sl 2) (substring a 2 sl) ""))) (cons key val))) lines))) ;; some accessors for common cards (define (afact-get-D afact) (let ((dval (alist-ref 'D afact))) (if dval (string->number dval) #f))) (define (afact-get-T afact) ;; get the artifact type as a symbol (let ((val (alist-ref 'T afact))) (if val (string->symbol val) val))) (define (afact-get-Z afact) (alist-ref 'Z afact)) (define (afact-get afact key default) (or (alist-ref key afact) default)) (define (afact-get-number/default afact key default) (let ((val (alist-ref key afact))) (if val (or (string->number val) default) ;; seems wrong default))) ;; bundles are never big and reading into memory for processing is fine ;; (define (read-bundle srcfile #!optional (mode 'uuid-raw)) (let* ((indat (with-input-from-file srcfile read-lines))) (let loop ((tail indat) (dat '()) ;; artifact being extracted (res '())) ;; list of artifacts (if (null? tail) (reverse res) ;; last dat should be empty list (let* ((curr-line (car tail))) (let-values (((ctype cdata) (card->type/value curr-line))) (let* ((is-z-card (eq? 'Z ctype)) (new-dat (cons (case mode ((uuid-raw) curr-line) (else (cons ctype cdata))) dat))) (if is-z-card (loop (cdr tail) ;; done with this artifact '() (cons (case mode ((uuid-raw) (cons cdata (string-intersperse (reverse new-dat) "\n"))) (else (reverse new-dat))) res)) (loop (cdr tail) new-dat res))))))))) ;; find all .bundle and .artifacts files in bundle-dir ;; and inport them into sqlite handle adb ;; (define (refresh-artifacts-db adb bundle-dir) (let* ((bundles (glob (conc bundle-dir"/*.bundle"))) (artifacts (glob (conc bundle-dir"/*.artifact"))) (uuids (get-all-uuids adb 'hash))) (with-transaction adb (lambda () (for-each (lambda (bundle-file) ;; (print "Importing artifacts from "bundle-file) (let* ((bdat (read-bundle bundle-file 'uuid-raw)) (count 0) (inc (lambda ()(set! count (+ count 1))))) (for-each (lambda (adat) (match adat ((zval . artifact) (if (not (hash-table-exists? uuids zval)) (begin ;; (print "INFO: importing new artifact "zval" from bundle "bundle-file) (inc) (execute adb "INSERT INTO artifacts (uuid, artifact) VALUES (?,?);" zval artifact) (hash-table-set! uuids zval #t)))) (else (print "ERROR: Bad artifact data "adat)))) bdat) (print "INFO: imported "count" artifacts from "bundle-file))) bundles) (for-each (lambda (artifact-file) ;; (print "Importing artifact from "artifact-file) (let-values (((uuid artifact) (minimal-artifact-read artifact-file))) (if uuid (if (not (hash-table-exists? uuids uuid)) (begin ;; (print "INFO: importing new artifact "uuid" from "artifact-file) (execute adb "INSERT INTO artifacts (uuid, artifact) VALUES (?,?);" uuid artifact) (hash-table-set! uuids uuid #t))) (print "Bad artifact in "artifact-file)))) artifacts))))) ;;====================================================================== ;; Artifacts db cache ;;====================================================================== ;; artifacts ;; id SERIAL PRIMARY KEY, ;; uuid TEXT NOT NULL, ;; artifact TEXT NOT NULL ;; ;; parents ;; id INTEGER REFERENCES artids.id, -- ;; parent_id REFERENCES artids.id ;; ;; schema is list of SQL statements - can be used to extend db with more tables ;; (define (open-artifacts-db dbpath dbfile #!key (schema '())) (let* ((dbfname (conc dbpath "/" dbfile)) (dbexists (if (file-exists? dbfname) #t (begin (create-directory dbpath #t) #f))) (adb (open-database dbfname))) (set-busy-handler! adb (make-busy-timeout 10000)) (execute adb "PRAGMA synchronous = 0;") (if (not dbexists) (with-transaction adb (lambda () (for-each (lambda (stmt) (execute adb stmt)) (append `("CREATE TABLE IF NOT EXISTS artifacts (id INTEGER PRIMARY KEY, uuid TEXT NOT NULL, artifact TEXT NOT NULL)" "CREATE TABLE IF NOT EXISTS parents (id INTEGER REFERENCES artifacts(id) NOT NULL, parent_id INTEGER REFERENCES artifacts(id) NOT NULL)") schema))))) adb)) (define (generate-year-month-name #!optional (seconds #f)) (let* ((curr-time (seconds->local-time (or seconds (current-seconds))))) (time->string curr-time "%Y%m"))) ;; I don't like this function. TODO: remove the ;; mode and option to return ht. Use instead the ;; get-all-artifacts below ;; (define (get-all-uuids adb #!optional (mode #f)) (let* ((res (fold-row (lambda (res uuid) (cons uuid res)) '() adb "SELECT uuid FROM artifacts;"))) (case mode ((hash) (let* ((ht (make-hash-table))) (for-each (lambda (uuid) (hash-table-set! ht uuid #t)) res) ht)) (else res)))) ;; returns raw artifacts (i.e. NOT alists but instead plain text) (define (get-all-artifacts adb) (let* ((ht (make-hash-table))) (for-each-row (lambda (id uuid artifact) (hash-table-set! ht uuid `(,id ,uuid ,artifact))) adb "SELECT id,uuid,artifact FROM artifacts;") ht)) ;; given a bundle-dir copy or create to /tmp and open ;; the YYMM.db file and hand the handle to the given proc ;; NOTE: we operate in /tmp/ to accomodate users on NFS ;; where slamming Unix locks at an NFS filer can cause ;; locking fails. Eventually this /tmp behavior will be ;; configurable. ;; (define (with-todays-adb bundle-dir proc) (let* ((dbname (conc (generate-year-month-name) ".db")) (destname (conc bundle-dir"/"dbname)) (tmparea (conc "/tmp/"(current-user-name)"-"(calc-sha1 bundle-dir))) (tmpname (conc tmparea"/"dbname)) (lockfile (conc destname".update-in-progress"))) ;; (print "with-todays-adb, bundle-dir: "bundle-dir", dbname: "dbname", destname: "destname",\n tmparea: " tmparea", lockfile: "lockfile) (if (not (file-exists? tmparea))(create-directory tmparea #t)) (let loop ((count 0)) (if (file-exists? lockfile) (if (< count 30) ;; aproximately 30 seconds (begin (sleep 1) (loop (+ 1 count))) (print "ERROR: "lockfile" exists, proceeding anyway")) (if (file-exists? destname) (begin (copy-file destname tmpname #t) (copy-file destname lockfile #t))))) (let* ((adb (open-artifacts-db tmparea dbname)) (res (proc adb))) (finalize! adb) (copy-file tmpname destname #t) (delete-file* lockfile) res))) ) ;; module artifacts ;; ATTIC |
Added artifacts/artifacts.setup version [bf666feb42].
1 2 3 4 5 6 7 8 9 10 11 | + + + + + + + + + + + | ;; Copyright 2007-2017, Matthew Welland. ;; ;; This program is made available under the GNU GPL version 2.0 or ;; greater. See the accompanying file COPYING for details. ;; ;; This program is distributed WITHOUT ANY WARRANTY; without even the ;; implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ;; PURPOSE. ;;;; pkts.setup (standard-extension 'pkts "1.0") |
Added artifacts/artifactsrec.scm version [28997466b3].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | (define-syntax define-record-type (syntax-rules () ((define-record-type type (constructor constructor-tag ...) predicate (field-tag accessor . more) ...) (begin (define type (make-record-type 'type '(field-tag ...))) (define constructor (record-constructor type '(constructor-tag ...))) (define predicate (record-predicate type)) (define-record-field type field-tag accessor . more) ...)))) ; An auxilliary macro for define field accessors and modifiers. ; This is needed only because modifiers are optional. (define-syntax define-record-field (syntax-rules () ((define-record-field type field-tag accessor) (define accessor (record-accessor type 'field-tag))) ((define-record-field type field-tag accessor modifier) (begin (define accessor (record-accessor type 'field-tag)) (define modifier (record-modifier type 'field-tag)))))) ; Record types ; We define the following procedures: ; ; (make-record-type <type-name <field-names>) -> <record-type> ; (record-constructor <record-type<field-names>) -> <constructor> ; (record-predicate <record-type>) -> <predicate> ; (record-accessor <record-type <field-name>) -> <accessor> ; (record-modifier <record-type <field-name>) -> <modifier> ; where ; (<constructor> <initial-value> ...) -> <record> ; (<predicate> <value>) -> <boolean> ; (<accessor> <record>) -> <value> ; (<modifier> <record> <value>) -> <unspecific> ; Record types are implemented using vector-like records. The first ; slot of each record contains the record's type, which is itself a ; record. (define (record-type record) (record-ref record 0)) ;---------------- ; Record types are themselves records, so we first define the type for ; them. Except for problems with circularities, this could be defined as: ; (define-record-type :record-type ; (make-record-type name field-tags) ; record-type? ; (name record-type-name) ; (field-tags record-type-field-tags)) ; As it is, we need to define everything by hand. (define :record-type (make-record 3)) (record-set! :record-type 0 :record-type) ; Its type is itself. (record-set! :record-type 1 ':record-type) (record-set! :record-type 2 '(name field-tags)) ; Now that :record-type exists we can define a procedure for making more ; record types. (define (make-record-type name field-tags) (let ((new (make-record 3))) (record-set! new 0 :record-type) (record-set! new 1 name) (record-set! new 2 field-tags) new)) ; Accessors for record types. (define (record-type-name record-type) (record-ref record-type 1)) (define (record-type-field-tags record-type) (record-ref record-type 2)) ;---------------- ; A utility for getting the offset of a field within a record. (define (field-index type tag) (let loop ((i 1) (tags (record-type-field-tags type))) (cond ((null? tags) (error "record type has no such field" type tag)) ((eq? tag (car tags)) i) (else (loop (+ i 1) (cdr tags)))))) ;---------------- ; Now we are ready to define RECORD-CONSTRUCTOR and the rest of the ; procedures used by the macro expansion of DEFINE-RECORD-TYPE. (define (record-constructor type tags) (let ((size (length (record-type-field-tags type))) (arg-count (length tags)) (indexes (map (lambda (tag) (field-index type tag)) tags))) (lambda args (if (= (length args) arg-count) (let ((new (make-record (+ size 1)))) (record-set! new 0 type) (for-each (lambda (arg i) (record-set! new i arg)) args indexes) new) (error "wrong number of arguments to constructor" type args))))) (define (record-predicate type) (lambda (thing) (and (record? thing) (eq? (record-type thing) type)))) (define (record-accessor type tag) (let ((index (field-index type tag))) (lambda (thing) (if (and (record? thing) (eq? (record-type thing) type)) (record-ref thing index) (error "accessor applied to bad value" type tag thing))))) (define (record-modifier type tag) (let ((index (field-index type tag))) (lambda (thing value) (if (and (record? thing) (eq? (record-type thing) type)) (record-set! thing index value) (error "modifier applied to bad value" type tag thing))))) Records ; This implements a record abstraction that is identical to vectors, ; except that they are not vectors (VECTOR? returns false when given a ; record and RECORD? returns false when given a vector). The following ; procedures are provided: ; (record? <value>) -> <boolean> ; (make-record <size>) -> <record> ; (record-ref <record> <index>) -> <value> ; (record-set! <record> <index> <value>) -> <unspecific> ; ; These can implemented in R5RS Scheme as vectors with a distinguishing ; value at index zero, providing VECTOR? is redefined to be a procedure ; that returns false if its argument contains the distinguishing record ; value. EVAL is also redefined to use the new value of VECTOR?. ; Define the marker and redefine VECTOR? and EVAL. (define record-marker (list 'record-marker)) (define real-vector? vector?) (define (vector? x) (and (real-vector? x) (or (= 0 (vector-length x)) (not (eq? (vector-ref x 0) record-marker))))) ; This won't work if ENV is the interaction environment and someone has ; redefined LAMBDA there. (define eval (let ((real-eval eval)) (lambda (exp env) ((real-eval `(lambda (vector?) ,exp)) vector?)))) ; Definitions of the record procedures. (define (record? x) (and (real-vector? x) (< 0 (vector-length x)) (eq? (vector-ref x 0) record-marker))) (define (make-record size) (let ((new (make-vector (+ size 1)))) (vector-set! new 0 record-marker) new)) (define (record-ref record index) (vector-ref record (+ index 1))) (define (record-set! record index value) (vector-set! record (+ index 1) value)) |
Added artifacts/tests/run.scm version [957c7c2ae2].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | (use test) ;; (use (prefix pkts pkts:)) (use pkts (prefix dbi dbi:)) ;; (use trace)(trace sdat->alist pkt->alist) (if (file-exists? "queue.db")(delete-file "queue.db")) (test-begin "pkts and pkt archives") ;;====================================================================== ;; Basic pkt creation, parsing and conversion routines ;;====================================================================== (test-begin "basic packets") (test #f '(A "This is a packet") (let-values (((t v) (card->type/value "A This is a packet"))) (list t v))) (test #f "A A\nZ 664449e7299e0065a3e25c138ccef2df13ba291e" (let-values (((uuid res) (add-z-card '("A A")))) res)) (test #f '("CC C++" "D 1486332719.0" "a A" "b C")(sort (construct-sdat 'b "C" 'a "A" 'CC "C++" 'D 1486332719.0) string<=?)) (define pkt-example #f) (test #f "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" (let-values (((uuid res) (construct-pkt 'b "C" 'a "A" 'CC "C++" 'D 1486332719.0))) (set! pkt-example (cons uuid res)) res)) (test-end "basic packets") ;;====================================================================== ;; Sqlite and postgresql based queue of pkts ;;====================================================================== (test-begin "pkt queue") (define db #f) (test #f 'sqlite3 (let ((dbh (open-queue-db "." "queue.db"))) (set! db dbh) (dbi:db-dbtype dbh))) (test #f (cdr pkt-example) (begin (add-to-queue db (cdr pkt-example)(car pkt-example) 'basic #f 0) (lookup-by-uuid db (car pkt-example) 0))) (test #f (cdr pkt-example) (lookup-by-id db 1)) (test #f 1 (length (find-pkts db '(basic) '()))) (test-end "pkt queue") ;;====================================================================== ;; Process groups of pkts ;;====================================================================== (test-begin "lists of packets") (test #f '((apkt . #f) (id . 1) (group-id . 2) (uuid . 3) (parent . 4) (pkt-type . 5)) ;; ((id . 1) (group-id . 2) (uuid . 3) (parent . 4) (pkt-type . 5)) (dblst->dpkts '(1 2 3 4 5))) (test #f '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (processed . 0))) ;; '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) ;; '(((id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) (get-dpkts db '(basic) 0 #f)) (test #f '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (processed . 0))) ;; '(((apkt (Z . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (b . "C") (a . "A") (D . "1486332719.0") (C . " C++")) (id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) ;; '(((id . 1) (group-id . 0) (uuid . "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84") (parent . "") (pkt-type . "basic") (pkt . "CC C++\nD 1486332719.0\na A\nb C\nZ 263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) (get-not-processed-pkts db 0 'basic 1000 0)) (test-end "lists of packets") (test-begin "pkts as alists") (define pktspec '((posting . ((title . t) ;; NOTE: same as ((posting (title . t)(url . u)(blub . b)) ... (url . u) (blurb . b))) (comment . ((comment . c) (score . s))) (basic . ((b-field . b) (a-field . a))))) (define pktlst (find-pkts db '(basic) '())) (define dpkt (car pktlst)) (test #f "A" (get-value 'a-field dpkt pktspec)) (test #f "C" (alist-ref 'b-field (dpkt->alist dpkt pktspec))) (define basic-spec '((nada (foo . b)(bar . f))(basic (foo . f)(bar . b)))) (define test-pkt '((foo . "fooval")(bar . "barval"))) (let*-values (((u p) (alist->pkt test-pkt basic-spec ptype: 'basic)) ((apkt) (pkt->alist p)) ((bpkt) (pkt->alist p pktspec: basic-spec))) (test #f "fooval" (alist-ref 'f apkt)) (test #f "fooval" (alist-ref 'foo bpkt)) (test #f #f (alist-ref 'f bpkt))) (test-end "pkts as alists") (test-begin "descendents and ancestors") (define (get-uuid pkt)(alist-ref 'uuid pkt)) ;; add a child to 263e (let-values (((uuid pkt) (construct-pkt 'x "X" 'y "Y" 'P "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" 'D "1486332719.0"))) (add-to-queue db pkt uuid 'basic "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" 0)) (test #f '("263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" "818fe30988c9673441b8f203972a8bda6af682f8") (map (lambda (x)(alist-ref 'uuid x)) (get-descendents db 0 "263eb3b6193de7fe65b1ded5bcda513e8b4d6b84"))) (test #f '("263eb3b6193de7fe65b1ded5bcda513e8b4d6b84" "818fe30988c9673441b8f203972a8bda6af682f8") (map (lambda (x)(alist-ref 'uuid x)) (get-ancestors db 0 "818fe30988c9673441b8f203972a8bda6af682f8"))) (test-end "descendents and ancestors") (test-end "pkts and pkt archives") (test-begin "pktsdb") (define spec '((tests (testname n TEXT) (testpath p TEXT) (duration d INTEGER)))) ;; (define pktsdb (make-pktdb)) ;; (pktdb-pktsdb-spec-set! pktsdb spec) (define pktsdb #f) (test #f #t (dbi:database? (let ((pdb (pktsdb-open "test.db" spec))) (set! pktsdb pdb) (pktdb-conn pdb)))) ;; (pp (pktdb-pktspec pktsdb)) (test #f #t (pktsdb-add-record pktsdb 'tests '((testname . "test1")))) (pktsdb-close pktsdb) (test-end "pktsdb") |
Modified client.scm from [2a6738b25e] to [cc83111095].
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | + + + + + + + + + - - - + + + + + + + + + + - + - + - + - - + + + + - + - - - - - + + + + + + + - - + + + - - + + - - + - - - + + - - - - + + + - + - - + - - - - + - + + + + + + + + + + + + + + + + + + + + + + + | spiffy-request-vars uri-common intarweb directory-utils) (declare (unit client)) (declare (uses common)) (declare (uses db)) (declare (uses tasks)) ;; tasks are where stuff is maintained about what is running. (declare (uses commonmod)) (import commonmod) (module client * ) (import client) (include "common_records.scm") (include "db_records.scm") ;; client:get-signature (define (client:get-signature) (if *my-client-signature* *my-client-signature* (let ((sig (conc (get-host-name) " " (current-process-id)))) (set! *my-client-signature* sig) *my-client-signature*))) ;; Not currently used! But, I think it *should* be used!!! #;(define (client:logout serverdat) (let ((ok (and (socket? serverdat) (cdb:logout serverdat *toppath* (client:get-signature))))) ok)) |
Modified common.scm from [5559976353] to [2e8089abf6].
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | + + | format dot-locking csv-xml z3 udp ;; sql-de-lite hostinfo md5 message-digest typed-records directory-utils stack matchable regex posix (srfi 18) extras ;; tcp (prefix nanomsg nmsg:) (prefix sqlite3 sqlite3:) pkts (prefix dbi dbi:) ) (use posix-extras pathname-expand files) (declare (unit common)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") |
159 160 161 162 163 164 165 | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | - + - - | ;; (define *db-last-sync* 0) ;; last time the sync to megatest.db happened (define *db-sync-in-progress* #f) ;; if there is a sync in progress do not try to start another ;; (define *db-multi-sync-mutex* (make-mutex)) ;; protect access to *db-sync-in-progress*, *db-last-sync* ;; task db (define *task-db* #f) ;; (vector db path-to-db) (define *db-access-allowed* #t) ;; flag to allow access ;; (define *db-access-mutex* (make-mutex)) ;; moved to dbfile |
208 209 210 211 212 213 214 | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | - - | (define *launch-setup-mutex* (make-mutex)) ;; need to be able to call launch:setup often so mutex it and re-call the real deal only if *toppath* not set (define *homehost-mutex* (make-mutex)) ;; Miscellaneous (define *triggers-mutex* (make-mutex)) ;; block overlapping processing of triggers (define *numcpus-cache* (make-hash-table)) |
247 248 249 250 251 252 253 | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | - - - - - - - - - - - - - - - - - - - - - - - | (define *common:this-exe-name* (pathname-strip-directory *common:this-exe-fullpath*)) (define (common:get-sync-lock-filepath) (let* ((tmp-area (common:get-db-tmp-area)) (lockfile (conc tmp-area "/megatest.db.sync-lock"))) lockfile)) |
313 314 315 316 317 318 319 320 321 322 323 324 325 326 | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | + + + + + + - + - - + + + - - + + + + + + + + | ((abort) "ABORT") ((skip) "SKIP") (else "FAIL"))) (define (common:logpro-exit-code->test-status exit-code) (status-sym->string (common:logpro-exit-code->status-sym exit-code))) ;; (defstruct remote ;; transport to be used ;; http - use http-transport ;; http-read-cached - use http-transport for writes but in-mem cached for reads (rmode 'http) (hh-dat (let ((res (or (server:choose-server *toppath* 'homehost) (cons #f #f)))) (assert (pair? res)(conc "FATAL: hh-dat should be a pair, got "res)) res)) (server-url #f) ;; (server:check-if-running *toppath*) #f)) (server-id #f) |
406 407 408 409 410 411 412 413 | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | + + + + - - + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + | (define (common:version-db-delta) (- megatest-version (common:get-last-run-version-number))) (define (common:version-changed?) (not (equal? (common:get-last-run-version) (common:version-signature)))) ;; From 1.70 to 1.80, db's are compatible. (define (common:api-changed?) (let* ( |
518 519 520 521 522 523 524 | 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 | - + | ;; logs directory you wish to log-rotate. ;; (define (common:rotate-logs) (let* ((all-files (make-hash-table)) (stats (make-hash-table)) (inc-stat (lambda (key) (hash-table-set! stats key (+ (hash-table-ref/default stats key 0) 1)))) |
597 598 599 600 601 602 603 | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 | + - + - + | (debug:print-info 0 *default-log-port* "Deleted " (length files) " files from logs, keeping " max-allowed " files.")))))) ;;====================================================================== ;; Force a megatest cleanup-db if version is changed and skip-version-check not specified ;; Do NOT check if not on homehost! ;; (define (common:exit-on-version-changed) (if (and *toppath* ;; do nothing if *toppath* not yet provided |
624 625 626 627 628 629 630 | 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | - + - + | (print-call-chain (current-error-port)) (exit 1)) (common:cleanup-db dbstruct))) ((not (common:file-exists? mtconf)) (debug:print 0 *default-log-port* " megatest.config does not exist in this area. Cannot proceed with megatest version migration.") (exit 1)) ((not (common:file-exists? dbfile)) |
708 709 710 711 712 713 714 | 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | + + - - - - - - - - - + + + + + + + + + - - - | (if dat dat "")))) (define (common:alist-ref/default key alist default) (or (alist-ref key alist) default)) ;; moved into commonmod ;; |
944 945 946 947 948 949 950 | 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | + - + - + - + - - - + - - + + - - - | *db-cache-path* (if *toppath* ;; common:get-create-writeable-dir (handle-exceptions exn (begin (debug:print-error 0 *default-log-port* "Couldn't create path to " *db-cache-path* ", exn=" exn) (exit 1)) (let* ((toppath (common:real-path *toppath*)) |
1046 1047 1048 1049 1050 1051 1052 | 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | - - - - - - - - - - - - - - - - | ;;====================================================================== ;; '(print (string-intersperse (map cadr (hash-table-ref/default (read-config "megatest.config" \#f \#t) "disks" '"'"'("none" ""))) "\n"))' (define (common:get-disks #!key (configf #f)) (hash-table-ref/default (or configf (read-config "megatest.config" #f #t)) "disks" '("none" ""))) |
1343 1344 1345 1346 1347 1348 1349 | 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 | - + | #t #f)) (else (debug:print 0 *default-log-port* "ERROR: Bad server force setting " force-setting ", forcing server.") #t)))) ;; default to requiring server (if force-result (begin |
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 | 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 | + + + + + + + + + + + + + + + + + + + + | (begin (debug:print-error 0 *default-log-port* "command \"/bin/readlink -f " path "\" failed. exn=" exn) path) ;; just give up (with-input-from-pipe (conc "/bin/readlink -f " path) (lambda () (read-line))))) ;; for reasons I don't understand multiple calls to real-path in parallel threads ;; must be protected by mutexes ;; (define (common:real-path inpath) ;; (process:cmd-run-with-stderr->list "readlink" "-f" inpath)) ;; cmd . params) ;; (let-values ;; (((inp oup pid) (process "readlink" (list "-f" inpath)))) ;; (with-input-from-port inp ;; (let loop ((inl (read-line)) ;; (res #f)) ;; (print "inl=" inl) ;; (if (eof-object? inl) ;; (begin ;; (close-input-port inp) ;; (close-output-port oup) ;; ;; (process-wait pid) ;; res) ;; (loop (read-line) inl)))))) (with-input-from-pipe (conc "readlink -f " inpath) read-line)) ;;====================================================================== ;; returns *effective load* (not normalized) ;; (define (common:get-intercept onemin fivemin) (if (< onemin fivemin) ;; load is decreasing, just use the onemin load onemin |
1987 1988 1989 1990 1991 1992 1993 | 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 | + + + + + + + + + - - - - - - + + + + + + + + | (begin ;; found a host, return it (debug:print 0 *default-log-port* "INFO: Found host: " new-best " load: " load " last-used: " delta " seconds ago, with job-rate: " job-rate) (host-last-used-set! rec curr-time) new-best) (if (null? tal) #f (loop (car tal)(cdr tal) best-host))))))))) (define (common:wait-for-homehost-load maxnormload msg) (let loop ((start-time (current-seconds))) ;; we saw some instances of this being called before *toppath* was set. This might be an early setup race. This delay should help but it is impossible to test... (if (not *toppath*) (begin (debug:print 0 *default-log-port* "ERROR: common:wait-for-homehost-load called before *toppath* set.") (thread-sleep! 30) (if (< (- (current-seconds) start-time) 300) (loop start-time))))) (case (rmt:transport-mode) ((http) |
2216 2217 2218 2219 2220 2221 2222 | 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 | - - - - - - - - - - - - - - - - - - - - | (define (get-uname . params) (let* ((uname-res (process:cmd-run->list (conc "uname " (if (null? params) "-a" (car params))))) (uname #f)) (if (null? (car uname-res)) "unknown" (caar uname-res)))) |
2617 2618 2619 2620 2621 2622 2623 | 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | (conc "viewscreen " cmd)))) (debug:print-info 02 *default-log-port* "Running command: " fullcmd) (cond (with-vars (common:without-vars fullcmd)) (with-orig-env (common:with-orig-env fullcmd)) (else (common:without-vars fullcmd "MT_.*"))))) |
Modified commonmod.scm from [2570fcf4eb] to [ff27fc279a].
15 16 17 18 19 20 21 22 23 24 25 26 27 | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | + - - - - - + + + + + + + + + + + + + + + + + + + + + + | ;; ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit commonmod)) ;; (declare (uses debugprint)) (use srfi-69) (module commonmod * |
134 135 136 137 138 139 140 141 142 143 144 145 146 147 | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | #f ;; I don't really care why this failed (at least for now) (delete-file* fname))) ;;====================================================================== ;; misc conversion, data manipulation functions ;;====================================================================== ;;====================================================================== ;; return first command that exists, else #f ;; (define (common:which cmds) (if (null? cmds) #f (let loop ((hed (car cmds)) (tal (cdr cmds))) (let ((res (with-input-from-pipe (conc "which " hed) read-line))) (if (and (string? res) (file-exists? res)) res (if (null? tal) #f (loop (car tal)(cdr tal)))))))) (define (common:get-megatest-exe) (let* ((mtexe (or (get-environment-variable "MT_MEGATEST") (common:which '("megatest")) "megatest"))) (if (file-exists? mtexe) (realpath mtexe) mtexe))) (define (common:get-megatest-exe-dir) (let* ((mtexe (common:get-megatest-exe))) (pathname-directory mtexe))) ;; more generic and comprehensive version of get-megatest-exe ;; (define (common:get-mtexe) (let* ((mtpathdir (common:get-megatest-exe-dir))) (or (common:get-megatest-exe) (if mtpathdir (conc mtpathdir"/megatest") #f) "megatest"))) (define (common:get-megatest-exe-path) (let* ((mtpathdir (common:get-megatest-exe-dir))) (conc mtpathdir":"(get-environment-variable "PATH") ":."))) (define (realpath x) (resolve-pathname (pathname-expand (or x "/dev/null")) )) ;; if it looks like a number -> convert it to a number, else return it ;; (define (lazy-convert inval) (let* ((as-num (if (string? inval)(string->number inval) #f))) (or as-num inval))) ;; to '((a . 1)(b . 2)(c . "a silly thing")(d . "")) |
159 160 161 162 163 164 165 166 167 168 169 170 171 172 | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | (if convert (lazy-convert inval) inval)))) (else f)))) (filter (lambda (x) (not (string-match "^\\s*" x))) val-list)) '()))) (define (get-cpu-load) (let* ((load-info (with-input-from-file "/proc/loadavg" read-lines))) (map string->number (string-split load-info)))) (define *current-host-cores* #f) (define (get-current-host-cores) (or *current-host-cores* (let ((cpu-info (with-input-from-file "/proc/cpuinfo" read-lines))) (let loop ((lines cpu-info)) (if (null? lines) 1 ;; gotta be at least one! (let* ((inl (car lines)) (tail (cdr lines)) (parts (string-split inl))) (match parts (("cpu" "cores" ":" num) (string->number num)) (else (loop tail))))))))) (define (number-of-processes-running processname) (with-input-from-pipe (conc "ps -def | egrep \""processname"\" |wc -l") (lambda () (string->number (read-line))))) ;; get the normalized (i.e. load / numcpus) for *this* host ;; (define (get-normalized-cpu-load) (/ (get-cpu-load)(get-current-host-cores))) ;;====================================================================== ;; testsuite and area utilites ;;====================================================================== (define (get-testsuite-name toppath configdat) (or (lookup configdat "setup" "area-name") (lookup configdat "setup" "testsuite") |
206 207 208 209 210 211 212 213 214 215 216 217 | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ;; (define (get-cfg-areas cfgdat) (let ((adat (get-section cfgdat "areas"))) (map (lambda (entry) `(,(car entry) . ,(val->alist (cadr entry)))) adat))) ;;====================================================================== ;; time utils ;;====================================================================== (define (common:human-time) (time->string (seconds->local-time (current-seconds)) "%Y-%m-%d %H:%M:%S")) ;;====================================================================== ;; T I M E A N D D A T E ;;====================================================================== ;;====================================================================== ;; Convert strings like "5s 2h 3m" => 60x60x2 + 3x60 + 5 (define (common:hms-string->seconds tstr) (let ((parts (string-split-fields "\\w+" tstr)) (time-secs 0) ;; s=seconds, m=minutes, h=hours, d=days, M=months, y=years, w=weeks (trx (regexp "^(\\d+)([smhdMyw])$"))) (for-each (lambda (part) (let ((match (string-match trx part))) (if match (let ((val (string->number (cadr match))) (unt (caddr match))) (if val (set! time-secs (+ time-secs (* val (case (string->symbol unt) ((s) 1) ((m) 60) ;; minutes ((h) 3600) ((d) 86400) ((w) 604800) ((M) 2628000) ;; aproximately one month ((y) 31536000) (else 0))))))) (print "ERROR: can't parse timestring "tstr", component "part) ))) parts) time-secs)) (define (seconds->hr-min-sec secs) (let* ((hrs (quotient secs 3600)) (min (quotient (- secs (* hrs 3600)) 60)) (sec (- secs (* hrs 3600)(* min 60)))) (conc (if (> hrs 0)(conc hrs "hr ") "") (if (> min 0)(conc min "m ") "") sec "s"))) (define (seconds->time-string sec) (time->string (seconds->local-time sec) "%H:%M:%S")) (define (seconds->work-week/day-time sec) (time->string (seconds->local-time sec) "ww%V.%u %H:%M")) (define (seconds->work-week/day sec) (time->string (seconds->local-time sec) "ww%V.%u")) (define (seconds->year-work-week/day sec) (time->string (seconds->local-time sec) "%yww%V.%w")) (define (seconds->year-work-week/day-time sec) (time->string (seconds->local-time sec) "%Yww%V.%w %H:%M")) (define (seconds->year-week/day-time sec) (time->string (seconds->local-time sec) "%Yw%V.%w %H:%M")) (define (seconds->quarter sec) (case (string->number (time->string (seconds->local-time sec) "%m")) ((1 2 3) 1) ((4 5 6) 2) ((7 8 9) 3) ((10 11 12) 4) (else #f))) ;;====================================================================== ;; basic ISO8601 format (e.g. "2017-02-28 06:02:54") date time => Unix epoch ;; (define (common:date-time->seconds datetime) (local-time->seconds (string->time datetime "%Y-%m-%d %H:%M:%S"))) ;;====================================================================== ;; given span of seconds tstart to tend ;; find start time to mark and mark delta ;; (define (common:find-start-mark-and-mark-delta tstart tend) (let* ((deltat (- (max tend (+ tend 10)) tstart)) ;; can't handle runs of less than 4 seconds. Pad it to 10 seconds ... (result #f) (min 60) (hr (* 60 60)) (day (* 24 hr)) (yr (* 365 day)) ;; year (mo (/ yr 12)) (wk (* day 7))) (for-each (lambda (max-blks) (for-each (lambda (span) ;; 5 2 1 (if (not result) (for-each (lambda (timeunit timesym) ;; year month day hr min sec (if (not result) (let* ((time-blk (* span timeunit)) (num-blks (quotient deltat time-blk))) (if (and (> num-blks 4)(< num-blks max-blks)) (let ((first (* (quotient tstart time-blk) time-blk))) (set! result (list span timeunit time-blk first timesym)) ))))) (list yr mo wk day hr min 1) '( y mo w d h m s)))) (list 8 6 5 2 1))) '(5 10 15 20 30 40 50 500)) (if values (apply values result) (values 0 day 1 0 'd)))) ;;====================================================================== ;; given x y lim return the cron expansion ;; (define (common:expand-cron-slash x y lim) (let loop ((curr x) (res `())) (if (< curr lim) (loop (+ curr y) (cons curr res)) (reverse res)))) ;;====================================================================== ;; expand a complex cron string to a list of cron strings ;; ;; x/y => x, x+y, x+2y, x+3y while x+Ny<max_for_field ;; a,b,c => a, b ,c ;; ;; NOTE: with flatten a lot of the crud below can be factored down. ;; (define (common:cron-expand cron-str) (if (list? cron-str) (flatten (fold (lambda (x res) (if (list? x) (let ((newres (map common:cron-expand x))) (append x newres)) (cons x res))) '() cron-str)) ;; (map common:cron-expand cron-str)) (let ((cron-items (string-split cron-str)) (slash-rx (regexp "(\\d+)/(\\d+)")) (comma-rx (regexp ".*,.*")) (max-vals '((min . 60) (hour . 24) (dayofmonth . 28) ;;; BUG!!!! This will be a bug for some combinations (month . 12) (dayofweek . 7)))) (if (< (length cron-items) 5) ;; bad spec cron-str ;; `(,cron-str) ;; just return the string, something downstream will fix it (let loop ((hed (car cron-items)) (tal (cdr cron-items)) (type 'min) (type-tal '(hour dayofmonth month dayofweek)) (res '())) (regex-case hed (slash-rx ( _ base incr ) (let* ((basen (string->number base)) (incrn (string->number incr)) (expanded-vals (common:expand-cron-slash basen incrn (alist-ref type max-vals))) (new-list-crons (fold (lambda (x myres) (cons (conc (if (null? res) "" (conc (string-intersperse res " ") " ")) x " " (string-intersperse tal " ")) myres)) '() expanded-vals))) ;; (print "new-list-crons: " new-list-crons) ;; (fold (lambda (x res) ;; (if (list? x) ;; (let ((newres (map common:cron-expand x))) ;; (append x newres)) ;; (cons x res))) ;; '() (flatten (map common:cron-expand new-list-crons)))) ;; (map common:cron-expand (map common:cron-expand new-list-crons)))) (else (if (null? tal) cron-str (loop (car tal)(cdr tal)(car type-tal)(cdr type-tal)(append res (list hed))))))))))) ;;====================================================================== ;; given a cron string and the last time event was processed return #t to run or #f to not run ;; ;; min hour dayofmonth month dayofweek ;; 0-59 0-23 1-31 1-12 0-6 ### NOTE: dayofweek does not include 7 ;; ;; #t => yes, run the job ;; #f => no, do not run the job ;; (define (common:cron-event cron-str now-seconds-in last-done) ;; ref-seconds = #f is NOW. (let* ((cron-items (map string->number (string-split cron-str))) (now-seconds (or now-seconds-in (current-seconds))) (now-time (seconds->local-time now-seconds)) (last-done-time (seconds->local-time last-done)) (all-times (make-hash-table))) ;; (print "cron-items: " cron-items "(length cron-items): " (length cron-items)) (if (not (eq? (length cron-items) 5)) ;; don't even try to figure out junk strings #f (match-let ((( cmin chour cdayofmonth cmonth cdayofweek) cron-items) ;; 0 1 2 3 4 5 6 ((nsec nmin nhour ndayofmonth nmonth nyr ndayofweek n7 n8 n9) (vector->list now-time)) ((lsec lmin lhour ldayofmonth lmonth lyr ldayofweek l7 l8 l9) (vector->list last-done-time))) ;; create all possible time slots ;; remove invalid slots due to (for example) day of week ;; get the start and end entries for the ref-seconds (current) time ;; if last-done > ref-seconds => this is an ERROR! ;; does the last-done time fall in the legit region? ;; yes => #f do not run again this command ;; no => #t ok to run the command (for-each ;; month (lambda (month) (for-each ;; dayofmonth (lambda (dom) (for-each (lambda (hr) ;; hour (for-each (lambda (minute) ;; minute (let ((copy-now (apply vector (vector->list now-time)))) (vector-set! copy-now 0 0) ;; force seconds to zero (vector-set! copy-now 1 minute) (vector-set! copy-now 2 hr) (vector-set! copy-now 3 dom) ;; dom is already corrected for zero referenced (vector-set! copy-now 4 month) (let* ((copy-now-secs (local-time->seconds copy-now)) (new-copy (seconds->local-time copy-now-secs))) ;; remake the time vector (if (or (not cdayofweek) (equal? (vector-ref new-copy 6) cdayofweek)) ;; if the day is specified and a match OR if the day is NOT specified (if (or (not cdayofmonth) (equal? (vector-ref new-copy 3) (+ 1 cdayofmonth))) ;; if the month is specified and a match OR if the month is NOT specified (hash-table-set! all-times copy-now-secs new-copy)))))) (if cmin `(,cmin) ;; if given cmin, have to use it (list (- nmin 1) nmin (+ nmin 1))))) ;; minute (if chour `(,chour) (list (- nhour 1) nhour (+ nhour 1))))) ;; hour (if cdayofmonth `(,cdayofmonth) (list (- ndayofmonth 1) ndayofmonth (+ ndayofmonth 1))))) (if cmonth `(,cmonth) (list (- nmonth 1) nmonth (+ nmonth 1)))) (let ((before #f) (is-in #f)) (for-each (lambda (moment) (if (and before (<= before now-seconds) (>= moment now-seconds)) (begin ;; (print) ;; (print "Before: " (time->string (seconds->local-time before))) ;; (print "Now: " (time->string (seconds->local-time now-seconds))) ;; (print "After: " (time->string (seconds->local-time moment))) ;; (print "Last: " (time->string (seconds->local-time last-done))) (if (< last-done before) (set! is-in before)) )) (set! before moment)) (sort (hash-table-keys all-times) <)) is-in))))) (define (common:extended-cron cron-str now-seconds-in last-done) (let ((expanded-cron (common:cron-expand cron-str))) (if (string? expanded-cron) (common:cron-event expanded-cron now-seconds-in last-done) (let loop ((hed (car expanded-cron)) (tal (cdr expanded-cron))) (if (common:cron-event hed now-seconds-in last-done) #t (if (null? tal) #f (loop (car tal)(cdr tal)))))))) ;;====================================================================== ;; misc stuff ;;====================================================================== (define (common:get-signature str) (message-digest-string (md5-primitive) str)) |
Modified configf.scm from [6390e213ef] to [1768130e73].
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | + + + | ;;====================================================================== (use regex regex-case matchable) ;; directory-utils) (declare (unit configf)) (declare (uses process)) (declare (uses env)) (declare (uses keys)) (declare (uses commonmod)) (declare (uses commonmod.import)) (import commonmod) (include "common_records.scm") ;; return list (path fullpath configname) (define (find-config configname #!key (toppath #f)) (if toppath (let ((cfname (conc toppath "/" configname))) |
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | + + - + | ;; read a line and process any #{ ... } constructs (define configf:var-expand-regex (regexp "^(.*)#\\{(scheme|system|shell|getenv|get|runconfigs-get|rget|scm|sh|rp|gv|g|mtrah)\\s+([^\\}\\{]*)\\}(.*)")) (define (configf:system ht cmd) (system cmd) ) (define configf:imports "(import commonmod)") (define (configf:process-line l ht allow-system #!key (linenum #f)) (let loop ((res l)) (if (string? res) (let ((matchdat (string-search configf:var-expand-regex res))) (if matchdat (let* ((prestr (list-ref matchdat 1)) (cmdtype (list-ref matchdat 2)) ;; eval, system, shell, getenv (cmd (list-ref matchdat 3)) (poststr (list-ref matchdat 4)) (result #f) (start-time (current-seconds)) (cmdsym (string->symbol cmdtype)) (fullcmd (case cmdsym |
Modified dashboard-context-menu.scm from [83fc3e6c83] to [9827592e3b].
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | + + + | (use canvas-draw) (use srfi-1 posix regex regex-case srfi-69) (use (prefix sqlite3 sqlite3:)) (declare (unit dashboard-context-menu)) (declare (uses common)) (declare (uses commonmod)) (declare (uses db)) (declare (uses gutils)) (declare (uses rmt)) (declare (uses ezsteps)) ;; (declare (uses sdb)) ;; (declare (uses filedb)) (declare (uses subrun)) (include "common_records.scm") (include "db_records.scm") (include "run_records.scm") (import commonmod) (define (dboard:launch-testpanel run-id test-id) (let* ((dboardexe (common:find-local-megatest "dashboard")) (cmd (conc dboardexe " -test " run-id "," test-id " &"))) (system cmd))) |
Modified dashboard-guimonitor.scm from [60455a8a12] to [76c7fb97a3].
32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | + + | (import (prefix sqlite3 sqlite3:)) (declare (unit dashboard-guimonitor)) (declare (uses common)) (declare (uses keys)) (declare (uses db)) (declare (uses tasks)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (include "db_records.scm") (include "run_records.scm") (include "task_records.scm") (define (control-panel db tdb keys) |
Modified dashboard-tests.scm from [b934cba7e8] to [124658aa85].
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | + + + | (use canvas-draw) (use srfi-1 posix regex regex-case srfi-69) (use (prefix sqlite3 sqlite3:)) (declare (unit dashboard-tests)) (declare (uses common)) (declare (uses commonmod)) (declare (uses db)) (declare (uses gutils)) (declare (uses rmt)) (declare (uses ezsteps)) ;; (declare (uses sdb)) ;; (declare (uses filedb)) (declare (uses subrun)) (import commonmod) (include "common_records.scm") (include "db_records.scm") (include "run_records.scm") ;;====================================================================== ;; C O M M O N |
457 458 459 460 461 462 463 | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | - + - | ;;====================================================================== ;; ;;====================================================================== (define (dashboard-tests:examine-test run-id test-id) ;; run-id run-key origtest) (let* ((db-path (db:dbfile-path)) ;; (conc (configf:lookup *configdat* "setup" "linktree") "/db/" run-id ".db")) |
Added dashboard-transport-mode.scm.template version [c59d475c4f].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | + + + + + + + + + + + + + + + + + + + + + + | ;;====================================================================== ;; set up transport, db cache and sync methods ;; ;; sync-method: 'original, 'attach or 'none ;; cache-method: 'tmp, 'inmem or 'none ;; rmt:transport-mode: 'http, 'tcp, 'nfs ;; ;; NOTE: NOT ALL COMBINATIONS WORK ;; ;;====================================================================== ;; uncomment this block to test without tcp or inmem ;; (dbfile:sync-method 'none) ;; (dbfile:cache-method 'none) ;; (rmt:transport-mode 'nfs) ;; uncomment this block to test with tcp and inmem (dbfile:sync-method 'original) (dbfile:cache-method 'inmem) (rmt:transport-mode 'tcp) |
Modified dashboard.scm from [4ad343f07e] to [97180e20b9].
42 43 44 45 46 47 48 | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | + + - + + + + + + + + + + | (declare (uses dashboard-tests)) (declare (uses tree)) (declare (uses dcommon)) (declare (uses dashboard-context-menu)) (declare (uses vg)) (declare (uses subrun)) (declare (uses mt)) (declare (uses dbmod)) ;; (declare (uses dbmemmod)) |
403 404 405 406 407 408 409 | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + | (define (dboard:runsdat-make-init) (make-dboard:runsdat runs-index: (make-hash-table) tests-index: (make-hash-table) matrix-dat: (make-sparse-array))) ;; duplicated in dcommon.scm ;; |
1074 1075 1076 1077 1078 1079 1080 | 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 | - + | ;; optimized to get runs constrained by what is visible on the screen ;; - not appropriate for where all the runs are needed ;; (define (update-buttons tabdat uidat numruns numtests) (let* ((runs (if (> (length (dboard:tabdat-allruns tabdat)) numruns) (take-right (dboard:tabdat-allruns tabdat) numruns) |
Modified db.scm from [e18bcc992d] to [fad48edea3].
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | + + + + + + + + + + + + | ;;====================================================================== ;; Database access ;;====================================================================== ;; dbstruct vector containing all the relevant dbs like main.db, megatest.db, run.db etc (declare (unit db)) (declare (uses common)) (declare (uses debugprint)) (declare (uses dbmod)) (declare (uses dbfile)) (declare (uses keys)) (declare (uses ods)) (declare (uses client)) (declare (uses mt)) (declare (uses commonmod)) (import commonmod) (use (srfi 18) extras tcp stack (prefix sqlite3 sqlite3:) srfi-1 posix |
42 43 44 45 46 47 48 | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | - - - - - - - - - - + + + + + + + + - - - - - - - - - | format dot-locking z3 typed-records matchable files) |
131 132 133 134 135 136 137 138 139 140 141 142 143 144 | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | (define (db:setup do-sync) (assert *toppath* "FATAL: db:setup called before launch:setup has been run.") (let* ((tmpdir (common:get-db-tmp-area))) (if (not *dbstruct-dbs*) (dbfile:setup do-sync *toppath* tmpdir) *dbstruct-dbs*))) ;; moved from dbfile ;; ;; ADD run-id SUPPORT ;; (define (db:create-all-triggers dbstruct) (db:with-db dbstruct #f #f (lambda (dbdat db) (db:create-triggers db)))) (define (db:create-triggers db) (for-each (lambda (key) (sqlite3:execute db (cadr key))) db:trigger-list)) (define (db:drop-all-triggers dbstruct) (db:with-db dbstruct #f #f (lambda (dbdat db) (db:drop-triggers db)))) (define (db:have-incompletes? dbstruct run-id ovr-deadtime) (let* ((incompleted '()) (oldlaunched '()) (toplevels '()) ;; (deadtime-str (configf:lookup *configdat* "setup" "deadtime")) (deadtime (or ovr-deadtime 72000))) ;; twenty hours (db:with-db dbstruct run-id #f (lambda (dbdat db) ;; in RUNNING or REMOTEHOSTSTART for more than 10 minutes ;; ;; HOWEVER: this code in run:test seems to work fine ;; (> (- (current-seconds)(+ (db:test-get-event_time testdat) ;; (db:test-get-run_duration testdat))) ;; 600) ;; (db:delay-if-busy dbdat) (sqlite3:for-each-row (lambda (test-id run-dir uname testname item-path) (if (and (equal? uname "n/a") (equal? item-path "")) ;; this is a toplevel test ;; what to do with toplevel? call rollup? (begin (set! toplevels (cons (list test-id run-dir uname testname item-path run-id) toplevels))) ;; (print-info "Found old toplevel test in RUNNING state, test-id=" test-id)) (set! incompleted (cons (list test-id run-dir uname testname item-path run-id) incompleted)))) (db:get-cache-stmth dbdat db "SELECT id,rundir,uname,testname,item_path FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > (run_duration + ?) AND state IN ('RUNNING','REMOTEHOSTSTART');") run-id deadtime) ;; in LAUNCHED for more than one day. Could be long due to job queues TODO/BUG: Need override for this in config ;; ;; (db:delay-if-busy dbdat) (sqlite3:for-each-row (lambda (test-id run-dir uname testname item-path) (if (and (equal? uname "n/a") (equal? item-path "")) ;; this is a toplevel test ;; what to do with toplevel? call rollup? (set! toplevels (cons (list test-id run-dir uname testname item-path run-id) toplevels)) (set! oldlaunched (cons (list test-id run-dir uname testname item-path run-id) oldlaunched)))) (db:get-cache-stmth dbdat db "SELECT id,rundir,uname,testname,item_path FROM tests WHERE run_id=? AND (strftime('%s','now') - event_time) > 86400 AND state IN ('LAUNCHED');") run-id) ;; (print-info "Found " (length oldlaunched) " old LAUNCHED items, " (length toplevels) " old LAUNCHED toplevel tests and " (length incompleted) " tests marked RUNNING but apparently dead.") (if (and (null? incompleted) (null? oldlaunched) (null? toplevels)) #f #t))))) ;; looks up subdb and returns it, if not found then set up ;; and then return it. ;; #;(define (db:get-db dbstruct run-id) (let* ((res (dbfile:get-subdb dbstruct run-id))) (if res |
357 358 359 360 361 362 363 | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | + - - - + + + + | ;; return the target db handle so it can be used ;; (define (db:cache-for-read-only source target #!key (use-last-update #f)) (if (and (hash-table-ref/default *global-db-store* target #f) (>= (file-modification-time target)(file-modification-time source))) (hash-table-ref *global-db-store* target) (let* ((toppath (launch:setup)) (targ-db-last-mod (db:get-sqlite3-mod-time target)) |
403 404 405 406 407 408 409 | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 | - - - + + + + + + + + + + + + - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + | ;; megatest-db ;; (conc cache-dir "/" fname) ;; use-last-update: #t))) ;; (thread-start! th1) ;; (apply proc cache-db params) ;; )))) |
454 455 456 457 458 459 460 | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 | + - + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - + + + + + - - + + - - - - - - - - - - - - - - + - - - - - - - - - + + + + + + + + + + - - - - - - - + + + + + - - - - - + + + + - - - - - - - + + + + + + + + - - - - - - - + + + + + + - - - - - - - + + + + + + + + + + + - - + - - - - - - - - - + + + + + + + + + + - - - - + + - - - - + - - + - - - - + + | fname", delta: " (- time1 time2) " seconds, reason: "(cdr do-cp)) (db:lock-and-delta-sync no-sync-db dbstruct fname runid (db:get-keys dbstruct) db:initialize-main-db) (hash-table-set! sync-durations (conc fname".db") (- (current-milliseconds) start-time))) (debug:print-info 3 *default-log-port* "skipping sync. " file " is up to date") ))) dbfiles) ;; WHY does the dbdat need to be added back? |
838 839 840 841 842 843 844 | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | - + + - + + | (sqlite3:execute db "CREATE TABLE IF NOT EXISTS test_rundat ( id INTEGER PRIMARY KEY, test_id INTEGER, update_time TIMESTAMP, cpuload INTEGER DEFAULT -1, diskfree INTEGER DEFAULT -1, diskusage INTGER DEFAULT -1, |
884 885 886 887 888 889 890 891 892 893 894 895 896 897 | 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 | + | db (conc "SELECT d.id,d.archive_area_name,disk_path,last_df,last_df_time FROM archive_disks AS d INNER JOIN archive_blocks AS b ON d.id=b.archive_disk_id WHERE b.id IN (" (string-intersperse (map conc res) ",") ") AND last_df > ?;") dneeded)) ;; BUG: Verfify this is really needed (dbfile:add-dbdat dbstruct #f dbdat) blocks)) ;; returns id of the record, register a disk allocated to archiving and record it's last known ;; available space ;; (define (db:archive-register-disk dbstruct bdisk-name bdisk-path df) |
988 989 990 991 992 993 994 | 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ;; D B U T I L S ;;====================================================================== ;;====================================================================== ;; M A I N T E N A N C E ;;====================================================================== |
1084 1085 1086 1087 1088 1089 1090 | 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 | - + - + - + | (debug:print-info 4 *default-log-port* "running-deadtime = " running-deadtime) (debug:print-info 4 *default-log-port* "deadtime-trim = " deadtime-trim) (db:with-db dbstruct run-id #f (lambda (dbdat db) (let* ((stmth1 (db:get-cache-stmth |
1363 1364 1365 1366 1367 1368 1369 | 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | - + - + - + - - + + - - - - - - + - - - - + + + - - - - + - - + + - - - - - - - - - + - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + | ;; (begin ;; (debug:print-info 4 *default-log-port* "launch throttle factor=" *global-delta*) ;; (set! *last-global-delta-printed* *global-delta*))) (define (db:set-var dbstruct var val) (db:with-db dbstruct #f #t (lambda (dbdat db) |
1940 1941 1942 1943 1944 1945 1946 | 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 | + - - - - - - - - - + + + + + + + + + | (if offset (conc " OFFSET " offset) "") ";")) (debug:print-info 4 *default-log-port* "runs:get-runs-by-patt qry=" qry-str " " runnamepatt) ;(print "runs:get-runs-by-patt qry=" qry-str " " runnamepatt) (vector header (reverse (db:with-db |
2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 | 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 | + + + + + - - - + + - + - - + + + - - + + + + + + + + + + + + + + + + | (db:with-db dbstruct #f #f (lambda (dbdat db) (if msg (sqlite3:execute db "UPDATE runs SET status=?,comment=? WHERE id=?;" status msg run-id) (sqlite3:execute db "UPDATE runs SET status=? WHERE id=?;" status run-id))))) (define (db:set-run-state-status-db dbdat db run-id state status ) (sqlite3:execute (db:get-cache-stmth dbdat db "UPDATE runs SET status=?,state=? WHERE id=?;") status state run-id)) (define (db:set-run-state-status dbstruct run-id state status ) (db:with-db dbstruct #f #f (lambda (dbdat db) |
2304 2305 2306 2307 2308 2309 2310 | 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 | - - + + | (db:with-db dbstruct run-id #f (lambda (dbdat db) (sqlite3:for-each-row (lambda (run-id testname item-path state status) ;; id,run_id,testname,state,status,event_time,host,cpuload,diskfree,uname,rundir,item_path,run_duration,final_logf,comment (set! res (vector test-id run-id testname state status -1 "" -1 -1 "" "-" item-path -1 "-" "-"))) db |
2400 2401 2402 2403 2404 2405 2406 | 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 | - + - + + + - - - - - - - - - - - - + + + + + + + + + + + + + - + | ;; ;; NB// Ultimately this will be deprecated in deference to mt:test-set-state-status-by-id ;; ;; NOTE: run-id is not used ;; ;; (define (db:test-set-state-status dbstruct run-id test-id newstate newstatus newcomment) (db:with-db dbstruct |
2457 2458 2459 2460 2461 2462 2463 | 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 | - + - + | ;; "SELECT count(id) FROM tests WHERE state in ('RUNNING','LAUNCHED','REMOTEHOSTSTART') AND run_id=? LIMIT 1;" "SELECT count(id) FROM tests WHERE state in ('RUNNING','LAUNCHED','REMOTEHOSTSTART') AND run_id=?;")) ;; ) (db:with-db dbstruct run-id #f (lambda (dbdat db) |
2670 2671 2672 2673 2674 2675 2676 | 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 | - + - - + + + + + + + + + + + + + + + + + + | (let* ((run-ids (db:get-all-run-ids mtdb))) (for-each (lambda (run-id) (let ((testrecs (db:get-all-tests-info-by-run-id mtdb run-id))) (db:prep-megatest.db-adj-test-ids (dbr:dbdat-dbh mtdb) run-id testrecs))) run-ids))) |
2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 | 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 | + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + | ;; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (set! res (cons (apply vector a b) res))) db (conc "SELECT " db:test-record-qry-selector " FROM tests WHERE id in (" (string-intersperse (map conc test-ids) ",") ");")) res)))) ;; try every second until tries times proc ;; (define (db:keep-trying-until-true proc params tries) (let* ((res (apply proc params))) (if res res (if (> tries 0) (begin (thread-sleep! 1) (db:keep-trying-until-true proc params (- tries 1))) (begin (debug:print-info 0 *default-log-port* "proc never returned true, params="params) #f))))) (define (db:get-test-info dbstruct run-id test-name item-path) (db:with-db dbstruct run-id #f (lambda (dbdat db) (db:get-test-info-db db run-id test-name item-path)))) (define (db:get-test-info-db db run-id test-name item-path) |
2841 2842 2843 2844 2845 2846 2847 | 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 | - + | (define (db:get-data-info-by-id dbstruct run-id test-data-id) (let* ((stmt "SELECT id,test_id, category, variable, value, expected, tol, units, comment, status, type, last_update FROM test_data WHERE id=? ORDER BY id ASC;")) ;; event_time DESC,id ASC; (db:with-db dbstruct run-id #f (lambda (dbdat db) |
3166 3167 3168 3169 3170 3171 3172 | 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 | + + - + + - + + + - + - - - - + + + + + + - - - - - + + + + + - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - + + + + + + + - + + + + + - - + + - + - - - - - - - - - + + + + + + - - - + + - + - | ;; if test-name is an integer work off that as test-id instead of test-name test-path ;; (define (db:set-state-status-and-roll-up-items dbstruct run-id test-name item-path state status comment) ;; establish info on incoming test followed by info on top level test ;; BBnote - for mode itemwait, linkage between upstream test & matching item status is propagated to run queue in db:prereqs-not-met (let* ((testdat (if (number? test-name) (db:get-test-info-by-id dbstruct run-id test-name) ;; test-name is actually a test-id (db:keep-trying-until-true ;; in our threaded stuff this call could happen before the test is registered (maybe?) db:get-test-info |
4425 4426 4427 4428 4429 4430 4431 | 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 | - | (sync-stale-seconds (configf:lookup-number *configdat* "server" "sync-stale-seconds" default: 300)) (debug-mode (debug:debug-mode 1)) (last-time (current-seconds)) ;; last time through the sync loop (no-sync-db (db:open-no-sync-db)) (sync-duration 0) ;; run time of the sync in milliseconds (tmp-area (common:get-db-tmp-area))) ;; Sync moved to http-transport keep-running loop |
4468 4469 4470 4471 4472 4473 4474 | 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 | - | (sync-stale-seconds (configf:lookup-number *configdat* "server" "sync-stale-seconds" default: 300)) (debug-mode (debug:debug-mode 1)) (last-time (current-seconds)) (no-sync-db (db:open-no-sync-db)) (stmt-cache #f) ;; (dbr:dbstruct-stmt-cache dbstruct)) (sync-duration 0) ;; run time of the sync in milliseconds (subdbs (hash-table-values (dbr:dbstruct-subdbs dbstruct)))) |
4610 4611 4612 4613 4614 4615 4616 4617 | 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 | + + + - + + + - + | (let ((db (cdr *task-db*))) (if (sqlite3:database? db) (begin (sqlite3:interrupt! db) (sqlite3:finalize! db #t) ;; (vector-set! *task-db* 0 #f) (set! *task-db* #f))))) (if (and *no-sync-db* (sqlite3:database? *no-sync-db*)) (sqlite3:finalize! *no-sync-db* #t)) (if (and (not (args:get-arg "-server")) |
Modified dbfile.scm from [d24edd08a7] to [ddb0c93f5d].
15 16 17 18 19 20 21 | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | - + + + + + - + + + + + + + + + + + + + + + + + + + + + | ;; ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit dbfile)) |
90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | + + + | (define *db-sync-in-progress* #f) (define *db-with-db-mutex* (make-mutex)) (define *max-api-process-requests* 0) (define *api-process-request-count* 0) (define *db-write-access* #t) (define *db-last-sync* 0) ;; last time the sync to megatest.db happened (define *db-multi-sync-mutex* (make-mutex)) ;; protect access to *db-sync-in-progress*, *db-last-sync* (define *db-last-access* (current-seconds)) (define *db-transaction-mutex* (make-mutex)) (define (db:generic-error-printout exn . message) (print-call-chain (current-error-port)) (apply dbfile:print-err message) (dbfile:print-err ", error: " ((condition-property-accessor 'exn 'message) exn) ", arguments: " ((condition-property-accessor 'exn 'arguments) exn) |
155 156 157 158 159 160 161 | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - + - - + - - - + + + + - + - - + + + + + + | subdbs) #t ) #f ) ) |
324 325 326 327 328 329 330 | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | - + - + - + - + | (exit 1)) (define (dbfile:print-err . params) (with-output-to-port (current-error-port) (lambda () (apply print params)))) |
400 401 402 403 404 405 406 | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | - + - - - + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | (let* ((backupfname (conc fname"-"(current-process-id)".bak")) (cmd (conc "cp "fname" "backupfname";mv "fname" "(conc fname ".delme;") "cp "backupfname" "fname))) (dbfile:print-err "WARNING: attempting recovery of file "fname" by running commands:\n" " "cmd) (system cmd))) |
442 443 444 445 446 447 448 449 450 451 452 453 454 455 | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | (let ((newres (if (string? res) (string->number res) #f))) (if newres newres res)) res))) (define (db:extract-time-identifier instr) (let ((tokens (string-split instr "+"))) (match tokens ((t i)(cons (string->number t) i)) ((t) (cons (string->number t) #f)) (else (assert #f "FATAL: db:extract-time-identifier handed bad data "instr))))) ;; transaction protected lock aquisition ;; either: ;; fails returns (#f . lock-creation-time) ;; succeeds (returns (#t . lock-creation-time) ;; use (db:no-sync-del! db keyname) to release the lock ;; (define (db:no-sync-get-lock-with-id db keyname identifier) (sqlite3:with-transaction db (lambda () (condition-case (let* ((curr-val (db:no-sync-get/default db keyname #f))) (if curr-val (match (db:extract-time-identifier curr-val) ((timestamp ident) (if (equal? ident identifier) #t ;; this *is* my lock #f)) ;; nope, not my lock (else #f)) ;; nope, not my lock (let ((lock-value (if identifier (conc (current-seconds)"+"identifier) (current-seconds)))) (sqlite3:execute db "INSERT OR REPLACE INTO no_sync_metadat (var,val) VALUES(?,?);" keyname lock-value) #t))) (exn (io-error) (dbfile:print-err "ERROR: i/o error with no-sync db. Check permissions, disk space etc. and try again.")) (exn (corrupt) (dbfile:print-err "ERROR: database no-sync db is corrupt. Repair it to proceed.")) (exn (busy) (dbfile:print-err "ERROR: database no-sync db is locked. Try copying to another location, remove original and copy back.")) (exn (permission)(dbfile:print-err "ERROR: database no-sync db has some permissions problem.")) (exn () ;; (status done) ;; I don't know how to detect status done but no data! (dbfile:print-err "ERROR: Unknown error with database no-sync db message: exn="(condition->list exn)", \n" ((condition-property-accessor 'exn 'message) exn)) #f))))) ;; transaction protected lock aquisition ;; either: ;; fails returns (#f . lock-creation-time) ;; succeeds (returns (#t . lock-creation-time) ;; use (db:no-sync-del! db keyname) to release the lock ;; |
511 512 513 514 515 516 517 | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | + - + | (dbfile:print-err "INFO: db:lock-and-delta-sync copying db "runid" at "(current-seconds)) (set! *db-sync-in-progress* #t) (db:sync-touched dbstruct runid keys dbinit) (set! *db-sync-in-progress* #f) (delete-file* lock-file) #t) (begin (if (common:low-noise-print 120 (conc "no lock "from-db-file)) |
554 555 556 557 558 559 560 | 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 | - + | (tmpdbfile (dbr:subdb-tmpdbfile subdb)) (mtdb (dbr:subdb-mtdbdat subdb)) (tmpdb (db:open-db dbstruct run-id dbinit)) ;; sqlite3-db tmpdbfile #f)) (start-t (current-seconds))) (mutex-lock! *db-multi-sync-mutex*) (let ((update_info (cons "last_update" (if force-sync 0 *db-last-sync*) ))) (mutex-unlock! *db-multi-sync-mutex*) |
617 618 619 620 621 622 623 | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 | - - + + | '("comment" #f) '("status" #f) '("type" #f) '("last_update" #f)))) ;; needs db to get keys, this is for syncing all tables ;; |
656 657 658 659 660 661 662 | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 | - + + + + + + + + + + + + + + + + - - + + | '("owner" #f) '("description" #f) '("reviewed" #f) '("iterated" #f) '("avg_runtime" #f) '("avg_disk" #f) '("tags" #f) |
868 869 870 871 872 873 874 | 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 | - + + | (append (list todb) slave-dbs) ) ) ) tbls) (let* ((runtime (- (current-milliseconds) start-time)) (should-print (or ;; (debug:debug-mode 12) |
913 914 915 916 917 918 919 | 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 | - - - - - - - - - - - - - - - - - - - - | END;" ) (list "update_test_data_trigger" "CREATE TRIGGER IF NOT EXISTS update_test_data_trigger AFTER UPDATE ON test_data FOR EACH ROW BEGIN UPDATE test_data SET last_update=(strftime('%s','now')) WHERE id=old.id; END;" ))) |
980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 | 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - - - + + + + + + + + - + + - - - + + + + + + - - - - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + | ;;====================================================================== ;; call with dbinit=db:initialize-main-db ;; (define (db:open-db dbstruct run-id dbinit) ;; (mutex-lock! *db-open-mutex*) (let* ((dbdat (dbfile:open-db dbstruct run-id dbinit))) #;(case (rmt:transport-mode) ((http) (dbfile:open-db dbstruct run-id dbinit)) ((tcp) (dbmod:open-db dbstruct run-id dbinit)) (else (assert #f "FATAL: rmt:transport-node not correct value"(rmt:transport-mode)))) (set! *db-write-access* (not (dbr:dbdat-read-only dbdat))) ;; (mutex-unlock! *db-open-mutex*) dbdat)) (define dbfile:db-init-proc (make-parameter #f)) ;; in xmaxima this gives a curve close to what I want: ;; plot2d ((exp(x/1.2)-1)/300, [x, 0, 10])$ ;; plot2d ((exp(x/1.5)-1)/40, [x, 0, 10])$ ;; plot2d ((exp(x/5)-1)/40, [x, 0, 20])$ (define (dbfile:droop x) (/ (- (exp (/ x 5)) 1) 40)) ;; (* numqrys (/ 1 (qif-slope)))) ;; create a dropping near the db file in a qif dir ;; use count of such files to gate queries (queries in flight) ;; (define (dbfile:wait-for-qif fname run-id params) (let* ((thedir (pathname-directory fname)) (dbnum (dbfile:run-id->dbnum run-id)) (destdir (conc thedir"/qif-"dbnum)) (uniqn (get-area-path-signature (conc dbnum params))) (crumbn (conc destdir"/"(current-seconds)"-"uniqn"."(current-process-id)))) (if (not (file-exists? destdir))(create-directory (conc destdir"/attic") #t)) (let loop ((count 0)) (let* ((currlks (glob (conc destdir"/*"))) (numqrys (length currlks)) (delayval (cond ;; do a droopish curve ((> numqrys 25) (for-each (lambda (f) (if (> (- (current-seconds) (handle-exceptions exn (current-seconds) ;; file is likely gone, just fake out (file-modification-time f))) (keep-age-param)) (let* ((basedir (pathname-directory f)) (filen (pathname-file f)) (destf (conc basedir"/attic/"filen))) (dbfile:print-err "Moving qif file "f" older than 10 seconds to "destf) ;; (delete-file* f) (handle-exceptions exn #t (file-move f destf #t))))) currlks) 4) ((> numqrys 0) (dbfile:droop numqrys)) ;; slope of 1/100 (else #f)))) (if (and delayval (< count 5)) (begin (thread-sleep! delayval) (loop (+ count 1)))))) (with-output-to-file crumbn (lambda () (print fname" run-id="run-id" params="params) )) crumbn)) ;; (db:with-db dbstruct run-id sqlite3:exec "select blah fgrom blaz;") ;; r/w is a flag to indicate if the db is modified by this query #t = yes, #f = no ;; |
1163 1164 1165 1166 1167 1168 1169 | 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 | - - + + + + + + + + + + + + + + + + + + | (define (dbfile:with-simple-file-lock fname proc #!key (expire-time 300)) (let ((gotlock (dbfile:simple-file-lock-and-wait fname expire-time: expire-time))) (if gotlock (let ((res (proc))) (dbfile:simple-file-release-lock fname) res) (assert #t "FATAL: simple file lock never got a lock.")))) |
Modified dbmod.scm from [043beb90c3] to [7b131a4554].
1 2 3 4 5 6 7 | 1 2 3 4 5 6 7 8 | + | ;;====================================================================== ;; Copyright 2017, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by |
15 16 17 18 19 20 21 22 23 24 25 | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ;; ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit dbmod)) (declare (uses dbfile)) (declare (uses commonmod)) (declare (uses debugprint)) (module dbmod * |
Modified dcommon.scm from [eab340744b] to [4b1e45fd47].
25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | + + + | (import canvas-draw-iup) (use regex typed-records matchable) (declare (unit dcommon)) (declare (uses gutils)) (declare (uses db)) (declare (uses commonmod)) (import commonmod) ;; (declare (uses synchash)) (include "megatest-version.scm") (include "common_records.scm") (include "db_records.scm") (include "key_records.scm") (include "run_records.scm") |
633 634 635 636 637 638 639 | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | + - + | (max-row (if (null? row-indices) 1 (common:max (map cadr row-indices)))) (max-col (if (null? col-indices) 1 (common:max (map cadr col-indices)))) (max-visible (max (- (dboard:tabdat-num-tests tabdat) 15) 3)) (max-col-vis (if (> max-col 10) 10 max-col)) (numrows 1) (numcols 1)) (if (common:low-noise-print 60 "runs-stats-update-clear") |
702 703 704 705 706 707 708 | 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 | + - + + | #:numcol 7 #:numcol-visible 7 #:numlin-visible 5 )) (colnames (list "Id" "MTver" "Pid" "Host" "Interface:OutPort" "RunTime" "State" "RunId")) (updater (lambda () (if (dashboard:monitor-changed? commondat tabdat) (let ((servers (case (rmt:transport-mode) |
Modified diff-report.scm from [f999ffe6db] to [0fbca9ae2f].
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | + + | ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;; (declare (unit diff-report)) (declare (uses common)) (declare (uses rmt)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (use matchable) (use fmt) (use ducttape-lib) (define css "") |
Added docs/reference/coping-with-the-tcp-time-wait-state-on-busy-linux-servers.pdf version [bb7c60045d].
cannot compute difference between binary files
Added docs/reference/networking-increasing-the-max-number-of-tcp-ip-connections.pdf version [c3bfe57256].
cannot compute difference between binary files
Added docs/reference/queues-dont-fix-overload.pdf version [938610cb6e].
cannot compute difference between binary files
Modified ezsteps.scm from [aab87817a5] to [077453aa67].
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | + + - + | (declare (unit ezsteps)) (declare (uses db)) (declare (uses common)) (declare (uses items)) (declare (uses runconfig)) ;; (declare (uses sdb)) ;; (declare (uses filedb)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") (include "run_records.scm") ;;(rmt:get-test-info-by-id run-id test-id) -> testdat ;; TODO: deprecate me in favor of ezsteps.scm ;; |
61 62 63 64 65 66 67 | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | - + + | (list-ref stepparts 3) (conc "# error, no command for step "stepname))) (script "") ; "#!/bin/bash\n") ;; yep, we depend on bin/bash FIXME!!!\ (logpro-file (conc stepname ".logpro")) (html-file (conc stepname ".html")) (dat-file (conc stepname ".dat")) (tconfig-logpro (configf:lookup testconfig "logpro" stepname)) |
94 95 96 97 98 99 100 | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | - + | ;; call the command using mt_ezstep ;; (set! script (conc "mt_ezstep " stepname " " (if prevstep prevstep "x") " " stepcmd)) (debug:print 4 *default-log-port* "script: " script) (rmt:teststep-set-status! run-id test-id stepname "start" "-" #f #f) ;; now launch the actual process (call-with-environment-variables |
Modified http-transport.scm from [84bebe0a7c] to [c61c306ba3].
151 152 153 154 155 156 157 | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | - + | (config-use-proxy (equal? (configf:lookup *configdat* "client" "use-http_proxy") "yes"))) (if (not config-use-proxy) (determine-proxy (constantly #f))) (debug:print-info 0 *default-log-port* "http-transport:try-start-server time=" (seconds->time-string (current-seconds)) " ipaddrsstr=" ipaddrstr " portnum=" portnum " config-hostname=" config-hostname) (handle-exceptions exn (begin |
239 240 241 242 243 244 245 | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | - + - - - - + - + - - + - - - - | (define (http-transport:inc-requests-and-prep-to-close-all-connections) (mutex-lock! *http-mutex*) (set! *http-requests-in-progress* (+ 1 *http-requests-in-progress*))) ;; Send "cmd" with json payload "params" to serverdat and receive result ;; |
284 285 286 287 288 289 290 | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | - - - + - - - - - - - + | (debug:print-info 0 *default-log-port* "couldn't talk to server, trying again ...") (begin (debug:print 0 *default-log-port* "WARNING: failure in with-input-from-request to " fullurl ".") (debug:print 0 *default-log-port* " message: " msg ", exn=" exn) (debug:print 0 *default-log-port* " cmd: " cmd " params: " params " key:" (or server-id "thekey")) (debug:print 0 *default-log-port* " call-chain: " call-chain))) ;; what if another thread is communicating ok? Can't happen due to mutex |
343 344 345 346 347 348 349 | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | - + - - - + - - - - + + - - - - + + + + + + - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - + - - - - - - - - - - - + + - - | (signal (make-composite-condition (make-property-condition 'timeout 'message "nmsg-transport:client-api-send-receive-raw timed out talking to server"))))))) ;; careful closing of connections stored in *runremote* ;; |
427 428 429 430 431 432 433 | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | - + - - - - - - + - + - - + + - - - - - + - - - - + + | (debug:print-info 0 *default-log-port* "Waiting for server alive signature") (mutex-lock! *heartbeat-mutex*) (set! sdat *server-info*) (mutex-unlock! *heartbeat-mutex*) (if (and sdat (not changed) (> (- (current-seconds) start-time) 2)) |
502 503 504 505 506 507 508 | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | - + + | (set! server-going #t) (debug:print 0 *default-log-port* "SERVER: running, megatest version: " (common:get-full-version))) ;; NOTE: the server is NOT yet marked as running in the log. We do that in the keep-running routine. (if (and no-sync-db (common:low-noise-print 10 "sync-all")) ;; cheesy way to reduce frequency of running sync :) (begin (if (common:low-noise-print 120 "sync-all-print") (debug:print 0 *default-log-port* "keep-running calling db:all-db-sync at " (time->string (seconds->local-time) "%H:%M:%S"))) |
558 559 560 561 562 563 564 | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | - + - + - + - + | (current-seconds))) (if (common:low-noise-print 120 "server continuing") (debug:print-info 0 *default-log-port* "Server continuing, seconds since last db access: " (- (current-seconds) last-access)) (let ((curr-time (current-seconds))) (handle-exceptions exn (debug:print 0 *default-log-port* "ERROR: Failed to change timestamp on info file " servinfofile ". Are you out of space on that disk? exn=" exn) |
619 620 621 622 623 624 625 | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 | - - - + + + - - - - - - - - - - - - - - - - + - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + | (exit))) ;; all routes though here end in exit ... ;; ;; start_server? ;; (define (http-transport:launch) |
Modified index-tree.scm from [10c620fbfc] to [6384bce0d0].
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | + + | (declare (unit tests)) (declare (uses lock-queue)) (declare (uses db)) (declare (uses common)) (declare (uses items)) (declare (uses runconfig)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") (include "run_records.scm") (include "test_records.scm") |
Modified items.scm from [16328a4b96] to [4ca6320933].
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | + + | ;; (define itemdat '((ripeness "green ripe overripe") ;; (temperature "cool medium hot") ;; (season "summer winter fall spring"))) (declare (unit items)) (declare (uses common)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") ;; Puts out all combinations (define (process-itemlist hierdepth curritemkey itemlist) (let ((res '())) (if (not hierdepth) |
Modified keys.scm from [9fa2c0cfa5] to [d7b8d553eb].
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | + + | ;;====================================================================== (use sqlite3 srfi-1 posix regex regex-case srfi-69) (import (prefix sqlite3 sqlite3:)) (declare (unit keys)) (declare (uses common)) (declare (uses commonmod)) (import commonmod) (include "key_records.scm") (include "common_records.scm") (define (keys->keystr keys) ;; => key1,key2,key3,additiona1, ... (string-intersperse keys ",")) |
Modified launch.scm from [9881087e2c] to [b3f7d09843].
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | + + + + + | (import (prefix base64 base64:)) (import (prefix sqlite3 sqlite3:)) (declare (unit launch)) (declare (uses subrun)) (declare (uses common)) (declare (uses commonmod)) (declare (uses configf)) (declare (uses db)) (declare (uses ezsteps)) (declare (uses dbfile)) (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") (include "megatest-fossil-hash.scm") (import commonmod dbfile) ;;====================================================================== ;; ezsteps ;;====================================================================== ;; ezsteps were going to be coded as ;; stepname[,predstep1,predstep2 ...] [{VAR1=first,second,third}] command to execute |
181 182 183 184 185 186 187 | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | - + | (setenv "MT_STEP_NAMES" (string-intersperse all-step-names " ")) (let loop ((ezstep (car ezstepslst)) (tal (cdr ezstepslst)) (prevstep #f)) (debug:print-info 0 *default-log-port* "Processing ezstep \"" (string-intersperse ezstep " ") "\"") ;; check exit-info (vector-ref exit-info 1) (if (launch:einf-exit-status exit-info) ;; (vector-ref exit-info 1) |
203 204 205 206 207 208 209 | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | - + | (debug:print 0 *default-log-port* "WARNING: a prior step failed, stopping at " ezstep))) (file-close status-file) ) )))))) (define (launch:monitor-job run-id test-id item-path fullrunscript ezsteps test-name tconfigreg exit-info m work-area runtlim misc-flags) |
237 238 239 240 241 242 243 | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | - - - + + + + - + | (delta (abs (- df disk-free)))) (if (and (> df 0) (> (/ delta df) 0.1)) ;; (> delta 200) ;; ignore changes under 200 Meg df #f))) (do-sync (or new-cpu-load new-disk-free over-time)) |
312 313 314 315 316 317 318 | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | - + | (tests:test-set-status! run-id test-id "KILLED" "KILLED" (conc (args:get-arg "-m")" "kill-reason) #f)) ;; BB ADDED kill-reason -- confirm OK with Matt (begin (debug:print-error 0 *default-log-port* "Nothing to kill, pid1=" pid1 ", pid2=" pid2) (tests:test-set-status! run-id test-id "KILLED" "FAILED TO KILL" (conc (args:get-arg "-m")" "kill-reason) #f) ;; BB ADDED kill-reason -- confirm OK with Matt ))) (mutex-unlock! m) ;; no point in sticking around. Exit now. But run end of run before exiting? |
763 764 765 766 767 768 769 | 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | - + - + + - - - - - + + + + + + + + + + + + | ;; if dead safe to mark the test as killed in the db ;; State/status table ;; new ;; 100% COMPLETED/ (PASS,FAIL,ABORT etc.) ==> COMPLETED / X where X is same as itemized rollup ;; > 3 RUNNING with not test_dead do nothing (run should already be RUNNING/ na ;; > 0 RUNNING and test_dead then send KILLREQ ==> COMPLETED ;; 0 RUNNING ==> this is actually the first condition, should not get here |
1129 1130 1131 1132 1133 1134 1135 | 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 | - + + + + | (begin (setenv "MT_RUN_AREA_HOME" *toppath*) (setenv "MT_TESTSUITENAME" (common:get-testsuite-name))) (begin (debug:print-error 0 *default-log-port* "failed to find the top path to your Megatest area.") (set! *toppath* #f) ;; force it to be false so we return #f #f)) |
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 | 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 | + | ;; 2. create run dir on disk, path name is meaningful ;; 3. create link from run dir to megatest runs area ;; 4. remotely run the test on allocated host ;; - could be ssh to host from hosts table (update regularly with load) ;; - could be netbatch ;; (launch-test db (cadr status) test-conf)) (define (launch-test test-id run-id run-info keyvals runname test-conf test-name test-path itemdat params) (assert runname "FATAL: launch-test called with no runname") (mutex-lock! *launch-setup-mutex*) ;; setting variables and processing the testconfig is NOT thread-safe, reuse the launch-setup mutex (let* ( ;; (lock-key (conc "test-" test-id)) ;; (got-lock (let loop ((lock (rmt:no-sync-get-lock lock-key)) ;; (expire-time (+ (current-seconds) 15))) ;; give up on getting the lock and steal it after 15 seconds ;; (if (car lock) ;; #t ;; (if (> (current-seconds) expire-time) |
1546 1547 1548 1549 1550 1551 1552 | 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 | - + - + | ;; the following call handles waiver propogation. cannot yet condense into roll-up-pass-fail (tests:test-set-status! run-id test-id "LAUNCHED" "n/a" #f #f) ;; (if launch-results launch-results "FAILED")) (rmt:set-state-status-and-roll-up-items run-id test-name item-path #f "LAUNCHED" #f) ;; (pp (hash-table->alist tconfig)) (set! diskpath (get-best-disk *configdat* tconfig)) (debug:print 2 *default-log-port* "best disk path = " diskpath) (if diskpath |
Modified lock-queue.scm from [21543b63ce] to [fbbd0328d6].
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | + + | ;; (use (prefix sqlite3 sqlite3:) srfi-18) (declare (unit lock-queue)) (declare (uses common)) (declare (uses tasks)) (declare (uses commonmod)) (import commonmod) ;;====================================================================== ;; attempt to prevent overlapping updates of rollup files by queueing ;; update requests in an sqlite db ;;====================================================================== ;;====================================================================== |
Modified margs.scm from [cc1616820d] to [7a5ab19394].
21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | + + + + + + + + + + | (define args:arg-hash (make-hash-table)) (define (args:get-arg arg . default) (if (null? default) (hash-table-ref/default args:arg-hash arg #f) (hash-table-ref/default args:arg-hash arg (car default)))) ;; get an arg as a number (define (args:get-arg-number arg . default) (let* ((val-str (args:get-arg arg)) (val (if val-str (string->number val-str) #f))) (if val val (if (null? default) #f default)))) (define (args:any? . args) (not (null? (filter (lambda (x) x) (map args:get-arg args))))) (define (args:get-arg-from ht arg . default) (if (null? default) |
Modified megatest-version.scm from [1aac8cc071] to [b3480582d4].
16 17 18 19 20 21 22 | 16 17 18 19 20 21 22 23 | - + | ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;; Always use two or four digit decimal ;; 1.01, 1.02...1.10,1.11,1.1101 ... 1.99,2.00.. ;; (declare (unit megatest-version)) |
Modified megatest.scm from [89decfdb89] to [f88c7a5d70].
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | + + + + + + + + - - - - - - + + + + + + - - - + + + - + + + - + + + + + + | ;; fake out readline usage of toplevel-command (define (toplevel-command . a) #f) (declare (uses common)) ;; (declare (uses megatest-version)) (declare (uses margs)) (declare (uses mtargs)) (declare (uses mtargs.import)) (declare (uses commonmod)) (declare (uses commonmod.import)) (declare (uses mtargs)) (declare (uses mtargs.import)) (declare (uses debugprint)) (declare (uses debugprint.import)) (declare (uses runs)) (declare (uses launch)) (declare (uses server)) (declare (uses client)) (declare (uses tests)) (declare (uses genexample)) ;; (declare (uses daemon)) (declare (uses db)) ;; (declare (uses dcommon)) (declare (uses tdb)) (declare (uses mt)) (declare (uses api)) (declare (uses tasks)) ;; only used for debugging. (declare (uses env)) (declare (uses diff-report)) (declare (uses db)) |
371 372 373 374 375 376 377 378 379 380 381 382 383 384 | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | + | "-override-timeout" "-test-files" ;; -test-paths is for listing all "-load" ;; load and exectute a scheme file "-section" "-var" "-dumpmode" "-run-id" "-db" "-ping" "-refdb2dat" "-o" "-log" "-sync-log" "-since" "-fields" |
583 584 585 586 587 588 589 | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 | - - + + - + - + | ;; this segment will run launch:setup only if -log is not set. This is fairly safe as servers are not ;; manually started and thus should never be started in a non-megatest area. Thus no need to handle situation ;; where (launch:setup) returns #f? ;; (if (or (args:get-arg "-log")(args:get-arg "-server")) ;; redirect the log always when a server (handle-exceptions exn |
652 653 654 655 656 657 658 | 668 669 670 671 672 673 674 675 676 677 678 679 680 681 | - - - - - - - - - - - - - | (original-exit exit-code))))) ;; for some switches always print the command to stderr ;; (if (args:any? "-run" "-runall" "-remove-runs" "-set-state-status" "-kill-runs" "-kill-rerun") (debug:print 0 *default-log-port* (string-intersperse (argv) " "))) |
932 933 934 935 936 937 938 | 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 | + + - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - + - + - + - + - | ;; Start the server - can be done in conjunction with -runall or -runtests (one day...) ;; we start the server if not running else start the client thread ;;====================================================================== ;; Server? Start up here. ;; (if (args:get-arg "-server") (let* (;; (run-id (args:get-arg "-run-id")) (dbfname (args:get-arg "-db")) |
1381 1382 1383 1384 1385 1386 1387 | 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 | - - + | ;; NOTE: list-runs and list-db-targets operate on local db!!! ;; ;; IDEA: megatest list -runname blah% ... ;; (if (or (args:get-arg "-list-runs") (args:get-arg "-list-db-targets")) (if (launch:setup) |
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 | 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 | + + + + + | (tests-spec (let ((t (alist-ref "tests" fields-spec equal?))) (if (and t (null? t)) ;; all fields db:test-record-fields t))) (adj-tests-spec (delete-duplicates (if tests-spec (cons "id" tests-spec) db:test-record-fields))) ;; '("id")))) (steps-spec (alist-ref "steps" fields-spec equal?)) (test-field-index (make-hash-table))) (if (and (args:get-arg "-dumpmode") (not (member (args:get-arg "-dumpmode") '("sexpr" "json" "ods" "list")))) (begin (debug:print 0 *default-log-port* "ERROR: dumpmode "(args:get-arg "-dumpmode")" not recognised. Use sexpr, json, ods or list") (exit))) (if (and tests-spec (not (null? tests-spec))) ;; do some validation and processing of the test-spec (let ((invalid-tests-spec (filter (lambda (x)(not (member x db:test-record-fields))) tests-spec))) (if (null? invalid-tests-spec) ;; generate the lookup map test-field-name => index-number (let loop ((hed (car adj-tests-spec)) (tal (cdr adj-tests-spec)) (idx 0)) |
1486 1487 1488 1489 1490 1491 1492 | 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | - + - + + + + | ;; (mutils:hierhash-set! data (db:get-value-by-header run header "status") targetstr runname "meta" "status" ) ;; (mutils:hierhash-set! data (db:get-value-by-header run header "state") targetstr runname "meta" "state" ) ;; (mutils:hierhash-set! data (conc (db:get-value-by-header run header "id")) targetstr runname "meta" "id" ) ;; (mutils:hierhash-set! data (db:get-value-by-header run header "event_time") targetstr runname "meta" "event_time" ) ;; (mutils:hierhash-set! data (db:get-value-by-header run header "comment") targetstr runname "meta" "comment" ) ;; ;; add last entry twice - seems to be a bug in hierhash? ;; (mutils:hierhash-set! data (db:get-value-by-header run header "comment") targetstr runname "meta" "comment" ) |
2052 2053 2054 2055 2056 2057 2058 | 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 | - + | ;;====================================================================== (if (args:get-arg "-extract-ods") (general-run-call "-extract-ods" "Make ods spreadsheet" (lambda (target runname keys keyvals) |
2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 | 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 | + + + + + + | (if (args:get-arg "-cleanup-db") (begin (if (not (launch:setup)) (begin (debug:print 0 *default-log-port* "Failed to setup, exiting") (exit 1))) ;; (if (not (server:choose-server *toppath* 'home?)) ;; (begin ;; (debug:print 0 *default-log-port* "Servers are not running on this host or no servers alive. Cannot run cleanup-db") ;; (exit 1))) (let ((dbstructs (db:setup #f))) (common:cleanup-db dbstructs)) (set! *didsomething* #t))) (if (args:get-arg "-mark-incompletes") (begin (if (not (launch:setup)) |
2377 2378 2379 2380 2381 2382 2383 | 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 | + + - + | (exit 0))) (if (or (getenv "MT_RUNSCRIPT") (args:get-arg "-repl") (args:get-arg "-load")) (let* ((toppath (launch:setup)) (dbstructs (if (and toppath ;; NOTE: server:choose-server is starting a server ;; either add equivalent for tcp mode or ???? |
Modified mlaunch.scm from [5bcd34288f] to [62be2ae3e1].
26 27 28 29 30 31 32 33 | 26 27 28 29 30 31 32 33 34 35 | + + | ;;====================================================================== (use sqlite3 srfi-1 posix regex regex-case srfi-69 format) (declare (unit mlaunch)) (declare (uses db)) (declare (uses common)) (declare (uses commonmod)) (import commonmod) |
Modified monitor.scm from [3df55c85ea] to [3205ec8bdb].
21 22 23 24 25 26 27 28 29 30 31 32 33 | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | + + | (import (prefix sqlite3 sqlite3:)) (declare (unit runs)) (declare (uses db)) (declare (uses common)) (declare (uses items)) (declare (uses runconfig)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") (include "run_records.scm") |
Added mtargs/mtargs.egg version [deacd4afda].
1 2 3 4 5 6 7 | + + + + + + + | ((license "LGPL") (version 0.1) (category misc) (dependencies srfi-69 srfi-1) (author "Matt Welland") (synopsis "Primitive argument processor.") (components (extension mtargs))) |
Modified mtargs/mtargs.scm from [54d4e74749] to [49b76da6ef].
16 17 18 19 20 21 22 | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | - - + + + - - + + - - + + + + + + + + + - + + + + + + + + + + - - - - - - - - - - - - - - - - - - | ;; along with mtargs. If not, see <http://www.gnu.org/licenses/>. (module mtargs ( arg-hash get-arg |
92 93 94 95 96 97 98 | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | - + - | (if (null? tail) remtargs (loop (car tail)(cdr tail) remtargs))) (else (if (null? tail)(append remtargs (list arg)) ;; return the non-used args (loop (car tail)(cdr tail)(append remtargs (list arg)))))))) )) |
Modified mtexec.scm from [6016ee8684] to [3a9610856f].
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | + + | (prefix dbi dbi:) ) ;; (declare (uses common)) (declare (uses margs)) (declare (uses configf)) ;; (declare (uses rmt)) (declare (uses commonmod)) (import commonmod) ;; (use ducttape-lib) (include "megatest-version.scm") (include "megatest-fossil-hash.scm") ;; (require-library stml) |
Modified mtut.scm from [413cf26858] to [b04fee463b].
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | + + + | (prefix sqlite3 sqlite3:) nanomsg) (declare (uses common)) (declare (uses margs)) (declare (uses configf)) ;; (declare (uses rmt)) (declare (uses commonmod)) (declare (uses commonmod.import)) (import commonmod) (use ducttape-lib) (include "megatest-fossil-hash.scm") (require-library stml) |
Modified newdashboard.scm from [a0c1909f88] to [c27106b5bc].
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | + + | (use sql-de-lite srfi-1 posix regex regex-case srfi-69 typed-records sparse-vectors ;; defstruct (prefix dbi dbi:)) (declare (uses common)) (declare (uses megatest-version)) (declare (uses margs)) (declare (uses commonmod)) (import commonmod) ;; (declare (uses launch)) ;; (declare (uses gutils)) ;; (declare (uses db)) ;; (declare (uses server)) ;; (declare (uses synchash)) (declare (uses dcommon)) |
Modified ods.scm from [42e94b826f] to [1b93bc9256].
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | + + | ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;; (use csv-xml regex) (declare (unit ods)) (declare (uses common)) (declare (uses commonmod)) (import commonmod) (define ods:dirs '("Configurations2" "Configurations2/toolpanel" "Configurations2/menubar" "Configurations2/toolbar" "Configurations2/progressbar" |
Modified portlogger.scm from [36a4964f50] to [8344cdf37f].
62 63 64 65 66 67 68 | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | - + | (avail (tasks:wait-on-journal fname 10))) ;; wait up to about 10 seconds for the journal to go away (handle-exceptions exn (begin ;; (release-dot-lock fname) (debug:print-error 0 *default-log-port* "portlogger:open-run-close failed. " proc " " params) (debug:print 0 *default-log-port* " message: " ((condition-property-accessor 'exn 'message) exn)) |
Modified rmt.scm from [91ffe1108a] to [ee23eeb29c].
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | + + + + + + + + + + + + + + + + - + - - - + + + - - - - - + + + + + + + + + + + - - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - + + - + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + - - + - - - - - - - - - - - - - + + + + - - - - - - - - - - + + + + + + + - - - - - + + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + - - - + + - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - + - - + + - - + + - - - + + | ;;====================================================================== (use format typed-records) ;; RADT => purpose of json format?? (declare (unit rmt)) (declare (uses api)) (declare (uses http-transport)) (declare (uses commonmod)) (declare (uses dbfile)) ;; (declare (uses dbmemmod)) (declare (uses dbmod)) (declare (uses tcp-transportmod)) (include "common_records.scm") ;; (declare (uses rmtmod)) ;; used by http-transport (import dbfile) ;; rmtmod) (import commonmod ;; dbmemmod dbfile dbmod tcp-transportmod) ;; http - use the old http + in /tmp db ;; tcp - use tcp transport with inmem db ;; nfs - use direct to disk access (read-only) ;; (define rmt:transport-mode (make-parameter 'http)) ;; ;; THESE ARE ALL CALLED ON THE CLIENT SIDE!!! ;; ;; generate entries for ~/.megatestrc with the following ;; ;; grep define ../rmt.scm | grep rmt: |perl -pi -e 's/\(define\s+\((\S+)\W.*$/\1/'|sort -u ;;====================================================================== ;; S U P P O R T F U N C T I O N S ;;====================================================================== ;; if a server is either running or in the process of starting call client:setup ;; else return #f to let the calling proc know that there is no server available ;; |
390 391 392 393 394 395 396 | 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | - + | (loop (car tal)(cdr tal) newmax-cmd currmax))))))) (mutex-unlock! *db-stats-mutex*) res)) (define (rmt:open-qry-close-locally cmd run-id params #!key (remretries 5)) (let* ((qry-is-write (not (member cmd api:read-only-queries))) (db-file-path (db:dbfile-path)) ;; 0)) |
430 431 432 433 434 435 436 | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | - + - - - - - - + | (if qry-is-write (let ((start-time (current-seconds))) (mutex-lock! *db-multi-sync-mutex*) / (set! *db-last-access* start-time) ;; THIS IS PROBABLY USELESS? (we are on a client) (mutex-unlock! *db-multi-sync-mutex*))))) res)) |
468 469 470 471 472 473 474 | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | - + - - + - - | (define (rmt:login run-id) (rmt:send-receive 'login run-id (list *toppath* megatest-version (client:get-signature)))) ;; This login does no retries under the hood - it acts a bit like a ping. ;; Deprecated for nmsg-transport. ;; |
517 518 519 520 521 522 523 524 525 | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | + - + | (rmt:send-receive 'get-tests-tags #f '())) ;;====================================================================== ;; K E Y S ;;====================================================================== ;; These require run-id because the values come from the run! ;; however the query must still apply to main.db ;; (define (rmt:get-key-val-pairs run-id) |
546 547 548 549 550 551 552 | 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 | - + - - + + + | res))) (define (rmt:get-targets) (rmt:send-receive 'get-targets #f '())) (define (rmt:get-target run-id) (assert (number? run-id) "FATAL: Run id required.") |
827 828 829 830 831 832 833 834 835 836 837 838 839 840 | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 | + + + | (assert (number? run-id) "FATAL: Run id required.") (rmt:send-receive 'get-run-status #f (list run-id))) (define (rmt:get-run-state run-id) (assert (number? run-id) "FATAL: Run id required.") (rmt:send-receive 'get-run-state #f (list run-id))) (define (rmt:get-run-state-status run-id) (assert (number? run-id) "FATAL: Run id required.") (rmt:send-receive 'get-run-state-status #f (list run-id))) (define (rmt:set-run-status run-id run-status #!key (msg #f)) (assert (number? run-id) "FATAL: Run id required.") (rmt:send-receive 'set-run-status #f (list run-id run-status msg))) (define (rmt:set-run-state-status run-id state status ) (assert (number? run-id) "FATAL: Run id required.") |
1042 1043 1044 1045 1046 1047 1048 | 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | - + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - + + | (define (rmt:test-set-archive-block-id run-id test-id archive-block-id) (assert (number? run-id) "FATAL: Run id required.") (rmt:send-receive 'test-set-archive-block-id run-id (list run-id test-id archive-block-id))) (define (rmt:test-get-archive-block-info archive-block-id) (rmt:send-receive 'test-get-archive-block-info #f (list archive-block-id))) |
1094 1095 1096 1097 1098 1099 1100 | 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 | - + | ;; server is ;; overloaded and we ;; want to ease off ;; the queries (let ((wait-delay (+ attemptnum (* attemptnum 10)))) (debug:print 0 *default-log-port* "WARNING: server is overloaded. Delaying " wait-delay " seconds and trying call again.") (mutex-lock! *rmt-mutex*) |
Modified runconfig.scm from [66b9c38588] to [7a53eaa476].
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | + + | ;; to this run field1val/field2val/field3val ... ;;====================================================================== (use format directory-utils) (declare (unit runconfig)) (declare (uses common)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (define (runconfig:read fname target environ-patt) (let ((ht (make-hash-table))) (if target (hash-table-set! ht target '())) (read-config fname ht #t environ-patt: environ-patt sections: (if target (list "default" target) #f)))) |
Modified runs.scm from [52f98f2a96] to [9ed9863b9e].
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | + + + | (use (prefix sqlite3 sqlite3:) srfi-1 posix regex regex-case srfi-69 (srfi 18) posix-extras directory-utils pathname-expand typed-records format sxml-serializer sxml-modifications matchable) (declare (unit runs)) (declare (uses db)) (declare (uses common)) (declare (uses commonmod)) (declare (uses items)) (declare (uses runconfig)) (declare (uses tests)) (declare (uses server)) (declare (uses mt)) (declare (uses archive)) ;; (declare (uses filedb)) (include "common_records.scm") (include "key_records.scm") (include "db_records.scm") (include "run_records.scm") (include "test_records.scm") ;; (include "debugger.scm") (import commonmod) ;; use this struct to facilitate refactoring ;; (defstruct runs:dat reglen regfull runname max-concurrent-jobs run-id |
1277 1278 1279 1280 1281 1282 1283 | 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 | - + + - + + + + + + + + | ", ")) (thread-sleep! 0.051) (list hed tal reg reruns)) ;; If no resources are available just kill time and loop again ;; ((not have-resources) ;; simply try again after waiting a second |
1773 1774 1775 1776 1777 1778 1779 | 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | - + | (let* ((jobgroup (runs:testdat-jobgroup testdat-in)) (can-run-more-tests (runs:dat-can-run-more-tests runsdat)) (last-jobs-check-time (runs:dat-last-jobs-check-time runsdat)) (should-check-jobs (match can-run-more-tests ((can-run-more-flag num-running nr-in-jobgroup max-concurrent-jobs . params) (if (< (- max-concurrent-jobs num-running) 25) (begin |
1853 1854 1855 1856 1857 1858 1859 | 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 | + - + | (my-item-path (item-list->path my-itemdat)) (newtestname (db:test-make-full-name hed my-item-path))) ;; test names are unique on testname/item-path (tests:testqueue-set-items! new-test-record #f) (tests:testqueue-set-itemdat! new-test-record my-itemdat) (tests:testqueue-set-item_path! new-test-record my-item-path) (hash-table-set! test-records newtestname new-test-record) ;; BUG: This next line sucks up a lot of horsepower |
Modified server.scm from [167f3b570d] to [851da574f1].
63 64 65 66 67 68 69 | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | - - - - - - - - - - - | ;;====================================================================== ;; S E R V E R ;;====================================================================== ;; Call this to start the actual server ;; |
110 111 112 113 114 115 116 | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - + | (define (server:get-server-id) (if *server-id* *server-id* (let ((sig (server:mk-signature))) ;; clients re-use the server:mk-signature logic (set! *server-id* sig) *server-id*))) |
188 189 190 191 192 193 194 | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + | (define (server:logf-get-start-info logf) (let ((server-rx (regexp "^SERVER STARTED: (\\S+):(\\d+) AT ([\\d\\.]+) server-id: (\\S+) pid: (\\d+)")) ;; SERVER STARTED: host:port AT timesecs server id (dbprep-rx (regexp "^SERVER: dbprep")) (dbprep-found 0) (bad-dat (list #f #f #f #f #f))) (handle-exceptions |
417 418 419 420 421 422 423 | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - - - - + + + + + + - - + + - + - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - + | (thread-sleep! ( + 1 idletime)) (server:wait-for-server-start-last-flag areapath))))))) ;; oldest server alive determines host then choose random of youngest ;; five servers on that host ;; (define (server:get-servers-info areapath) ;; (assert *toppath* "FATAL: server:get-servers-info called before *toppath* has been set.") |
536 537 538 539 540 541 542 | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | + - + - + | (define (server:start-and-wait areapath #!key (timeout 60)) (let ((give-up-time (+ (current-seconds) timeout))) (let loop ((server-info (server:check-if-running areapath)) (try-num 0)) (if (or server-info (> (current-seconds) give-up-time)) ;; server-url will be #f if no server available. (server:record->url server-info) (let* ( (servers (server:choose-server areapath 'all-valid)) |
585 586 587 588 589 590 591 | 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | - + - + - - - - - - - - - - - - - - - + + + + + + + + - - - + + - - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + | (define (server:kill servr) (handle-exceptions exn (begin (debug:print-info 0 *default-log-port* "Unable to get host and/or port from " servr ", exn=" exn) #f) |
662 663 664 665 666 667 668 | 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | #f))) ;; timeout is hms string: 1h 5m 3s, default is 1 minute ;; This is currently broken. Just use the number of hours with no unit. ;; Default is 60 seconds. ;; (define (server:expiration-timeout) |
Modified subrun.scm from [8e4ec606e5] to [4fc2a9b685].
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | + + + | (use (prefix sqlite3 sqlite3:) srfi-1 posix regex regex-case srfi-69 (srfi 18) posix-extras directory-utils pathname-expand typed-records format call-with-environment-variables) (declare (unit subrun)) ;;(declare (uses runs)) (declare (uses db)) (declare (uses common)) (declare (uses commonmod)) ;;(declare (uses items)) ;;(declare (uses runconfig)) ;;(declare (uses tests)) ;;(declare (uses server)) (declare (uses mt)) ;;(declare (uses archive)) ;; (declare (uses filedb)) (import commonmod) ;(include "common_records.scm") ;;(include "key_records.scm") (include "db_records.scm") ;; provides db:test-get-id ;;(include "run_records.scm") ;;(include "test_records.scm") |
133 134 135 136 137 138 139 | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | - + | (define (subrun:launch-cmd test-run-dir run-mode #!optional (sub-cmd "-run")) ;; BUG: "-run" should be changed to "-rerun-clean" but current doesn't work (if (subrun:subrun-removed? test-run-dir) (subrun:unset-subrun-removed test-run-dir)) (let* ((log-prefix "run") (switches (subrun:selector+log-switches test-run-dir log-prefix)) (run-wait (equal? run-mode "yes")) |
230 231 232 233 234 235 236 237 | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | + + + + - - + + - + | (map (lambda (x) (list (car x) (cdr x))) switch-alist)) " "))) res)) ;; NOTE: Here we run sub megatest but this is not intended for one version ;; of megatest to test another version. Thus we propagate the (define (subrun:exec-sub-megatest test-run-dir action-switches-str log-prefix) (let* ((mtpathdir (common:get-megatest-exe-dir)) (mtexe (common:get-mtexe)) |
Modified tasks.scm from [0f38bdbcce] to [499c2cc5ba].
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | + + | (declare (unit tasks)) (declare (uses dbfile)) (declare (uses db)) (declare (uses rmt)) (declare (uses common)) (declare (uses pgdb)) (declare (uses commonmod)) (import commonmod) (import dbfile) ;; (import pgdb) ;; pgdb is a module (include "task_records.scm") (include "db_records.scm") |
Modified tcmt.scm from [6658a745e5] to [bb0554607f].
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | + + | (use trace) ;; (trace-call-sites #t) (declare (uses margs)) (declare (uses rmt)) (declare (uses common)) ;; (declare (uses megatest-version)) (declare (uses commonmod)) (import commonmod) (include "megatest-version.scm") (include "megatest-fossil-hash.scm") (include "db_records.scm") (define origargs (cdr (argv))) (define remargs (args:get-args |
Added tcp-transportmod.scm version [8f58514e4b].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ;;====================================================================== ;; Copyright 2017, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit tcp-transportmod)) (declare (uses debugprint)) (declare (uses commonmod)) (declare (uses dbfile)) (declare (uses dbmod)) (use address-info) (module tcp-transportmod * (import scheme (prefix sqlite3 sqlite3:) chicken data-structures address-info directory-utils extras files hostinfo matchable md5 message-digest ports posix regex regex-case s11n srfi-1 srfi-18 srfi-4 srfi-69 stack typed-records tcp-server tcp debugprint commonmod dbfile dbmod ) ;;====================================================================== ;; client ;;====================================================================== ;; (define keep-age-param (make-parameter 10)) ;; qif file age, if over move to attic ;; Used ONLY for client ;; (defstruct tt-conn host port host-port dbfname server-id server-start pid ) ;; Used for BOTH clients and servers (defstruct tt ;; client related (conns (make-hash-table)) ;; dbfname -> conn ;; server related (state 'starting) (areapath #f) (host #f) (port #f) (conn #f) (cleanup-proc #f) (handler #f) ;; receives data and responds (socket #f) (thread #f) (host-port #f) (cmd-thread #f) (ro-mode #f) (ro-mode-checked #f) (last-access (current-seconds)) (servinf-file #f) (last-serv-start 0) ) ;; parameters ;; (define tt-server-timeout-param (make-parameter 600)) ;; make ttdat visible (define *server-info* #f) (define (tt:make-remote areapath) (make-tt areapath: areapath)) ;; 1 ... or #f (define (tt:valid-run-id run-id) (or (number? run-id) (not run-id))) ;; do all the busy work of finding and setting up conn for ;; connecting to a server ;; (define (tt:client-connect-to-server ttdat dbfname run-id testsuite) (assert (tt:valid-run-id run-id) "FATAL: invalid run-id "run-id) (let* ((conn (hash-table-ref/default (tt-conns ttdat) dbfname #f)) (server-start-proc (lambda () (tt:server-process-run (tt-areapath ttdat) testsuite ;; (dbfile:testsuite-name) (common:find-local-megatest) run-id)))) (if conn conn ;; we are already connected to the server (let* ((sdat (tt:get-current-server-info ttdat dbfname))) (match sdat ((host port start-time server-id pid dbfname2 servinffile) (assert (equal? dbfname dbfname2) "FATAL: read server info from wrong file.") (let* ((host-port (conc host":"port)) (conn (make-tt-conn host: host port: port host-port: host-port dbfname: dbfname servinf-file: servinffile server-id: server-id server-start: start-time pid: pid))) (hash-table-set! (tt-conns ttdat) dbfname conn) ;; verify we can talk to this server (let* ((ping-res (tt:ping host port server-id))) (case ping-res ((running) conn) ((starting) (thread-sleep! 0.5) (tt:client-connect-to-server ttdat dbfname run-id testsuite)) (else (let* ((curr-secs (current-seconds))) ;; rm the (last server) would go here (if (> (- curr-secs (tt-last-serv-start ttdat)) 10) (begin (tt-last-serv-start-set! ttdat curr-secs) (server-start-proc))) ;; start server if 30 sec since last attempt (thread-sleep! 1) (tt:client-connect-to-server ttdat dbfname run-id testsuite))))))) (else (if (> (- (current-seconds) (tt-last-serv-start ttdat)) 5) ;; really do not want to swamp the machine with servers (begin (debug:print-info 0 *default-log-port* "No server found. Starting one for run-id "run-id" in dbfile "dbfname) (server-start-proc) (tt-last-serv-start-set! ttdat (current-seconds)))) (thread-sleep! 1) (tt:client-connect-to-server ttdat dbfname run-id testsuite))))))) (define (tt:ping host port server-id) (let* ((res (tt:send-receive-direct host port `(ping #f #f #f)))) ;; please send me your server-id ;; ;; need two threads, one a 5 second timer ;; (match res ((status errmsg result meta) (if (equal? result server-id) (let* ((server-state (alist-ref 'sstate meta))) ;; (debug:print 0 *default-log-port* "Ping to "host":"port" successful.") (or server-state 'unk)) ;; then we are good (begin (debug:print 0 *default-log-port* "WARNING: server-id does not match, expected: "server-id", got: "result) #f))) (else ;; (debug:print 0 *default-log-port* "res not in form (status errmsg result meta), got: "res) #f)))) ;; client side handler ;; ;;(tt:handler #<tt> get-keys #f () 2 #f "/home/matt/data/megatest/ext-tests" #f "main.db" "ext-tests" "/home/matt/data/megatest/bin/.22.04/../megatest") ;; (define (tt:handler ttdat cmd run-id params attemptnum area-dat areapath readonly-mode dbfname testsuite mtexe) ;; NOTE: areapath is passed in and in tt struct. We'll use passed in value for now. (let* ((conn (tt:client-connect-to-server ttdat dbfname run-id testsuite))) ;; (hash-table-ref/default (tt-conns ttdat) dbfname #f))) (if conn ;; have connection, call the server (let* ((res (tt:send-receive ttdat conn cmd run-id params))) ;; res is (status errmsg result meta) (match res ((status errmsg result meta) (if (list? meta) (let* ((delay-wait (alist-ref 'delay-wait meta))) (if (and (number? delay-wait) (> delay-wait 0)) (begin (debug:print 0 *default-log-port* "Server is loaded, delaying "delay-wait" seconds") (thread-sleep! delay-wait))))) (case status ((busy) ;; result will be how long the server wants you to delay (debug:print 0 *default-log-port* "WARNING: server for "dbfname" is overloaded, will try again in "result" seconds.") (thread-sleep! (if (number? result) result 2)) (tt:handler ttdat cmd run-id params (+ attemptnum 1) area-dat areapath readonly-mode dbfname testsuite mtexe)) ((loaded) (debug:print 0 *default-log-port* "WARNING: server for "dbfname" is loaded, will try again in a 1/4 second.") (thread-sleep! 0.25) (tt:handler ttdat cmd run-id params (+ attemptnum 1) area-dat areapath readonly-mode dbfname testsuite mtexe)) (else result))) (else (if (not res) (let* ((host (tt-conn-host conn)) (port (tt-conn-port conn)) ;; (dbfname (tt-conn-port conn)) ;; 192.168.0.127:4242-726924:4.db (pid (tt-conn-pid conn)) (servinf (conc areapath"/.servinfo/"host":"port"-"pid":"dbfname))) (hash-table-set! (tt-conns ttdat) dbfname #f) (if (file-exists? servinf) (begin (debug:print 0 *default-log-port* "INFO: no ping response from server "host":"port" for "dbfname) (if (and (file-exists? servinf) (> (- (current-seconds)(file-modification-time servinf)) 60)) (begin (debug:print 0 *default-log-port* "INFO: "servinf" file seems old and no ping response, removing it.") (delete-file* servinf)))) (debug:print 0 *default-log-port* "INFO: connection to server "host":"port" broken for "dbfname", but do not see servinf file "servinf)) (tt:handler ttdat cmd run-id params (+ attemptnum 1) area-dat areapath readonly-mode dbfname testsuite mtexe)) (assert #f "FATAL: tt:handler received bad data "res))))) (begin (thread-sleep! 1) ;; give it a rest and try again (tt:handler ttdat cmd run-id params attemptnum area-dat areapath readonly-mode dbfname testsuite mtexe))))) ;; no conn yet, find and or start and find a server ;; (let* ((server (tt:find-server ttdat dbfname))) ;; (if server ;; (let* ((conn (tt:client-connect-to-server server))) ;; (hash-table-set! (tt-conns ttdat) dbfname conn) ;; (tt:handler ttdat cmd run-id params attemptnum area-dat areapath readonly-mode ;; dbfname testsuite mtexe)) ;; ;; no server, try to start a server process ;; (begin ;; (tt:server-process-run areapath testsuite mtexe run-id) ;; #!key (profile-mode "")) ;; (thread-sleep! 1) ;; (tt:handler ttdat cmd run-id params attemptnum area-dat areapath ;; readonly-mode dbfname testsuite mtexe))))))) (define (tt:bid-for-servership run-id) #f) ;; gets server info and appends path to server file ;; sorts by age, oldest first ;; ;; returns list of (host port startseconds server-id servinfofile) ;; (define (tt:get-server-info-sorted ttdat dbfname) (let* ((areapath (tt-areapath ttdat)) (sfiles (tt:find-server areapath dbfname)) (sdats (filter car (map tt:server-get-info sfiles))) ;; first element is #f if the file disappeared while being read (sorted (sort sdats (lambda (a b) (< (list-ref a 2)(list-ref b 2))))) (count 0)) (for-each (lambda (rec) (if (or (> (length sorted) 1) (common:low-noise-print 120 "server info sorted")) (debug:print 0 *default-log-port* "SERVER #"count": "(string-intersperse (map conc sorted) ", "))) (set! count (+ count 1))) sorted) sorted)) (define (tt:get-current-server-info ttdat dbfname) (assert (tt-areapath ttdat) "FATAL: areapath not set in ttdat.") ;; ;; TODO - replace most of below with tt;get-server-info-sorted ;; (let* ((areapath (tt-areapath ttdat)) (sfiles (tt:find-server areapath dbfname)) (sdats (filter car (map tt:server-get-info sfiles))) ;; first element is #f if the file disappeared while being read (sorted (sort sdats (lambda (a b) (< (list-ref a 2)(list-ref b 2)))))) (if (null? sorted) #f ;; we'll want to wait until extra servers have exited (car sorted)))) (define (tt:send-receive ttdat conn cmd run-id params) (let* ((host-port (tt-conn-host-port conn)) ;; (conc (tt-conn-host conn)":"(tt-conn-port conn))) (host (tt-conn-host conn)) (port (tt-conn-port conn)) (dat (list cmd run-id params #f))) ;; no meta data yet (tt:send-receive-direct host port dat))) (define (tt:send-receive-direct host port dat) (assert (number? port) "FATAL: tt:send-receive-direct called with port not a number "port) (handle-exceptions exn #f ;; Add condition-case or better handling here (let-values (((inp oup)(tcp-connect host port))) (let ((res (if (and inp oup) (begin (serialize dat oup) (close-output-port oup) (deserialize inp)) ))) (close-input-port inp) res)))) ;;====================================================================== ;; server ;;====================================================================== (define (tt:sync-dbs ttdat) #f) ;; start the listener and start responding to requests ;; ;; NOTE: organise by dbfname, not run-id so we don't need ;; to pull in more modules ;; ;; This is the routine called in megatest.scm to start a server ;; ;; Server viability is checked in keep-running. Blindly start and run here. ;; (define (tt:start-server areapath run-id dbfname-in handler keys) (assert areapath "FATAL: areapath not provided for tt:start-server") ;; is there already a server for this dbfile? Then exit. (let* ((ttdat (make-tt areapath: areapath)) (dbfname (or dbfname-in (dbmod:run-id->dbfname run-id)))) ;; (servers (tt:find-server areapath dbfname))) ;; should use tt:get-current-server-info instead ;; (if (null? servers) (let* ((dbstruct (dbmod:open-dbmoddb areapath run-id dbfname (dbfile:db-init-proc) keys))) (tt-handler-set! ttdat (handler dbstruct)) (let* ((tcp-thread (make-thread (lambda () (tt:start-tcp-server ttdat)) ;; start the tcp-server which applies handler to incoming data "tcp-server-thread")) (run-thread (make-thread (lambda () (tt:keep-running ttdat dbfname dbstruct))))) (thread-start! tcp-thread) (thread-start! run-thread) (thread-join! run-thread) ;; run thread will exit on timeout or other conditions (exit))) ;;(begin ;; (debug:print 0 *default-log-port* "INFO: found server(s) already running for db "dbfname", "(string-intersperse servers ",")" Exiting.") ;; (exit))))) )) (define (tt:keep-running ttdat dbfname dbstruct) ;; verfiy conn for ready ;; listener socket has been started by this stage ;; wait for a port before creating the registration file ;; (let* ((db-locked-in #f) (areapath (tt-areapath ttdat)) (nosyncdbpath (conc areapath"/.megatest")) (cleanup (lambda () (if (tt-cleanup-proc ttdat) ((tt-cleanup-proc ttdat))) (dbfile:with-no-sync-db nosyncdbpath (lambda (db) (db:no-sync-del! db dbfname)))))) (set! *server-info* ttdat) (let loop ((count 0)) (if (> count 240) (begin (debug:print 0 *default-log-port* "FATAL: Could not start a tcp server, giving up.") (exit 1)) (if (not (tt-port ttdat)) ;; no connection yet (begin (thread-sleep! 0.25) (loop (+ count 1)))))) (tt:create-server-registration-file ttdat dbfname) ;; now start watching the last-access, if it hasn't been touched ;; in over ten seconds we exit (thread-sleep! 0.05) ;; any real need for delay here? (let loop () (let* ((servers (tt:get-server-info-sorted ttdat dbfname)) (ok (cond ((null? servers) #f) ;; not ok ((equal? (list-ref (car servers) 6) ;; compare the servinfofile (tt-servinf-file ttdat)) (let* ((res (if db-locked-in #t (let* ((success (dbfile:with-no-sync-db nosyncdbpath (lambda (db) (db:no-sync-get-lock-with-id db dbfname (tt-servinf-file ttdat)))))) (if success (begin (tt-state-set! ttdat 'running) (debug:print 0 *default-log-port* "Got server lock for " dbfname) (set! db-locked-in #t) #t) (begin (debug:print 0 *default-log-port* "Failed to get server lock for "dbfname) #f)))))) (if (and res (common:low-noise-print 120 "top server message")) (debug:print-info 0 *default-log-port* "Keep running, I'm the top server for " dbfname" on "(tt-host ttdat)":"(tt-port ttdat))) res)) (else (debug:print-info 0 *default-log-port* "I'm not the lead server: "servers) (let* ((leadsrv (car servers))) (match leadsrv ((host port startseconds server-id pid dbfname servinfofile) (let* ((res (tt:ping host port server-id))) (debug:print-info 0 *default-log-port* "Ping to "host":"port", with server-id "server-id ", and file "servinfofile" returned "res) (if res #f ;; not the server, but all good, want to exit (if (and (file-exists? servinfofile) (> (- (current-seconds)(file-modification-time servinfofile)) 30)) (begin ;; can't ping and file has been on disk 15 seconds, go ahead and try to remove it (debug:print-info 0 *default-log-port* "Removing apparently dead server info file: "servinfofile) (delete-file* servinfofile) #t) ;; not the server but the server is not reachable (begin (debug:print 0 *default-log-port* "I'm not the server but could not ping "host":"port", trying again.") (thread-sleep! 1) ;; just because #t))))) (else ;; should never get here (debug:print 0 *default-log-port* "BAD SERVER RECORD: "leadsrv) (assert #f "Bad server record "leadsrv)))))))) (if ok ;; (if (> *api-process-request-count* 0) ;; have requests in flight ;; (tt-last-access-set! ttdat (current-seconds))) (tt-last-access-set! ttdat *db-last-access*) ;; bit silly, just use db-last-access (begin (cleanup) (exit))) (let* ((last-update (dbr:dbstruct-last-update dbstruct)) (curr-secs (current-seconds))) (if (and (eq? (tt-state ttdat) 'running) (> (- curr-secs last-update) 3)) ;; every 3-4 seconds update the db? maybe this should be refresh the inmem? (begin (set! (file-modification-time (tt-servinf-file ttdat)) (current-seconds)) ((dbr:dbstruct-sync-proc dbstruct) last-update) (dbr:dbstruct-last-update-set! dbstruct curr-secs)))) (if (< (- (current-seconds) (tt-last-access ttdat)) (tt-server-timeout-param)) (begin (thread-sleep! 5) (loop))))) (cleanup) (debug:print 0 *default-log-port* "INFO: Server timed out, exiting."))) ;; ;; given an already set up uconn start the cmd-loop ;; ;; ;; (define (tt:cmd-loop ttdat) ;; (let* ((serv-listener (-socket uconn)) ;; (listener (lambda () ;; (let loop ((state 'start)) ;; (let-values (((inp oup)(tcp-accept serv-listener))) ;; ;; (mutex-lock! *send-mutex*) ;; DOESN'T SEEM TO HELP ;; (let* ((rdat (deserialize inp)) ;; '(my-host-port qrykey cmd params) ;; (resp (ulex-handler uconn rdat))) ;; (serialize resp oup) ;; (close-input-port inp) ;; (close-output-port oup) ;; ;; (mutex-unlock! *send-mutex*) ;; DOESN'T SEEM TO HELP ;; ) ;; (loop state)))))) ;; ;; start N of them ;; (let loop ((thnum 0) ;; (threads '())) ;; (if (< thnum 100) ;; (let* ((th (make-thread listener (conc "listener" thnum)))) ;; (thread-start! th) ;; (loop (+ thnum 1) ;; (cons th threads))) ;; (map thread-join! threads))))) ;; ;; ;; ;; (define (wait-and-close uconn) ;; (thread-join! (udat-cmd-thread uconn)) ;; (tcp-close (udat-socket uconn))) ;; ;; (define (tt:shutdown-server ttdat) (let* ((cleanproc (tt-cleanup-proc ttdat))) (tt-state-set! ttdat 'shutdown) (if cleanproc (cleanproc)) (tcp-close (tt-socket ttdat)) ;; close up ports here )) ;; (define (wait-and-close uconn) ;; (thread-join! (tt-cmd-thread uconn)) ;; (tcp-close (tt-socket uconn))) ;; return servid ;; side-effects: ;; ttdat-cleanup-proc is populated with function to remove the serverinfo file (define (tt:create-server-registration-file ttdat dbfname) (let* ((areapath (tt-areapath ttdat)) (servdir (tt:get-servinfo-dir areapath)) (host (tt-host ttdat)) (port (tt-port ttdat)) (servinf (conc servdir"/"host":"port"-"(current-process-id)":"dbfname)) (serv-id (tt:mk-signature areapath)) (clean-proc (lambda () (delete-file* servinf)))) (assert (and host port) "FATAL: tt:create-server-registration-file called with no conn, dbfname="dbfname) (tt-cleanup-proc-set! ttdat clean-proc) (tt-servinf-file-set! ttdat servinf) (with-output-to-file servinf (lambda () (print "SERVER STARTED: "host":"port" AT "(current-seconds)" server-id: "serv-id" pid: "(current-process-id)" dbfname: "dbfname))) serv-id)) ;; find valid server ;; get servers listed, last part of name must match :<dbfname> ;; if more than one, wait one second and look again ;; future: ping oldest, if alive remove other :<dbfname> files ;; (define (tt:find-server areapath dbfname) (let* ((servdir (tt:get-servinfo-dir areapath)) (sfiles (glob (conc servdir"/*:"dbfname)))) sfiles)) ;; given a path to a server info file return: host port startseconds server-id pid dbfname logf ;; example of what it's looking for in the log file: ;; SERVER STARTED: 10.38.175.67:50216 AT 1616502350.0 server-id: 4907e90fc55c7a09694e3f658c639cf4 ;; (define (tt:server-get-info logf) (let ((server-rx (regexp "^SERVER STARTED: (\\S+):(\\d+) AT ([\\d\\.]+) server-id: (\\S+) pid: (\\d+) dbfname: (\\S+)")) ;; SERVER STARTED: host:port AT timesecs server id (dbprep-rx (regexp "^SERVER: dbprep")) (dbprep-found 0) (bad-dat (list #f #f #f #f #f #f logf))) (let ((fdat (handle-exceptions exn (begin ;; WARNING: this is potentially dangerous to blanket ignore the errors (debug:print-info 0 *default-log-port* "Unable to get server info from "logf", exn=" exn) '()) ;; no idea what went wrong, call it a bad server, return empty list (with-input-from-file logf read-lines)))) (if (null? fdat) ;; bad data, return bad-dat bad-dat (let loop ((inl (car fdat)) (tail (cdr fdat)) (lnum 0)) (let ((mlst (string-match server-rx inl)) (dbprep (string-match dbprep-rx inl))) (if dbprep (set! dbprep-found 1)) (if (not mlst) (if (> lnum 500) ;; give up if more than 500 lines of server log read bad-dat (if (null? tail) bad-dat (loop (car tail)(cdr tail)(+ lnum 1)))) (match mlst ;; have a not null list ((_ host port start server-id pid dbfname) (list host (string->number port) (string->number start) server-id (string->number pid) dbfname logf)) (else (debug:print 0 *default-log-port* "ERROR: did not recognise SERVER line info "mlst) bad-dat))))))))) ;; Given an area path, start a server process ### NOTE ### > file 2>&1 ;; if the target-host is set ;; try running on that host ;; incidental: rotate logs in logs/ dir. ;; (define (tt:server-process-run areapath testsuite mtexe run-id #!key (profile-mode "")) ;; areapath is *toppath* for a given testsuite area (assert areapath "FATAL: tt:server-process-run called without areapath defined.") (assert testsuite "FATAL: tt:server-process-run called without testsuite defined.") (assert mtexe "FATAL: tt:server-process-run called without mtexe defined.") ;; mtest -server - -m testsuite:ext-tests -db 6.db (let* ((dbfname (dbmod:run-id->dbfname run-id)) (load (get-normalized-cpu-load)) (nrun (number-of-processes-running (conc "mtest.*server.*"testsuite".*"dbfname)))) (cond ((> load 2.0) (debug:print 0 *default-log-port* "Normalized load "load" is over the limit of 2.0. Not starting a server.") (thread-sleep! 1)) ((> nrun 100) (debug:print 0 *default-log-port* nrun" servers running on this host, not starting another.") (thread-sleep! 1)) (else (if (not (file-exists? (conc areapath"/logs"))) (create-directory (conc areapath"/logs") #t)) (let* ((logfile (conc areapath "/logs/server.log")) ;; -" curr-pid "-" target-host ".log")) (cmdln (conc mtexe " -server - ";; (or target-host "-") " -m testsuite:" testsuite ;; " -run-id " (or run-id "main") ;; NO, we do NOT want to have run id as part of this " -db " dbfname ;; (dbmod:run-id->dbfname run-id) " " profile-mode ))) ;; (conc " >> " logfile " 2>&1 &"))))) ;; we want the remote server to start in *toppath* so push there ;; (push-directory areapath) ;; use cd in the command line instead (debug:print 0 *default-log-port* "INFO: Trying to start server in tcp mode (" cmdln ") at "(common:human-time)" for "areapath) ;; (debug:print 0 *default-log-port* "INFO: starting server at " (common:human-time)) (setenv "NBFAKE_QUIET" "yes") ;; BUG: change to with-environment-variable ... (setenv "NBFAKE_LOG" logfile) (system (conc "cd "areapath" ; nbfake " cmdln)) (unsetenv "NBFAKE_QUIET") (unsetenv "NBFAKE_LOG") ;;(pop-directory) ))))) ;;====================================================================== ;; tcp connection stuff ;;====================================================================== ;; find a port and start tcp-server. This only starts the tcp portion of ;; the server, look at (tt:start-server ...) above for the entry point ;; for the entire server system ;; (define (tt:start-tcp-server ttdat) (setup-listener ttdat) (let* ((socket (tt-socket ttdat)) (handler (tt-handler ttdat))) ((make-tcp-server socket handler) #f ;; yes, send error messages to std-err ))) ;; create a tcp listener and return a populated udat struct with ;; my port, address, hostname, pid etc. ;; return #f if fail to find a port to allocate. ;; ;; if udata-in is #f create the record ;; if there is already a serv-listener return the udata ;; (define (setup-listener uconn #!optional (port 4242)) (assert (tt? uconn) "FATAL: setup-listener called with wrong struct "uconn) (handle-exceptions exn (if (< port 65535) (begin (thread-sleep! 0.25) (setup-listener uconn (+ port 1))) #f) (connect-listener uconn port))) (define (connect-listener uconn port) ;; (tcp-listener-socket LISTENER)(socket-name so) ;; sockaddr-address, sockaddr-port, sockaddr->string (let* ((tlsn (tcp-listen port 1000 #f)) ;; (tcp-listen TCPPORT [BACKLOG [HOST]]) (addr (tt:get-best-guess-address (get-host-name)))) ;; (get-my-best-address))) ;; (hostinfo-addresses (host-information (current-hostname))) (tt-port-set! uconn port) (tt-host-set! uconn addr) (tt-host-port-set! uconn (conc addr":"port)) (tt-socket-set! uconn tlsn) uconn)) ;;====================================================================== ;; utils ;;====================================================================== ;; Generate a unique signature for this server (define (tt:mk-signature areapath) (message-digest-string (md5-primitive) (with-output-to-string (lambda () (write (list areapath (current-process-id) (argv))))))) (define (tt:get-best-guess-address hostname) (let ((res #f)) (for-each (lambda (adr) (if (not (eq? (u8vector-ref adr 0) 127)) (set! res adr))) ;; NOTE: This can fail when there is no mention of the host in /etc/hosts. FIXME (vector->list (hostinfo-addresses (hostname->hostinfo hostname)))) (string-intersperse (map number->string (u8vector->list (if res res (hostname->ip hostname)))) "."))) (define (tt:get-servinfo-dir areapath) (let* ((spath (conc areapath"/.servinfo"))) (if (not (file-exists? spath)) (create-directory spath #t)) spath)) ;;====================================================================== ;; network utilities ;;====================================================================== ;; NOTE: Look at address-info egg as alternative to some of this (define (rate-ip ipaddr) (regex-case ipaddr ( "^127\\..*" _ 0 ) ( "^(10\\.0|192\\.168)\\..*" _ 1 ) ( else 2 ) )) ;; Change this to bias for addresses with a reasonable broadcast value? ;; (define (ip-pref-less? a b) (> (rate-ip a) (rate-ip b))) (define (get-my-best-address) (let ((all-my-addresses (get-all-ips))) (cond ((null? all-my-addresses) (get-host-name)) ;; no interfaces? ((eq? (length all-my-addresses) 1) (car all-my-addresses)) ;; only one to choose from, just go with it (else (car (sort all-my-addresses ip-pref-less?)))))) (define (get-all-ips-sorted) (sort (get-all-ips) ip-pref-less?)) (define (get-all-ips) (map address-info-host (filter (lambda (x) (equal? (address-info-type x) "tcp")) (address-infos (get-host-name))))) ) |
Modified tdb.scm from [6edff6262d] to [0211217236].
30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | + + | (declare (unit tdb)) (declare (uses common)) (declare (uses keys)) (declare (uses ods)) (declare (uses client)) (declare (uses mt)) (declare (uses db)) (declare (uses commonmod)) (import commonmod) (include "common_records.scm") (include "db_records.scm") (include "key_records.scm") (include "run_records.scm") ;;====================================================================== |
Modified tests.scm from [5c2006972a] to [b17b9fa8b7].
1964 1965 1966 1967 1968 1969 1970 | 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 | - + - + | ;;====================================================================== ;; test steps ;;====================================================================== ;; teststep-set-status! used to be here (define (test-get-kill-request run-id test-id) ;; run-id test-name itemdat) |
Added transport-mode.scm.template version [7b4174ac3b].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | + + + + + + + + + + + + + + + + + + + + + + | ;;====================================================================== ;; set up transport, db cache and sync methods ;; ;; sync-method: 'original, 'attach or 'none ;; cache-method: 'tmp, 'inmem or 'none ;; rmt:transport-mode: 'http, 'tcp, 'nfs ;; ;; NOTE: NOT ALL COMBINATIONS WORK ;; ;;====================================================================== ;; uncomment this block to test without tcp or inmem ;; (dbfile:sync-method 'none) ;; (dbfile:cache-method 'none) ;; (rmt:transport-mode 'nfs) ;; uncomment this block to test with tcp and inmem (dbfile:sync-method 'original) ;; attach) (dbfile:cache-method 'inmem) (rmt:transport-mode 'tcp) |
Added ulex/dbmgr.scm version [afcee6ee9f].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | ;;====================================================================== ;; Copyright 2022, Matthew Welland. ;; ;; This file is part of Megatest. ;; ;; Megatest is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; ;; Megatest is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with Megatest. If not, see <http://www.gnu.org/licenses/>. ;;====================================================================== (declare (unit dbmgrmod)) (declare (uses ulex)) (declare (uses apimod)) (declare (uses pkts)) (declare (uses commonmod)) (declare (uses dbmod)) (declare (uses mtargs)) (declare (uses portloggermod)) (declare (uses debugprint)) (module dbmgrmod * (import scheme chicken.base chicken.condition chicken.file chicken.format chicken.port chicken.process chicken.process-context chicken.process-context.posix chicken.sort chicken.string chicken.time (prefix sqlite3 sqlite3:) matchable md5 message-digest regex s11n srfi-1 srfi-18 srfi-69 system-information typed-records pkts ulex commonmod apimod dbmod debugprint (prefix mtargs args:) portloggermod ) ;; Configurations for server ;; (tcp-buffer-size 2048) ;; (max-connections 2048) ;; info about me as a listener and my connections to db servers ;; stored (for now) in *db-serv-info* ;; (defstruct servdat (host #f) (port #f) (uuid #f) (dbfile #f) (uconn #f) ;; this is the listener *FOR THIS PROCESS* (mode #f) (status 'starting) (trynum 0) ;; count the number of ports we've tried (conns (make-hash-table)) ;; apath/dbname => conndat ) (define *db-serv-info* (make-servdat)) (define (servdat->url sdat) (conc (servdat-host sdat)":"(servdat-port sdat))) ;; db servers contact info ;; (defstruct conndat (apath #f) (dbname #f) (fullname #f) (hostport #f) (ipaddr #f) (port #f) (srvpkt #f) (srvkey #f) (lastmsg 0) (expires 0)) (define *srvpktspec* `((server (host . h) (port . p) (servkey . k) (pid . i) (ipaddr . a) (dbpath . d)))) ;;====================================================================== ;; S U P P O R T F U N C T I O N S ;;====================================================================== ;; set up the api proc, seems like there should be a better place for this? ;; ;; IS THIS NEEDED ANYMORE? TODO - REMOVE IF POSSIBLE ;; ;; (define api-proc (make-parameter conc)) ;; (api-proc api:execute-requests) ;; do we have a connection to apath dbname and ;; is it not expired? then return it ;; ;; else setup a connection ;; ;; if that fails, return '(#f "some reason") ;; NB// convert to raising an exception ;; (define (rmt:get-conn remdat apath dbname) (let* ((fullname (db:dbname->path apath dbname))) (hash-table-ref/default (servdat-conns remdat) fullname #f))) (define (rmt:drop-conn remdat apath dbname) (let* ((fullname (db:dbname->path apath dbname))) (hash-table-delete! (servdat-conns remdat) fullname))) (define (rmt:find-main-server uconn apath dbname) (let* ((pktsdir (get-pkts-dir apath)) (all-srvpkts (get-all-server-pkts pktsdir *srvpktspec*)) (viable-srvs (get-viable-servers all-srvpkts dbname))) (get-the-server uconn apath viable-srvs))) (define *connstart-mutex* (make-mutex)) (define *last-main-start* 0) ;; looks for a connection to main, returns if have and not exired ;; creates new otherwise ;; ;; connections for other servers happens by requesting from main ;; ;; TODO: This is unnecessarily re-creating the record in the hash table ;; (define (rmt:open-main-connection remdat apath) (let* ((fullpath (db:dbname->path apath ".db/main.db")) (conns (servdat-conns remdat)) (conn (rmt:get-conn remdat apath ".db/main.db")) ;; (hash-table-ref/default conns fullpath #f)) ;; TODO - create call for this (start-rmt:run (lambda () (let* ((th1 (make-thread (lambda ()(rmt:run (get-host-name))) "non-db mode server"))) (thread-start! th1) (thread-sleep! 1) (let loop ((count 0)) (assert (< count 30) "FATAL: responder failed to initialize in rmt:open-main-connection") (if (or (not *db-serv-info*) (not (servdat-uconn *db-serv-info*))) (begin (thread-sleep! 1) (loop (+ count 1))) (begin (servdat-mode-set! *db-serv-info* 'non-db) (servdat-uconn *db-serv-info*))))))) (myconn (servdat-uconn *db-serv-info*))) (cond ((not myconn) (start-rmt:run) (rmt:open-main-connection remdat apath)) ((and conn ;; conn is NOT a socket, just saying ... (< (current-seconds) (conndat-expires conn))) #t) ;; we are current and good to go - we'll deal elsewhere with a server that was killed or died ((and conn (>= (current-seconds)(conndat-expires conn))) (debug:print-info 0 *default-log-port* "connection to "fullpath" server expired. Reconnecting.") (rmt:drop-conn remdat apath ".db/main.db") ;; (rmt:open-main-connection remdat apath)) (else ;; Below we will find or create and connect to main (debug:print-info 0 *default-log-port* "rmt:open-main-connection - starting from scratch") (let* ((dbname (db:run-id->dbname #f)) (the-srv (rmt:find-main-server myconn apath dbname)) (start-main-srv (lambda () ;; call IF there is no the-srv found (mutex-lock! *connstart-mutex*) (if (> (- (current-seconds) *last-main-start*) 5) ;; at least four seconds since last attempt to start main server (begin (api:run-server-process apath dbname) (set! *last-main-start* (current-seconds)) (thread-sleep! 1)) (thread-sleep! 0.25)) (mutex-unlock! *connstart-mutex*) (rmt:open-main-connection remdat apath) ;; TODO: Add limit to number of tries ))) (if (not the-srv) ;; have server, try connecting to it (start-main-srv) (let* ((srv-addr (server-address the-srv)) ;; need serv (ipaddr (alist-ref 'ipaddr the-srv)) (port (alist-ref 'port the-srv)) (srvkey (alist-ref 'servkey the-srv)) (fullpath (db:dbname->path apath dbname)) (new-the-srv (make-conndat apath: apath dbname: dbname fullname: fullpath hostport: srv-addr ;; socket: (open-nn-connection srv-addr) - TODO - open ulex connection? ipaddr: ipaddr port: port srvpkt: the-srv srvkey: srvkey ;; generated by rmt:get-signature on the server side lastmsg: (current-seconds) expires: (+ (current-seconds) (server:expiration-timeout) -2) ;; this needs to be gathered during the ping ))) (hash-table-set! conns fullpath new-the-srv))) #t))))) ;; NB// sinfo is a servdat struct ;; (define (rmt:general-open-connection sinfo apath dbname #!key (num-tries 5)) (assert (not (equal? dbname ".db/main.db")) "ERROR: general-open-connection should never be called with main as the db") (let* ((mdbname ".db/main.db") ;; (db:run-id->dbname #f)) TODO: put this back to the lookup when stable (fullname (db:dbname->path apath dbname)) (conns (servdat-conns sinfo)) (mconn (rmt:get-conn sinfo apath ".db/main.db")) (dconn (rmt:get-conn sinfo apath dbname))) #;(if (and mconn (not (debug:print-logger))) (begin (debug:print-info 0 *default-log-port* "Turning on logging to main, look in logs dir for main log.") (debug:print-logger rmt:log-to-main))) (cond ((and mconn dconn (< (current-seconds)(conndat-expires dconn))) #t) ;; good to go ((not mconn) ;; no channel open to main? open it... (rmt:open-main-connection sinfo apath) (rmt:general-open-connection sinfo apath dbname num-tries: (- num-tries 1))) ((not dconn) ;; no channel open to dbname? (let* ((res (rmt:send-receive-real sinfo apath mdbname 'get-server `(,apath ,dbname)))) (case res ((server-started) (if (> num-tries 0) (begin (thread-sleep! 2) (rmt:general-open-connection sinfo apath dbname num-tries: (- num-tries 1))) (begin (debug:print-error 0 *default-log-port* "Failed to start servers needed or open channel to "apath", "dbname) (exit 1)))) (else (if (list? res) ;; server has been registered and the info was returned. pass it on. (begin ;; ("192.168.0.9" 53817 ;; "5e34239f48e8973b3813221e54701a01" "24310" ;; "192.168.0.9" ;; "/home/matt/data/megatest/tests/simplerun" ;; ".db/1.db") (match res ((host port servkey pid ipaddr apath dbname) (debug:print-info 0 *default-log-port* "got "res) (hash-table-set! conns fullname (make-conndat apath: apath dbname: dbname hostport: (conc host":"port) ;; socket: (open-nn-connection (conc host":"port)) ;; TODO - open ulex connection? ipaddr: ipaddr port: port srvkey: servkey lastmsg: (current-seconds) expires: (+ (current-seconds) (server:expiration-timeout) -2)))) (else (debug:print-info 0 *default-log-port* "return data from starting server did not match host port servkey pid ipaddr apath dbname " res))) res) (begin (debug:print-info 0 *default-log-port* "Unexpected result: " res) res))))))) #t)) ;;====================================================================== ;; FOR DEBUGGING SET TO #t ;; (define *localmode* #t) (define *localmode* #f) (define *dbstruct* (make-dbr:dbstruct)) ;; Defaults to current area ;; (define (rmt:send-receive cmd rid params #!key (attemptnum 1)(area-dat #f)) (let* ((apath *toppath*) (sinfo *db-serv-info*) (dbname (db:run-id->dbname rid))) (if *localmode* (api:execute-requests *dbstruct* cmd params) (begin (rmt:open-main-connection sinfo apath) (if rid (rmt:general-open-connection sinfo apath dbname)) #;(if (not (member cmd '(log-to-main))) (debug:print-info 0 *default-log-port* "rmt:send-receive "cmd" params="params)) (rmt:send-receive-real sinfo apath dbname cmd params))))) ;; db is at apath/.db/dbname, rid is an intermediary solution and will be removed ;; sometime in the future ;; (define (rmt:send-receive-real sinfo apath dbname cmd params) (assert (not (eq? 'primordial (thread-name (current-thread)))) "FATAL: Do not call rmt:send-receive-real in the primodial thread.") (let* ((cdat (rmt:get-conn sinfo apath dbname))) (assert cdat "FATAL: rmt:send-receive-real called without the needed channels opened") (let* ((uconn (servdat-uconn sinfo)) ;; get the interface to ulex ;; then send-receive using the ulex layer to host-port stored in cdat (res (send-receive uconn (conndat-hostport cdat) cmd params)) #;(th1 (make-thread (lambda () (set! res (send-receive uconn (conndat-hostport cdat) cmd params))) "send-receive thread"))) ;; (thread-start! th1) ;; (thread-join! th1) ;; gratuitious thread stuff is so that mailbox is not used in primordial thead ;; since we accessed the server we can bump the expires time up (conndat-expires-set! cdat (+ (current-seconds) (server:expiration-timeout) -10)) ;; ten second margin for network time misalignments etc. res))) ;; db is at apath/.db/dbname, rid is an intermediary solution and will be removed ;; sometime in the future. ;; ;; Purpose - call the main.db server and request a server be started ;; for the given area path and dbname ;; (define (rmt:print-db-stats) (let ((fmtstr "~40a~7-d~9-d~20,2-f")) ;; "~20,2-f" (debug:print 18 *default-log-port* "DB Stats, "(seconds->year-week/day-time (current-seconds))"\n=====================") (debug:print 18 *default-log-port* (format #f "~40a~8a~10a~10a" "Cmd" "Count" "TotTime" "Avg")) (for-each (lambda (cmd) (let ((cmd-dat (hash-table-ref *db-stats* cmd))) (debug:print 18 *default-log-port* (format #f fmtstr cmd (vector-ref cmd-dat 0) (vector-ref cmd-dat 1) (/ (vector-ref cmd-dat 1)(vector-ref cmd-dat 0)))))) (sort (hash-table-keys *db-stats*) (lambda (a b) (> (vector-ref (hash-table-ref *db-stats* a) 0) (vector-ref (hash-table-ref *db-stats* b) 0))))))) (define (rmt:get-max-query-average run-id) (mutex-lock! *db-stats-mutex*) (let* ((runkey (conc "run-id=" run-id " ")) (cmds (filter (lambda (x) (substring-index runkey x)) (hash-table-keys *db-stats*))) (res (if (null? cmds) (cons 'none 0) (let loop ((cmd (car cmds)) (tal (cdr cmds)) (max-cmd (car cmds)) (res 0)) (let* ((cmd-dat (hash-table-ref *db-stats* cmd)) (tot (vector-ref cmd-dat 0)) (curravg (/ (vector-ref cmd-dat 1) (vector-ref cmd-dat 0))) ;; count is never zero by construction (currmax (max res curravg)) (newmax-cmd (if (> curravg res) cmd max-cmd))) (if (null? tal) (if (> tot 10) (cons newmax-cmd currmax) (cons 'none 0)) (loop (car tal)(cdr tal) newmax-cmd currmax))))))) (mutex-unlock! *db-stats-mutex*) res)) ;; host and port are used to ensure we are remove proper records (define (rmt:server-shutdown host port) (let ((dbfile (servdat-dbfile *db-serv-info*))) (debug:print-info 0 *default-log-port* "dbfile is "dbfile) (if dbfile (let* ((am-server (args:get-arg "-server")) (dbfile (args:get-arg "-db")) (apath *toppath*) #;(sinfo *remotedat*)) ;; foundation for future fix (if *dbstruct-db* (let* ((dbdat (db:get-dbdat *dbstruct-db* apath dbfile)) (db (dbr:dbdat-db dbdat)) (inmem (dbr:dbdat-db dbdat)) ;; WRONG ) ;; do a final sync here (debug:print-info 0 *default-log-port* "Doing final sync for "apath" "dbfile" at "(current-seconds)) (db:sync-inmem->disk *dbstruct-db* apath dbfile force-sync: #t) ;; let's finalize here (debug:print-info 0 *default-log-port* "Finalizing db and inmem") (if (sqlite3:database? db) (sqlite3:finalize! db) (debug:print-info 0 *default-log-port* "in rmt:server-shutdown, db is not a database, not finalizing...")) (if (sqlite3:database? inmem) (sqlite3:finalize! inmem) (debug:print-info 0 *default-log-port* "in rmt:server-shutdown, inmem is not a database, not finalizing...")) (debug:print-info 0 *default-log-port* "Finalizing db and inmem complete")) (debug:print-info 0 *default-log-port* "Db was never opened, no cleanup to do.")) (if (not am-server) (debug:print-info 0 *default-log-port* "I am not a server, should NOT get here!") (if (string-match ".*/main.db$" dbfile) (let ((pkt-file (conc (get-pkts-dir *toppath*) "/" (servdat-uuid *db-serv-info*) ".pkt"))) (debug:print-info 0 *default-log-port* "removing pkt "pkt-file) (delete-file* pkt-file) (debug:print-info 0 *default-log-port* "Releasing lock (if any) for "dbfile ", host "host", port "port) (db:with-lock-db (servdat-dbfile *db-serv-info*) (lambda (dbh dbfile) (db:release-lock dbh dbfile host port)))) ;; I'm not the server - should not have a lock to remove (let* ((sdat *db-serv-info*) ;; we have a run-id server (host (servdat-host sdat)) (port (servdat-port sdat)) (uuid (servdat-uuid sdat)) (res (rmt:deregister-server *db-serv-info* *toppath* host port uuid dbfile))) (debug:print-info 0 *default-log-port* "deregistered-server, res="res) (debug:print-info 0 *default-log-port* "deregistering server "host":"port" with uuid "uuid) ))))))) (define (common:run-sync?) ;; (and (common:on-homehost?) (args:get-arg "-server")) (define *rmt:run-mutex* (make-mutex)) (define *rmt:run-flag* #f) ;; Main entry point to start a server. was start-server (define (rmt:run hostn) (mutex-lock! *rmt:run-mutex*) (if *rmt:run-flag* (begin (debug:print-warn 0 *default-log-port* "rmt:run already running.") (mutex-unlock! *rmt:run-mutex*)) (begin (set! *rmt:run-flag* #t) (mutex-unlock! *rmt:run-mutex*) ;; ;; Configurations for server ;; (tcp-buffer-size 2048) ;; (max-connections 2048) (debug:print 2 *default-log-port* "PID: "(current-process-id)". Attempting to start the server ...") (if (and *db-serv-info* (servdat-uconn *db-serv-info*)) (let* ((uconn (servdat-uconn *db-serv-info*))) (wait-and-close uconn)) (let* ((port (portlogger:open-run-close portlogger:find-port)) (handler-proc (lambda (rem-host-port qrykey cmd params) ;; (set! *db-last-access* (current-seconds)) (assert (list? params) "FATAL: handler called with non-list params") (assert (args:get-arg "-server") "FATAL: handler called on non-server side. cmd="cmd", params="params) (debug:print 0 *default-log-port* "handler call: "cmd", params="params) (api:execute-requests *dbstruct-db* cmd params)))) ;; (api:process-request *dbstuct-db* (if (not *db-serv-info*) (set! *db-serv-info* (make-servdat host: hostn port: port))) (let* ((uconn (run-listener handler-proc port)) (rport (udat-port uconn))) ;; the real port (servdat-host-set! *db-serv-info* hostn) (servdat-port-set! *db-serv-info* rport) (servdat-uconn-set! *db-serv-info* uconn) (wait-and-close uconn) (db:print-current-query-stats) ))) (let* ((host (servdat-host *db-serv-info*)) (port (servdat-port *db-serv-info*)) (mode (or (servdat-mode *db-serv-info*) "non-db"))) ;; server exit stuff here ;; (rmt:server-shutdown host port) - always do in on-exit ;; (portlogger:open-run-close portlogger:set-port port "released") ;; moved to on-exit (debug:print-info 0 *default-log-port* "Server "host":"port" mode "mode"shutdown complete. Exiting") )))) ;;====================================================================== ;; S E R V E R U T I L I T I E S ;;====================================================================== ;;====================================================================== ;; NEW SERVER METHOD ;;====================================================================== ;; only use for main.db - need to re-write some of this :( ;; (define (get-lock-db sdat dbfile host port) (assert host "FATAL: get-lock-db called with host not set.") (assert port "FATAL: get-lock-db called with port not set.") (let* ((dbh (db:open-run-db dbfile db:initialize-db)) ;; open-run-db creates a standard db with schema used by all situations (res (db:get-iam-server-lock dbh dbfile host port)) (uconn (servdat-uconn sdat))) ;; res => list then already locked, check server is responsive ;; => #t then sucessfully got the lock ;; => #f reserved for future use as to indicate something went wrong (match res ((owner_pid owner_host owner_port event_time) (if (server-ready? uconn (conc owner_host":"owner_port) "abc") #f ;; locked by someone else (begin ;; locked by someone dead and gone (debug:print 0 *default-log-port* "WARNING: stale lock - have to steal it. This may fail.") (db:steal-lock-db dbh dbfile port)))) (#t #t) ;; placeholder so that we don't touch res if it is #t (else (set! res #f))) (sqlite3:finalize! dbh) res)) (define (register-server pkts-dir pkt-spec host port servkey ipaddr dbpath) (let* ((pkt-dat `((host . ,host) (port . ,port) (servkey . ,servkey) (pid . ,(current-process-id)) (ipaddr . ,ipaddr) (dbpath . ,dbpath))) (uuid (write-alist->pkt pkts-dir pkt-dat pktspec: pkt-spec ptype: 'server))) (debug:print 0 *default-log-port* "Server on "host":"port" registered in pkt "uuid) uuid)) (define (get-pkts-dir #!optional (apath #f)) (let* ((effective-toppath (or *toppath* apath))) (assert effective-toppath "ERROR: get-pkts-dir called without *toppath* set. Exiting.") (let* ((pdir (conc effective-toppath "/.meta/srvpkts"))) (if (file-exists? pdir) pdir (begin (handle-exceptions ;; this exception handler should NOT be needed but ... exn pdir (create-directory pdir #t)) pdir))))) ;; given a pkts dir read ;; (define (get-all-server-pkts pktsdir-in pktspec) (let* ((pktsdir (if (file-exists? pktsdir-in) pktsdir-in (begin (create-directory pktsdir-in #t) pktsdir-in))) (all-pkt-files (glob (conc pktsdir "/*.pkt")))) (map (lambda (pkt-file) (read-pkt->alist pkt-file pktspec: pktspec)) all-pkt-files))) (define (server-address srv-pkt) (conc (alist-ref 'host srv-pkt) ":" (alist-ref 'port srv-pkt))) (define (server-ready? uconn host-port key) ;; server-address is host:port (let* ((params `((cmd . ping)(key . ,key))) (data `((cmd . ping) (key . ,key) (params . ,params))) ;; I don't get it. (res (send-receive uconn host-port 'ping data))) (if (eq? res 'ack) ;; yep, likely it is who we want on the other end res #f))) ;; (begin (debug:print-info 0 *default-log-port* "server-ready? => "res) #f)))) ; from the pkts return servers associated with dbpath ;; NOTE: Only one can be alive - have to check on each ;; in the list of pkts returned ;; (define (get-viable-servers serv-pkts dbpath) (let loop ((tail serv-pkts) (res '())) (if (null? tail) res ;; NOTE: sort by age so oldest is considered first (let* ((spkt (car tail))) (loop (cdr tail) (if (equal? dbpath (alist-ref 'dbpath spkt)) (cons spkt res) res)))))) (define (remove-pkts-if-not-alive uconn serv-pkts) (filter (lambda (pkt) (let* ((host (alist-ref 'host pkt)) (port (alist-ref 'port pkt)) (host-port (conc host":"port)) (key (alist-ref 'servkey pkt)) (pktz (alist-ref 'Z pkt)) (res (server-ready? uconn host-port key))) (if res res (let* ((pktsdir (get-pkts-dir *toppath*)) (pktpath (conc pktsdir"/"pktz".pkt"))) (debug:print 0 *default-log-port* "WARNING: pkt with no server "pktpath) (delete-file* pktpath) #f)))) serv-pkts)) ;; from viable servers get one that is alive and ready ;; (define (get-the-server uconn apath serv-pkts) (let loop ((tail serv-pkts)) (if (null? tail) #f (let* ((spkt (car tail)) (host (alist-ref 'ipaddr spkt)) (port (alist-ref 'port spkt)) (host-port (conc host":"port)) (dbpth (alist-ref 'dbpath spkt)) (srvkey (alist-ref 'Z spkt)) ;; (alist-ref 'srvkey spkt)) (addr (server-address spkt))) (if (server-ready? uconn host-port srvkey) spkt (loop (cdr tail))))))) ;; am I the "first" in line server? I.e. my D card is smallest ;; use Z card as tie breaker ;; (define (get-best-candidate serv-pkts dbpath) (if (null? serv-pkts) #f (let loop ((tail serv-pkts) (best (car serv-pkts))) (if (null? tail) best (let* ((candidate (car tail)) (candidate-bd (string->number (alist-ref 'D candidate))) (best-bd (string->number (alist-ref 'D best))) ;; bigger number is younger (candidate-z (alist-ref 'Z candidate)) (best-z (alist-ref 'Z best)) (new-best (cond ((> best-bd candidate-bd) ;; best is younger than candidate candidate) ((< best-bd candidate-bd) ;; candidate is younger than best best) (else (if (string>=? best-z candidate-z) best candidate))))) ;; use Z card as tie breaker (if (null? tail) new-best (loop (cdr tail) new-best))))))) ;;====================================================================== ;; END NEW SERVER METHOD ;;====================================================================== ;; if .db/main.db check the pkts ;; (define (rmt:wait-for-server pkts-dir db-file server-key) (let* ((sdat *db-serv-info*)) (let loop ((start-time (current-seconds)) (changed #t) (last-sdat "not this")) (begin ;; let ((sdat #f)) (thread-sleep! 0.01) (debug:print-info 0 *default-log-port* "Waiting for server alive signature") (mutex-lock! *heartbeat-mutex*) (set! sdat *db-serv-info*) (mutex-unlock! *heartbeat-mutex*) (if (and sdat (not changed) (> (- (current-seconds) start-time) 2)) (let* ((uconn (servdat-uconn sdat))) (servdat-status-set! sdat 'iface-stable) (debug:print-info 0 *default-log-port* "Received server alive signature, now attempting to lock in server") ;; create a server pkt in *toppath*/.meta/srvpkts ;; TODO: ;; 1. change sdat to stuct ;; 2. add uuid to struct ;; 3. update uuid in sdat here ;; (servdat-uuid-set! sdat (register-server pkts-dir *srvpktspec* (get-host-name) (servdat-port sdat) server-key (servdat-host sdat) db-file)) ;; (set! *my-signature* (servdat-uuid sdat)) ;; replace with Z, no, stick with proper key ;; now read pkts and see if we are a contender (let* ((all-pkts (get-all-server-pkts pkts-dir *srvpktspec*)) (viables (get-viable-servers all-pkts db-file)) (alive (remove-pkts-if-not-alive uconn viables)) (best-srv (get-best-candidate alive db-file)) (best-srv-key (if best-srv (alist-ref 'servkey best-srv) #f)) (i-am-srv (equal? best-srv-key server-key)) (delete-pkt (lambda () (let* ((pktfile (conc (get-pkts-dir *toppath*) "/" (servdat-uuid *db-serv-info*) ".pkt"))) (debug:print-info 0 *default-log-port* "Attempting to remove bogus pkt file "pktfile) (delete-file* pktfile))))) ;; remove immediately instead of waiting for on-exit (debug:print 0 *default-log-port* "best-srv-key: "best-srv-key", server-key: "server-key", i-am-srv: "i-am-srv) ;; am I the best-srv, compare server-keys to know (if i-am-srv (if (get-lock-db sdat db-file (servdat-host sdat)(servdat-port sdat)) ;; (db:get-iam-server-lock *dbstruct-db* *toppath* run-id) (begin (debug:print-info 0 *default-log-port* "I'm the server!") (servdat-dbfile-set! sdat db-file) (servdat-status-set! sdat 'db-locked)) (begin (debug:print-info 0 *default-log-port* "I'm not the server, exiting.") (bdat-time-to-exit-set! *bdat* #t) (delete-pkt) (thread-sleep! 0.2) (exit))) (begin (debug:print-info 0 *default-log-port* "Keys do not match "best-srv-key", "server-key", exiting.") (bdat-time-to-exit-set! *bdat* #t) (delete-pkt) (thread-sleep! 0.2) (exit))) sdat)) (begin ;; sdat not yet contains server info (debug:print-info 0 *default-log-port* "Still waiting, last-sdat=" last-sdat) (sleep 4) (if (> (- (current-seconds) start-time) 120) ;; been waiting for two minutes (begin (debug:print-error 0 *default-log-port* "transport appears to have died, exiting server") (exit)) (loop start-time (equal? sdat last-sdat) sdat)))))))) (define (rmt:register-server sinfo apath iface port server-key dbname) (servdat-conns sinfo) ;; just checking types (rmt:open-main-connection sinfo apath) ;; we need a channel to main.db (rmt:send-receive-real sinfo apath ;; params: host port servkey pid ipaddr dbpath (db:run-id->dbname #f) 'register-server `(,iface ,port ,server-key ,(current-process-id) ,iface ,apath ,dbname))) (define (rmt:get-count-servers sinfo apath) (servdat-conns sinfo) ;; just checking types (rmt:open-main-connection sinfo apath) ;; we need a channel to main.db (rmt:send-receive-real sinfo apath ;; params: host port servkey pid ipaddr dbpath (db:run-id->dbname #f) 'get-count-servers `(,apath))) (define (rmt:get-servers-info apath) (rmt:send-receive 'get-servers-info #f `(,apath))) (define (rmt:deregister-server db-serv-info apath iface port server-key dbname) (rmt:open-main-connection db-serv-info apath) ;; we need a channel to main.db (rmt:send-receive-real db-serv-info apath ;; params: host port servkey pid ipaddr dbpath (db:run-id->dbname #f) 'deregister-server `(,iface ,port ,server-key ,(current-process-id) ,iface ,apath ,dbname))) (define (rmt:wait-for-stable-interface #!optional (num-tries-allowed 100)) ;; wait until *db-serv-info* stops changing (let* ((stime (current-seconds))) (let loop ((last-host #f) (last-port #f) (tries 0)) (let* ((curr-host (and *db-serv-info* (servdat-host *db-serv-info*))) (curr-port (and *db-serv-info* (servdat-port *db-serv-info*)))) ;; first we verify port and interface, update *db-serv-info* in need be. (cond ((> tries num-tries-allowed) (debug:print 0 *default-log-port* "rmt:keep-running, giving up after trying for several minutes.") (exit 1)) ((not *db-serv-info*) (thread-sleep! 0.25) (loop curr-host curr-port (+ tries 1))) ((or (not last-host)(not last-port)) (debug:print 0 *default-log-port* "rmt:keep-running, still no interface, tries="tries) (thread-sleep! 0.25) (loop curr-host curr-port (+ tries 1))) ((or (not (equal? last-host curr-host)) (not (equal? last-port curr-port))) (debug:print-info 0 *default-log-port* "WARNING: interface changed, refreshing iface and port info") (thread-sleep! 0.25) (loop curr-host curr-port (+ tries 1))) ((< (- (current-seconds) stime) 1) ;; keep up the looping until at least 3 seconds have passed (thread-sleep! 0.5) (loop curr-host curr-port (+ tries 1))) (else (rmt:get-signature) ;; sets *my-signature* as side effect (servdat-status-set! *db-serv-info* 'interface-stable) (debug:print 0 *default-log-port* "SERVER STARTED: " curr-host ":" curr-port " AT " (current-seconds) " server signature: " *my-signature* " with "(servdat-trynum *db-serv-info*)" port changes") (flush-output *default-log-port*) #t)))))) ;; run rmt:keep-running in a parallel thread to monitor that the db is being ;; used and to shutdown after sometime if it is not. ;; (define (rmt:keep-running dbname) ;; if none running or if > 20 seconds since ;; server last used then start shutdown ;; This thread waits for the server to come alive (debug:print-info 0 *default-log-port* "Starting the sync-back, keep alive thread in server") (let* ((sinfo *db-serv-info*) (server-start-time (current-seconds)) (pkts-dir (get-pkts-dir)) (server-key (rmt:get-signature)) ;; This servers key (is-main (equal? (args:get-arg "-db") ".db/main.db")) (last-access 0) (server-timeout (server:expiration-timeout)) (shutdown-server-sequence (lambda (host port) (set! *unclean-shutdown* #f) ;; Should not be needed anymore (debug:print-info 0 *default-log-port* "Starting to shutdown the server. pid="(current-process-id)) ;; (rmt:server-shutdown host port) -- called in on-exit ;; (portlogger:open-run-close portlogger:set-port port "released") called in on-exit (exit))) (timed-out? (lambda () (<= (+ last-access server-timeout) (current-seconds))))) (servdat-dbfile-set! *db-serv-info* (args:get-arg "-db")) ;; main and run db servers have both got wait logic (could/should merge it) (if is-main (rmt:wait-for-server pkts-dir dbname server-key) (rmt:wait-for-stable-interface)) ;; this is our forever loop (let* ((iface (servdat-host *db-serv-info*)) (port (servdat-port *db-serv-info*)) (uconn (servdat-uconn *db-serv-info*))) (let loop ((count 0) (bad-sync-count 0) (start-time (current-milliseconds))) (if (and (not is-main) (common:low-noise-print 60 "servdat-status")) (debug:print-info 0 *default-log-port* "servdat-status is " (servdat-status *db-serv-info*))) (mutex-lock! *heartbeat-mutex*) ;; set up the database handle (if (not *dbstruct-db*) ;; no db opened yet, open the db and register with main if appropriate (let ((watchdog (bdat-watchdog *bdat*))) (debug:print 0 *default-log-port* "SERVER: dbprep") (db:setup dbname) ;; sets *dbstruct-db* as side effect (servdat-status-set! *db-serv-info* 'db-opened) ;; IFF I'm not main, call into main and register self (if (not is-main) (let ((res (rmt:register-server sinfo *toppath* iface port server-key dbname))) (if res ;; we are the server (servdat-status-set! *db-serv-info* 'have-interface-and-db) ;; now check that the db locker is alive, clear it out if not (let* ((serv-info (rmt:server-info *toppath* dbname))) (match serv-info ((host port servkey pid ipaddr apath dbpath) (if (not (server-ready? uconn (conc host":"port) servkey)) (begin (debug:print-info 0 *default-log-port* "Server registered but not alive. Removing and trying again.") (rmt:deregister-server sinfo apath host port servkey dbpath) ;; servkey pid ipaddr apath dbpath) (loop (+ count 1) bad-sync-count start-time)))) (else (debug:print 0 *default-log-port* "We are not the server for "dbname", exiting. Server info is: "serv-info) (exit))))))) (debug:print 0 *default-log-port* "SERVER: running, db "dbname" opened, megatest version: " (common:get-full-version)) ;; start the watchdog ;; is this really needed? #;(if watchdog (if (not (member (thread-state watchdog) '(ready running blocked sleeping dead))) (begin (debug:print-info 0 *default-log-port* "Starting watchdog thread (in state "(thread-state watchdog)")") (thread-start! watchdog)) (debug:print-info 0 *default-log-port* "Not starting watchdog thread (in state "(thread-state watchdog)")")) (debug:print 0 *default-log-port* "ERROR: *watchdog* not setup, cannot start it.")) #;(loop (+ count 1) bad-sync-count start-time) )) (db:sync-inmem->disk *dbstruct-db* *toppath* dbname force-sync: #t) (mutex-unlock! *heartbeat-mutex*) ;; when things go wrong we don't want to be doing the various ;; queries too often so we strive to run this stuff only every ;; four seconds or so. (let* ((sync-time (- (current-milliseconds) start-time)) (rem-time (quotient (- 4000 sync-time) 1000))) (if (and (<= rem-time 4) (> rem-time 0)) (thread-sleep! rem-time))) ;; Transfer *db-last-access* to last-access to use in checking that we are still alive (set! last-access *db-last-access*) (if (< count 1) ;; 3x3 = 9 secs aprox (loop (+ count 1) bad-sync-count (current-milliseconds))) (if (common:low-noise-print 60 "dbstats") (begin (debug:print 0 *default-log-port* "Server stats:") (db:print-current-query-stats))) (let* ((hrs-since-start (/ (- (current-seconds) server-start-time) 3600))) (cond ((not *server-run*) (debug:print-info 0 *default-log-port* "*server-run* set to #f. Shutting down.") (shutdown-server-sequence (get-host-name) port)) ((timed-out?) (debug:print-info 0 *default-log-port* "Server timed out. seconds since last db access: " (- (current-seconds) last-access)) (shutdown-server-sequence (get-host-name) port)) ((and *server-run* (or (not (timed-out?)) (if is-main ;; do not exit if there are other servers (keep main open until all others gone) (> (rmt:get-count-servers sinfo *toppath*) 1) #f))) (if (common:low-noise-print 120 "server continuing") (debug:print-info 0 *default-log-port* "Server continuing, seconds since last db access: " (- (current-seconds) last-access))) (loop 0 bad-sync-count (current-milliseconds))) (else (set! *unclean-shutdown* #f) (debug:print-info 0 *default-log-port* "Server timed out. seconds since last db access: " (- (current-seconds) last-access)) (shutdown-server-sequence (get-host-name) port) #;(debug:print-info 0 *default-log-port* "Sending 'quit to server, received: " (open-send-receive-nn (conc iface":"port) ;; do this here and not in server-shutdown (sexpr->string 'quit)))))))))) (define (rmt:get-reasonable-hostname) (let* ((inhost (or (args:get-arg "-server") "-"))) (if (equal? inhost "-") (get-host-name) inhost))) ;; Call this to start the actual server ;; ;; all routes though here end in exit ... ;; ;; This is the point at which servers are started ;; (define (rmt:server-launch dbname) (debug:print-info 0 *default-log-port* "Entered rmt:server-launch") (let* ((th2 (make-thread (lambda () (debug:print-info 0 *default-log-port* "Server run thread started") (rmt:run (rmt:get-reasonable-hostname))) "Server run")) (th3 (make-thread (lambda () (debug:print-info 0 *default-log-port* "Server monitor thread started") (if (args:get-arg "-server") (rmt:keep-running dbname))) "Keep running"))) (thread-start! th2) (thread-sleep! 0.252) ;; give the server time to settle before starting the keep-running monitor. (thread-start! th3) (set! *didsomething* #t) (thread-join! th2) (thread-join! th3)) #f) ;;====================================================================== ;; S E R V E R - D I R E C T C A L L S ;;====================================================================== (define (rmt:kill-server run-id) (rmt:send-receive 'kill-server #f (list run-id))) (define (rmt:start-server run-id) (rmt:send-receive 'start-server #f (list run-id))) (define (rmt:server-info apath dbname) (rmt:send-receive 'get-server-info #f (list apath dbname))) ;;====================================================================== ;; Nanomsg transport ;;====================================================================== #;(define (is-port-in-use port-num) (let* ((ret #f)) (let-values (((inp oup pid) (process "netstat" (list "-tulpn" )))) (let loop ((inl (read-line inp))) (if (not (eof-object? inl)) (begin (if (string-search (regexp (conc ":" port-num)) inl) (begin ;(print "Output: " inl) (set! ret #t)) (loop (read-line inp))))))) ret)) #;(define (open-nn-connection host-port) (let ((req (make-req-socket)) (uri (conc "tcp://" host-port))) (nng-dial req uri) (socket-set! req 'nng/recvtimeo 2000) req)) #;(define (send-receive-nn req msg) (nng-send req msg) (nng-recv req)) #;(define (close-nn-connection req) (nng-close! req)) ;; ;; open connection to server, send message, close connection ;; ;; ;; (define (open-send-close-nn host-port msg #!key (timeout 3) ) ;; default timeout is 3 seconds ;; (let ((req (make-req-socket 'req)) ;; (uri (conc "tcp://" host-port)) ;; (res #f) ;; ;; (contacts (alist-ref 'contact attrib)) ;; ;; (mode (alist-ref 'mode attrib)) ;; ) ;; (socket-set! req 'nng/recvtimeo 2000) ;; (handle-exceptions ;; exn ;; (let ((emsg ((condition-property-accessor 'exn 'message) exn))) ;; ;; Send notification ;; (debug:print 0 *default-log-port* "ERROR: Failed to connect / send to " uri " message was \"" emsg "\"" ) ;; #f) ;; (nng-dial req uri) ;; ;; (print "Connected to the server " ) ;; (nng-send req msg) ;; ;; (print "Request Sent") ;; (let* ((th1 (make-thread (lambda () ;; (let ((resp (nng-recv req))) ;; (nng-close! req) ;; (set! res (if (equal? resp "ok") ;; #t ;; #f)))) ;; "recv thread")) ;; (th2 (make-thread (lambda () ;; (thread-sleep! timeout) ;; (thread-terminate! th1)) ;; "timer thread"))) ;; (thread-start! th1) ;; (thread-start! th2) ;; (thread-join! th1) ;; res)))) ;; #;(define (open-send-receive-nn host-port msg #!key (timeout 3) ) ;; default timeout is 3 seconds (let ((req (make-req-socket)) (uri (conc "tcp://" host-port)) (res #f)) (handle-exceptions exn (let ((emsg ((condition-property-accessor 'exn 'message) exn))) ;; Send notification (debug:print 0 *default-log-port* "ERROR: Failed to connect / send to " uri " message was \"" emsg "\", exn=" exn) #f) (nng-dial req uri) (nng-send req msg) (let* ((th1 (make-thread (lambda () (let ((resp (nng-recv req))) (nng-close! req) ;; (print resp) (set! res resp))) "recv thread")) (th2 (make-thread (lambda () (thread-sleep! timeout) (thread-terminate! th1)) "timer thread"))) (thread-start! th1) (thread-start! th2) (thread-join! th1) res)))) ;;====================================================================== ;; S E R V E R U T I L I T I E S ;;====================================================================== ;; run ping in separate process, safest way in some cases ;; #;(define (server:ping-server ifaceport) (with-input-from-pipe (conc (common:get-megatest-exe) " -ping " ifaceport) (lambda () (let loop ((inl (read-line)) (res "NOREPLY")) (if (eof-object? inl) (case (string->symbol res) ((NOREPLY) #f) ((LOGIN_OK) #t) (else #f)) (loop (read-line) inl)))))) ;; NOT USED (well, ok, reference in rpc-transport but otherwise not used). ;; #;(define (server:login toppath) (lambda (toppath) (set! *db-last-access* (current-seconds)) ;; might not be needed. (if (equal? *toppath* toppath) #t #f))) ;; (define server:sync-lock-token "SERVER_SYNC_LOCK") ;; (define (server:release-sync-lock) ;; (db:no-sync-del! *no-sync-db* server:sync-lock-token)) ;; (define (server:have-sync-lock?) ;; (let* ((have-lock-pair (db:no-sync-get-lock *no-sync-db* server:sync-lock-token)) ;; (have-lock? (car have-lock-pair)) ;; (lock-time (cdr have-lock-pair)) ;; (lock-age (- (current-seconds) lock-time))) ;; (cond ;; (have-lock? #t) ;; ((>lock-age ;; (* 3 (configf:lookup-number *configdat* "server" "minimum-intersync-delay" default: 180))) ;; (server:release-sync-lock) ;; (server:have-sync-lock?)) ;; (else #f)))) ) |
Modified ulex/ulex.scm from [42b648b50c] to [c73b8e0289].
1 2 | 1 2 3 4 5 6 7 8 9 10 | - + | ;; ulex: Distributed sqlite3 db ;;; |
21 22 23 24 25 26 27 | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 | - - - - + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - - - + + + + + + + + + + - - - + - - - + + + + + + + + + + + + - - - - - + + + + + + + - - + + - - - - - - - - + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + - - - - + + + + + - - + + + + + - - - - - - + + + + + + + - - - - + + + + + + + - - - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + - - + + + + + + + + + - + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + - - - - - - + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - - + + + + + + + - + + - - - - - + + + + + + + + - - - + + + - - - - - - - + + + + + + + + + + + + + + - - - - + + + + + + - - - - - - + + + + + + + - - - + + + + + + - - + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + - - - - + + + + + + + + + + + - - + + - - - - - - + - - - + - - - - - + - - - - - - - - + + + + + + + + + + + + + + + + + - - + - - - - + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + - - - - - - - + + + + + + + + + + + - - - + + + + + + + + - - + + + - - - - - - - - + + + + + + + + - - - - - + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - - + - - - - + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | ;; ABOUT: ;; See README in the distribution at https://www.kiatoa.com/fossils/ulex ;; NOTES: ;; Why sql-de-lite and not say, dbi? - performance mostly, then simplicity. ;; ;;====================================================================== |
Modified utils/nbfake from [3dc733e001] to [3e514ddfd2].
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | + | nbfake <command to run> nbfake behavior can be changed by setting the following env vars: NBFAKE_HOST SSH to \$NBFAKE_HOST and run command NBFAKE_LOG Logfile for nbfake output NB_WASH_GROUPS comma-separated list of groups to wash into NB_WASH_ENABLED must be set in order to enable wash groups NBFAKE_QUIET set to suppress informational output __EOF exit fi #============================================================================== # Setup |
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | + + | WASHCMD="wash -q -n $grouplist -X" fi #============================================================================== # Run and log #============================================================================== if [[ -z "$NBFAKE_QUIET" ]];then cat <<__EOF >&2 #====================================================================== # NBFAKE logging command to: $MY_NBFAKE_LOG # $WASHCMD $* #====================================================================== __EOF fi if [[ -z "$MY_NBFAKE_HOST" ]]; then # Run locally sh -c "cd $CURRWD;export DISPLAY=$DISPLAY; export PATH=\"$PATH\"; nohup $WASHCMD $* >> $MY_NBFAKE_LOG 2>&1 &" else # run remotely ssh -X -n -f $MY_NBFAKE_HOST "sh -c \"cd $CURRWD;export DISPLAY=$DISPLAY; export PATH=\"$PATH\"; nohup $WASHCMD $* >> $MY_NBFAKE_LOG 2>&1 &\"" fi |