skyANAponuch, хотя бы один тынц дайте, хочется посмотреть на "и далее"
парадокс (шото напоминающее операцию like)
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.
proc isSpace1(char)
private x
x = substr(char,1,1)
if(x = " " or x = "\t" ) then
return true
endif
return false
endproc
proc countErrs(s1, s2)
private a1, a2, a1L, a2L, a1P, a2P, ; array, array length, array pointer
errs, mmatch,
MODUL,x
MODUL = 100 ; 1283 - 83 mmatch
; 12 errors
;
deSpace( s1, s2) a1P = 1 a2P = 1
;? "-------------------"
calls=0
x = countMatch(0,0)
errs = int(x / MODUL)
mmatch = x - int(x / MODUL) * MODUL
;? "mmatch = ", mmatch," calls = ", calls
return errs
endproc
proc countMatch(mmatch, errs)
calls= calls+1
while(a1P <= a1L and a2P <= a2L )
if( a1[a1P] <> a2[a2P] ) then
return searchMatch (mmatch,errs)
endif
a1P = a1P + 1
a2P = a2P + 1
mmatch = mmatch + 1
endwhile
errs = errs + max(0, max ( a1L+1 - a1P, a2L+1 - a2P))
return errs * MODUL + mmatch
endproc
proc searchMatch(mmatch, errs)
private err, x,y,m,e, structP
structP = 0
err = 1
WHILE a1P + err <= a1L or a2P + err <= a2L
; поиск возможных продолжений
; по каждому продолжению
; записывается структура <a1P, a2P, mmatch, errs>
; для оценки выбора продолжения
array x[2*err]
array y[2*err]
array m[2*err]
array e[2*err]
structP = searchSequel(err)
if(structP > 0) then
quitloop
endif
err = err + 1
endWHILE
errs = errs + err
if(structP > 0) then
return weightSequel(mmatch, errs, structP)
endif
return (errs * MODUL) + mmatch
endproc
proc saveStruct(p, i1, i2)
p = p + 1
if(p <= 2*err) then
x[p] = i1
y[p] = i2
m[p] = 0
e[p] = 0
return 1
endif
return 0
endproc
proc searchSequel(err) ; доступ к структуре в вызвавшей программе
private rc, i1, i2
rc = 0
i1 = a1P
i2 = a2P
while( (i1 < a1P + err) OR (i2 < a2P + err))
if((i2 <= a2L) and (a1P + err <= a1L)) then
if( a2[i2] = a1[a1P + err] ) then
rc = rc + saveStruct(rc, a1P + err, i2)
endif
endif
if((i1 <= a1L) and (a2P + err <= a2L)) then
if( a1[i1] = a2[a2P + err] ) then
rc = rc + saveStruct(rc, i1, a2P + err)
endif
endif
i1 = i1 + 1
i2 = i2 + 1
endwhile
if(i1 <= a1L and i2 <= a2L) then
if( a1[i1] = a2[i2] ) then
rc = rc + saveStruct(rc, i1, i2)
endif
endif
return rc
endproc
proc weightSequel(mmatch, errs, sP)
private p, errsMatch , minEr, maxMa , er, ma, i1, i2, ppp
errsMatch = 0
minEr = 32000
maxMa = -32000
for p from 1 to sP
er = errs
a1P = x[p]
a2P = y[p]
errsMatch = countMatch (mmatch, errs)
m[p] = errsMatch - int(errsMatch / MODUL) * MODUL
e[p] = int(errsMatch / MODUL)
if (m[p] > maxMa) then
ppp = p
minEr = e[p]
maxMa = m[p]
else if (m[p] = maxMa and e[p] < minEr) then
ppp = p
minEr = e[p]
maxMa = m[p]
endif
endif
endfor
errsMatch = minEr * MODUL + maxMa
return errsMatch
endproc
proc deSpace( string1, string2)
private i,j, prevChar, char
prevChar = 0;
i = 0;
j = 0
;string1 = ltrim(rtrim(string1))
a1L = len(string1)
array a1[a1L]
for i from 1 to a1L
char = substr(string1, i, 1)
if((not isSpace1(char)) or (not isSpace1(prevChar))) then
j = j + 1
a1[j] = char
prevChar = char
endif
endfor
a1L = j
prevChar = 0;
i = 0;
j = 0
;string2 = ltrim(rtrim(string2))
a2L = len(string2)
array a2[a2L]
for i from 1 to a2L
char = substr(string2, i, 1)
if((not isSpace1(char)) or (not isSpace1(prevChar))) then
j = j + 1
a2[j] = char
prevChar = char
endif
endfor
a2L = j
endproc
proc printArray(arr, arrL)
private i
@ 2,2
?? "--> "
for i from 1 to arrL
execute "?? "+arr+"["+strval(i)+"]"
endfor
?? " <--"
endproc
rsl
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. 1625. 1626. 1627. 1628. 1629. 1630. 1631. 1632. 1633. 1634. 1635. 1636. 1637. 1638. 1639. 1640. 1641. 1642. 1643. 1644. 1645. 1646. 1647. 1648. 1649. 1650. 1651. 1652. 1653. 1654. 1655. 1656. 1657. 1658. 1659. 1660. 1661. 1662. 1663. 1664. 1665. 1666. 1667. 1668. 1669. 1670. 1671. 1672. 1673. 1674. 1675. 1676. 1677. 1678. 1679. 1680. 1681. 1682. 1683. 1684. 1685. 1686. 1687. 1688. 1689. 1690. 1691. 1692. 1693. 1694. 1695. 1696. 1697. 1698. 1699. 1700. 1701. 1702. 1703. 1704. 1705. 1706. 1707. 1708. 1709. 1710. 1711. 1712. 1713. 1714. 1715. 1716. 1717. 1718. 1719. 1720. 1721. 1722. 1723. 1724. 1725. 1726. 1727. 1728. 1729. 1730. 1731. 1732. 1733. 1734. 1735. 1736. 1737. 1738. 1739. 1740. 1741. 1742. 1743. 1744. 1745. 1746. 1747. 1748. 1749. 1750. 1751. 1752. 1753. 1754. 1755. 1756. 1757. 1758. 1759. 1760. 1761. 1762. 1763. 1764. 1765. 1766. 1767. 1768. 1769. 1770. 1771. 1772. 1773. 1774. 1775. 1776. 1777. 1778. 1779. 1780. 1781. 1782. 1783. 1784. 1785. 1786. 1787. 1788. 1789. 1790. 1791. 1792. 1793. 1794. 1795. 1796. 1797. 1798. 1799. 1800. 1801. 1802. 1803. 1804. 1805. 1806. 1807. 1808. 1809. 1810. 1811. 1812. 1813. 1814. 1815. 1816. 1817. 1818. 1819. 1820. 1821. 1822. 1823. 1824. 1825. 1826. 1827. 1828. 1829. 1830. 1831. 1832. 1833. 1834. 1835. 1836. 1837. 1838. 1839. 1840. 1841. 1842. 1843. 1844. 1845. 1846. 1847. 1848. 1849. 1850. 1851. 1852. 1853. 1854. 1855. 1856. 1857. 1858. 1859. 1860. 1861. 1862. 1863. 1864. 1865. 1866. 1867. 1868. 1869. 1870. 1871. 1872. 1873. 1874. 1875. 1876. 1877. 1878. 1879. 1880. 1881. 1882. 1883. 1884. 1885. 1886. 1887. 1888. 1889. 1890. 1891. 1892. 1893. 1894. 1895. 1896. 1897. 1898. 1899. 1900. 1901. 1902. 1903. 1904. 1905. 1906. 1907. 1908. 1909. 1910. 1911. 1912. 1913. 1914. 1915. 1916. 1917. 1918. 1919. 1920. 1921. 1922. 1923. 1924. 1925. 1926. 1927. 1928. 1929. 1930. 1931. 1932. 1933. 1934. 1935. 1936. 1937. 1938. 1939. 1940. 1941. 1942. 1943. 1944. 1945. 1946. 1947. 1948. 1949. 1950. 1951. 1952. 1953. 1954. 1955. 1956. 1957. 1958. 1959. 1960. 1961. 1962. 1963. 1964. 1965. 1966. 1967. 1968. 1969. 1970. 1971. 1972. 1973. 1974. 1975. 1976. 1977. 1978. 1979. 1980. 1981. 1982. 1983. 1984. 1985. 1986. 1987. 1988. 1989. 1990. 1991. 1992. 1993. 1994. 1995. 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. 2027. 2028. 2029. 2030. 2031. 2032. 2033. 2034. 2035. 2036. 2037. 2038. 2039. 2040. 2041. 2042. 2043. 2044. 2045. 2046. 2047. 2048. 2049. 2050. 2051. 2052. 2053. 2054. 2055. 2056. 2057. 2058. 2059. 2060. 2061. 2062. 2063. 2064. 2065. 2066. 2067. 2068. 2069. 2070. 2071. 2072. 2073. 2074. 2075. 2076. 2077. 2078. 2079. 2080. 2081. 2082. 2083. 2084. 2085. 2086. 2087. 2088. 2089. 2090. 2091. 2092. 2093. 2094. 2095. 2096. 2097. 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. 2162. 2163. 2164. 2165. 2166. 2167. 2168. 2169. 2170. 2171. 2172. 2173. 2174. 2175. 2176. 2177. 2178. 2179. 2180. 2181. 2182. 2183. 2184. 2185. 2186. 2187. 2188. 2189. 2190. 2191. 2192. 2193. 2194. 2195. 2196. 2197. 2198. 2199. 2200. 2201. 2202. 2203. 2204. 2205. 2206. 2207. 2208. 2209. 2210. 2211. 2212. 2213. 2214. 2215. 2216. 2217. 2218. 2219. 2220. 2221. 2222. 2223. 2224. 2225. 2226. 2227. 2228. 2229. 2230. 2231. 2232. 2233. 2234. 2235. 2236. 2237. 2238. 2239. 2240. 2241. 2242. 2243. 2244. 2245. 2246. 2247. 2248. 2249. 2250. 2251. 2252. 2253. 2254. 2255. 2256. 2257. 2258. 2259. 2260. 2261. 2262. 2263. 2264. 2265. 2266. 2267. 2268. 2269. 2270. 2271. 2272. 2273. 2274. 2275. 2276. 2277. 2278. 2279. 2280. 2281. 2282. 2283. 2284. 2285. 2286. 2287. 2288. 2289. 2290. 2291. 2292. 2293. 2294. 2295. 2296. 2297. 2298. 2299. 2300. 2301. 2302. 2303. 2304. 2305. 2306. 2307. 2308. 2309. 2310. 2311. 2312. 2313. 2314. 2315. 2316. 2317. 2318. 2319. 2320. 2321. 2322. 2323. 2324. 2325. 2326. 2327. 2328. 2329. 2330. 2331. 2332. 2333. 2334. 2335. 2336. 2337. 2338. 2339. 2340. 2341. 2342. 2343. 2344. 2345. 2346. 2347. 2348. 2349. 2350. 2351. 2352. 2353. 2354. 2355. 2356. 2357. 2358. 2359. 2360. 2361. 2362. 2363. 2364. 2365. 2366. 2367. 2368. 2369. 2370. 2371. 2372. 2373. 2374. 2375. 2376. 2377. 2378. 2379. 2380. 2381. 2382. 2383. 2384. 2385. 2386. 2387. 2388. 2389. 2390. 2391. 2392. 2393. 2394. 2395. 2396. 2397. 2398. 2399. 2400. 2401. 2402. 2403. 2404. 2405. 2406. 2407. 2408. 2409. 2410. 2411. 2412. 2413. 2414. 2415. 2416. 2417. 2418. 2419. 2420. 2421. 2422. 2423. 2424. 2425. 2426. 2427. 2428. 2429. 2430. 2431. 2432. 2433. 2434. 2435. 2436. 2437. 2438. 2439. 2440. 2441. 2442. 2443. 2444. 2445. 2446. 2447. 2448. 2449. 2450. 2451. 2452. 2453. 2454. 2455. 2456. 2457. 2458. 2459. 2460. 2461. 2462. 2463. 2464. 2465. 2466. 2467. 2468. 2469. 2470. 2471. 2472. 2473. 2474. 2475. 2476. 2477. 2478. 2479. 2480. 2481. 2482. 2483. 2484. 2485. 2486. 2487. 2488. 2489. 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. 2535. 2536. 2537. 2538. 2539. 2540. 2541. 2542. 2543. 2544. 2545. 2546. 2547. 2548. 2549. 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. 2578. 2579. 2580. 2581. 2582. 2583. 2584. 2585. 2586. 2587. 2588. 2589. 2590. 2591. 2592. 2593. 2594. 2595. 2596. 2597. 2598. 2599. 2600. 2601. 2602. 2603. 2604. 2605. 2606. 2607. 2608. 2609. 2610. 2611. 2612. 2613. 2614. 2615. 2616. 2617. 2618. 2619. 2620. 2621. 2622. 2623. 2624. 2625. 2626. 2627. 2628. 2629. 2630. 2631. 2632. 2633. 2634. 2635. 2636. 2637. 2638. 2639. 2640. 2641. 2642. 2643. 2644. 2645. 2646. 2647. 2648. 2649. 2650. 2651. 2652. 2653. 2654. 2655. 2656. 2657. 2658. 2659. 2660. 2661. 2662. 2663. 2664. 2665. 2666. 2667. 2668. 2669. 2670. 2671. 2672. 2673. 2674. 2675. 2676. 2677. 2678. 2679. 2680. 2681. 2682. 2683. 2684. 2685. 2686. 2687. 2688. 2689. 2690. 2691. 2692. 2693. 2694. 2695. 2696. 2697. 2698. 2699. 2700. 2701. 2702. 2703. 2704. 2705. 2706. 2707. 2708. 2709. 2710. 2711. 2712. 2713. 2714. 2715. 2716. 2717. 2718. 2719. 2720. 2721. 2722. 2723. 2724. 2725. 2726. 2727. 2728. 2729. 2730. 2731. 2732. 2733. 2734. 2735. 2736. 2737. 2738. 2739. 2740. 2741. 2742. 2743. 2744. 2745. 2746. 2747. 2748. 2749. 2750. 2751. 2752. 2753. 2754. 2755. 2756. 2757. 2758. 2759. 2760. 2761. 2762. 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. 2808. 2809. 2810. 2811. 2812. 2813. 2814. 2815. 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. 2861. 2862. 2863. 2864. 2865. 2866. 2867. 2868. 2869. 2870. 2871. 2872. 2873. 2874. 2875. 2876. 2877. 2878. 2879. 2880. 2881. 2882. 2883. 2884. 2885. 2886. 2887. 2888. 2889. 2890. 2891. 2892. 2893. 2894. 2895. 2896. 2897. 2898. 2899. 2900. 2901. 2902. 2903. 2904. 2905. 2906. 2907. 2908. 2909. 2910. 2911. 2912. 2913. 2914. 2915. 2916. 2917. 2918. 2919. 2920. 2921. 2922. 2923. 2924. 2925. 2926. 2927. 2928. 2929. 2930. 2931. 2932. 2933. 2934. 2935. 2936. 2937. 2938. 2939. 2940. 2941. 2942. 2943. 2944. 2945. 2946. 2947. 2948. 2949. 2950. 2951. 2952. 2953. 2954. 2955. 2956. 2957. 2958. 2959. 2960. 2961. 2962. 2963. 2964. 2965. 2966. 2967. 2968. 2969. 2970. 2971. 2972. 2973. 2974. 2975. 2976. 2977. 2978. 2979. 2980. 2981. 2982. 2983. 2984. 2985. 2986. 2987. 2988. 2989. 2990. 2991. 2992. 2993. 2994. 2995. 2996. 2997. 2998. 2999. 3000. 3001. 3002. 3003. 3004. 3005. 3006. 3007. 3008. 3009. 3010. 3011. 3012. 3013. 3014. 3015. 3016. 3017. 3018. 3019. 3020. 3021. 3022. 3023. 3024. 3025. 3026. 3027. 3028. 3029. 3030. 3031. 3032. 3033. 3034. 3035. 3036. 3037. 3038. 3039. 3040. 3041. 3042. 3043. 3044. 3045. 3046. 3047. 3048. 3049. 3050. 3051. 3052. 3053. 3054. 3055. 3056. 3057. 3058. 3059. 3060. 3061. 3062. 3063. 3064. 3065. 3066. 3067. 3068. 3069. 3070. 3071. 3072. 3073. 3074. 3075. 3076. 3077. 3078. 3079. 3080. 3081. 3082. 3083. 3084. 3085. 3086. 3087. 3088. 3089. 3090. 3091. 3092. 3093. 3094. 3095. 3096. 3097. 3098. 3099. 3100. 3101. 3102. 3103. 3104. 3105. 3106. 3107. 3108. 3109. 3110. 3111. 3112. 3113. 3114. 3115. 3116. 3117. 3118. 3119. 3120. 3121. 3122. 3123. 3124. 3125. 3126. 3127. 3128. 3129. 3130. 3131. 3132. 3133. 3134. 3135. 3136. 3137. 3138. 3139. 3140. 3141. 3142. 3143. 3144. 3145. 3146. 3147. 3148. 3149. 3150. 3151. 3152. 3153. 3154. 3155. 3156. 3157. 3158. 3159. 3160. 3161. 3162. 3163. 3164. 3165. 3166. 3167. 3168. 3169. 3170. 3171. 3172. 3173. 3174. 3175. 3176. 3177. 3178. 3179. 3180. 3181. 3182. 3183. 3184. 3185. 3186. 3187. 3188. 3189. 3190. 3191. 3192. 3193. 3194. 3195. 3196. 3197. 3198. 3199. 3200. 3201. 3202. 3203. 3204. 3205. 3206. 3207. 3208. 3209. 3210. 3211. 3212. 3213. 3214. 3215. 3216. 3217. 3218. 3219. 3220. 3221. 3222. 3223. 3224. 3225. 3226. 3227. 3228. 3229. 3230. 3231. 3232. 3233. 3234. 3235. 3236. 3237. 3238. 3239. 3240. 3241. 3242. 3243. 3244. 3245. 3246. 3247. 3248. 3249. 3250. 3251. 3252. 3253. 3254. 3255. 3256. 3257. 3258. 3259. 3260. 3261. 3262. 3263. 3264. 3265. 3266. 3267. 3268. 3269. 3270. 3271. 3272. 3273. 3274. 3275. 3276. 3277. 3278. 3279. 3280. 3281. 3282. 3283. 3284. 3285. 3286. 3287. 3288. 3289. 3290. 3291. 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. 3480. 3481. 3482. 3483. 3484. 3485. 3486. 3487. 3488. 3489. 3490. 3491. 3492. 3493. 3494. 3495. 3496. 3497. 3498. 3499. 3500. 3501. 3502. 3503. 3504. 3505. 3506. 3507. 3508. 3509. 3510. 3511. 3512. 3513. 3514. 3515. 3516. 3517. 3518. 3519. 3520. 3521. 3522. 3523. 3524. 3525. 3526. 3527. 3528. 3529. 3530. 3531. 3532. 3533. 3534. 3535. 3536. 3537. 3538. 3539. 3540. 3541. 3542. 3543. 3544. 3545. 3546. 3547. 3548. 3549. 3550. 3551. 3552. 3553. 3554. 3555. 3556. 3557. 3558. 3559. 3560. 3561. 3562. 3563. 3564. 3565. 3566. 3567. 3568. 3569. 3570. 3571. 3572. 3573. 3574. 3575. 3576. 3577. 3578. 3579. 3580. 3581. 3582. 3583. 3584. 3585. 3586. 3587. 3588. 3589. 3590. 3591. 3592. 3593. 3594. 3595. 3596. 3597. 3598. 3599. 3600. 3601. 3602. 3603. 3604. 3605. 3606. 3607. 3608. 3609. 3610. 3611. 3612. 3613. 3614. 3615. 3616. 3617. 3618. 3619. 3620. 3621. 3622. 3623. 3624. 3625. 3626. 3627. 3628. 3629. 3630. 3631. 3632. 3633. 3634. 3635.
АННОТАЦИЯ
Данный документ содержит сведения о назначении компоненты
"Gass Station Advanced Utilities", общего ее описания и действий
по настройке и тестированию.
От читателя требуется знание терминов и основных принципов работы
SQL сервера (с которыми можно познакомится в книге [1]); языка
C++, протоколов TCP/IP. Для постановки задачи используется язык
формальных спецификаций RSL (cm. [2,3] ).
Работа выполнена по заказу компании TechnoLux, Ltd..
Данный документ является обьединением документов ТЕХНИЧЕСКОЕ
ЗАДАНИЕ, ОПИСАНИЕ ПРОГРАММЫ.
Дата создания документа: 24.12.2002
5
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
1. ОБЩИЕ СВЕДЕНИЯ О "Gass Station Advanced Utilities"
Информационная система "Gass Station Advanced Utilities" версии 0
модификации 90 имеет обозначение GSAU \ve. "Gass Station Advanced Utilities"
является набором файлов документации, исполняемых файлов (работающих
частично под управлением Windows 32, частично под управлением Unix),
исходных текстов программ написанных на языке C (которые могут
компилироваться под Windows 32 и Unix), скриптов, написанных на диалекте SQL
- Sybase SQL Anywere, для построения тестовой БД.
1.1. НАЗНАЧЕНИЕ "Gass Station Advanced Utilities"
"Gass Station Advanced Utilities" предназначена для:
- описания высокоуровневого протокола управления насосами заправочной
станции;
- передачи команд управления от оператора к контроллерам насосов
заправочной станции;
- передачи информации о состоянии насосов и контроллеров насосов к
оператору;
- является демонстрацией возможностей Библиотеки Интерфейса Обмена
Данными ( [4] );
- является демонстрацией возможностей языка формальных спецификаций RSL
( [4] ) и применения его к использованию при проектирования реляционных БД.
6
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
1.2. МИНИМАЛЬНАЯ КОНФИГУРАЦИЯ ТЕХНИЧЕСКИХ И ПРОГРАММНЫХ
СРЕДСТВ
Минимальная конфигурация GSAU включает в себя
- контроллер для управления насосами - ????????
- выделенный сервер, работающий под управлением FreeBSD 4.6 c
установленным Sybase ASA SQL сервером. Допускается использование Linux.
- хотя бы один клиент, работающий под управлением Windos 32.
Рекомендутеся WinNT, (Win2000, WinXP).
- требуется наличие установленного и настроенного программного
обеспечения для поддержки сети, использующей протоколы TCP/IP. Требования к
сетевому оборудованию и программному обеспечению совпадают с требованиями
Sybase SQL Anywhere.
1.3. ПРОЦЕДУРА УСТАНОВКИ GSAU
not ready
1.4. ЗАПУСК И ОСТАНОВ GSAU
not ready
7
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
2. ОПИСАНИЕ "Gass Station Advanced Utilities"
2.1. ВВЕДЕНИЕ
После нескольких лет изучения литературы, касающейся вопросов
1) построения реляционных баз данных ([1]);
2) построения надежного программного обеспечения ([6]);
3) использования формальных методов для построения надежного
программного обеспечения (RAISE: [2], [3]; VDM: [7]),
и, пообщавшись c некоторыми разработчиками и проектантами, удалось заметить,
что программисты, которые работают в данных областях, как бы игнорируют друг
друга. То есть те, кто использует формальные методы, ни чего не знают про
реляционные базы данных, а те, кто занимется теорией и практикой реляционных
базы данных, ведать не ведают о формальных подходах к построению
программного обеспечения.
В документе делается попытка показать пути для использования языка
формальных спецификаций RAISE для проектирования БД и наметить возможности
по автоматической генерации SQL - скриптов и кода, написанного на
процедурных языках (например C++) из формальных спецификаций языка RAISE.
Таким образом, используя мощь формальной пошаговой разработки и жесткой
проверки типов на ранних стадиях RAISE Development Method-а, можно было бы
добиться существенного прогресса в таких нетривиальных вопросах, например,
как согласованное измененение типов полей таблиц в SQL - скриптах языка
определения данных и, соответствующих этим полям, переменных процедурного
языка.
В связи с очевидной необьятностью данной задачи в общем (замахиваться
на генерацию всех тонкостей, например, SQL от Oracle - на наш взгляд
бесперспективная задача), было принято решения сконцентрироваться на
подмножестве DML (язык манипулирования данными), как наиболее близкий к
"чистому" SQL и оставить без рассмотрения всевозможные диалекты для создания
хранимых процедур (PL/SQL, Transact SQL, Watcom SQL и так далее). В
результате удалось
1) создать специальный тип отношение Relation, как отображение из
натуральных чисел(поля первичного ключа) в неинтерпретируемую запись
(собственно сама запись);
2) ввести функции (-члены класса), моделирующие все четыре операци
(Insert, Update, Delete, Select с учетом организации курсоров);
8
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
3) ввести функции (-члены класса), моделирующие фразу where (where);
4) ввести функции (-члены класса), моделирующие проверку всевозможных
ограничений целостности (check, unique);
5) промоделировать условия ссылочной целостности (referential
integrity);
6) и показать способ записывания триггеров.
7) показать какие поля структур должны иметь умолчательные значения и
могут не вводится в БД, а какие обязательно должны вводится явно. Это можно
сделать через перегрузку функции insert.
Со стороны клиентской части приложения (процедурный язык высокого
уровня) была создана библиотека обмена с базой данных ([4], [5]), основанная
на идее использования для обмена (Select, Update, Insert) информацией не
отдельных host- переменных, а специальных структур обмена, которые
автоматически создаются из определения таблицы или обзора. Причем удалось
добиться "существенной похожести" обьектов, наследующих свойства типа
отношеня Relation и структур обмена, таким образом, что одна строчка языка
формальных спецификаций транслируется в одну (ну почти одну) строчку
процедурного языка. В данном случае - C++.
Все вышеизложенное позволяет считать что создан некоторый подход,
позволяющий проектировать и разрабатывать приложения, основанные на
реляционных базах данных таким формальным методом как RAISE Development
Method. В качестве иллюстрации по использованию данного подхода приводится
пример разработка протокола общения между контроллером насосов и клиентскими
местами (операторами) заправочной станции.
2.2. ОБЩАЯ СХЕМА КОМПОНЕНТ GSAU И ИНТЕРФЕЙСОВ МЕЖДУ НИМИ
Согласно рекомендациям ([6]) определим компоненты из которых состоит
система GSAU и проследим потоки данных между компонентами.
Cписок компонент системы GSAU:
- исполнитель (agent) - человек, который непосредственно пользуется
насосом и наливает горючее в бак автомобиля;
- бак автомобиля, далее бачок;
- шланг насоса (nozzle);
- насос (pump); кнопка (позиция) выбора горючего, далее кнопка
(position). С каждой кнопкой жестко связана некотороя пропорция в которой
смешивается (или не смешивается) горючее из разных баков заправочной
станции. ;
9
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
- бак заправочной станции, далее бак (tank). На заправочной станции
содержится по два бака горючего разного качества. В момент заправки горючее
из двух баков смешивается в заданной пропорции;
- контроллер - устройство передающиее информацию между насосами и
компьютером;
- com - порт (com port) - устройство, через которое контроллер
подключается к компьютеру.
- драйвер контроллера (driver) - программа, которая позволяет
обменивается информацией контроллеру (через com- порт) и приложению,
использующему контроллер. В нашем случае это "Gass Station Advanced
Utilities";
- имитатор драйвера контроллера - программа, позволяющая использовать
GSAU без физического наличия драйверов контроллера, com- портов,
контроллеров и насосов (в основном для целей отладки и демонстрации работы
GSAU). Запускается на GSAU- сервере.
- имитатор контролера - программа, позволяющая использовать GSAU без
физического наличия контроллеров и насосов (в основном для целей отладки и
демонстрации работы GSAU). Требуется драйвер контроллера, com- порт,
дополнительный компьютер (на котором будет запускаться имитатор контроллера)
и нуль- модем для соединения com- портов на GSAU -сервере и дополнительном
компьютере.
- менеджер драйверов контроллера (manager) - программа, маскирующая от
основной части GSAU особенности реализации и сам факт наличия того или иного
контроллера.
- наблюдатель за корректростью изменения состояния насоса (pump
monitor), наблюдатель состояний.
- база данных - не комментируется.
- UDP/TCP отправитель и получатель - компоненты GSAU, для передачи
информации через UDP/TCP протоколы соответствено.
- приложение интерфейса оператора (UI) - основная компонента GSAU -
клиента, позволяющая оператору GSAU наблюдать за работой насосов заправочной
станции и управлять их работой.
- оператор.
Драйвера, менеджер драйверов, наблюдатель состояния, TCP получатель,
UDP отправитель и база данных физически располагаются на GSAU - сервере
(Unix box). Наблюдатель ввода и приложение интерфейса пользователя, UDP
получатель, TCP отправитель - физически располагаются на GSAU - клиенте
(Windows box).
10
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
2.2.1. Описание взаимодействия GSAU- сервера и GSAU- клиента
GSAU- сервер и GSAU- клиент обмениваются информацией друг с другом в
асинхронном режиме через две пары каналов. (Вообще говоря GSAU- клиентов
может быть больше одного, но этот вопрос в данный момент нас не интересует и
на схеме не отражен). В каждой из пар роль одного канала играет
соответствующий протокол интернета, роль второго канала играет
соответствующая таблица БД. Каждая из компонент может послать информацию в
другую компоненту в любой момент времени. От сервера к клиенту (клиентам)
информация посылается через протокол UDP (на схеме - проходит через канал
UDP, таблицу State), так как все клиенты должны отображать все изменения,
которые происходят на насосах станции. Таким образом получаем одного
отправителя и много получателей информации. От клиента (клиентов) к серверу
информация посылается через протокол TCP (канал TCP и таблицу Command), так
как имется в точности один отправитель и один получатель информации.
В каждой отдельной операции пересылки/требования информации
пересылается один отдельно взятый атрибут насоса.
Постулируется следующее поведение пары клиент - сервер. В обоих случаях
(при отправлении и получении информации) сервер ни когда ни чего не ждет,
всегда ждет клиент. В случае если сервер занят приемом информации от
предыдущего клиента, он перестает принимать следующие запросы, и следующий
клиент должен ждать, пока сервер освободится. В случае когда сервер отсылает
информацию, клиент должен сам позаботится о том, чтобы успеть обработать или
сохранить текущую порцию информации перед приемом следующей.
2.2.2. Типы основных потоков данных между GSAU-сервером и
GSAU- клиентом
Основными типами потоков данных есть State, StateIndicator (синоним
Indicator), Command, CommandIndicator (синоним Indicator). Типы Pump и
Position будут использоваться для построения структур обмена и
соответствующих конкретных таблиц на основе типа Relation.
Как было постулированно выше, в каждой отдельной операции передачи
информации между клиентами и сервером, пересылается один отдельно взятый
атрибут насоса. Поэтому тип State есть записью из двух полей
- pump (натуральное число) - содержит уникальный идентификатор насоса,
- и state (может иметь любой тип из заданного множества типов (TTank,
Gas, OnLine и т.д.) - аналог обьединения (Union) языка СИ) каждый из которых
описывает соответствующй атрибут насоса. Таким образом, любая переменная
типа State однозначно задает значение любого атрибута любого насоса.
Далее, тип Command имеет дополнительный атрибут логического типа, что
бы показать должен ли контроллер задать (писать) желаемое значение желаемого
атрибута насоса или контроллер должен вычитать (читать) значение это
значение желаемого атрибута.
11
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
Переменные типа Command и State записываются в соответствующие строки
таблиц базы данных ("медленная" связь). Информация о наличии новой
команды/новом состоянии передается через "быстрый" канал связи (сеть TCP/IP)
переменными типа Indicator, уведомляя об изменениях, произошедших в таблицах
БД. Переменная типа Indicator имеет поля, необходимые для надежной работы и
однозначного определения, передаваемой информации. Поле index - опеределяет
таблицу и колонку в которой произошли изменения, поле id задает строчку этой
таблицы, поле get_set - сообщает является ли заданная строчки командой
установить или вычитать значения.
Большая часть типов для атрибутов, например тип Gas, является записью
(Record) и, одновременно с определением переменной заданного типа,
опеределяет несколько функций, которые могут использоваться вместе с этой
переменной - конструктор, деструкторы и реконструкторы. Имена деструкторов
совпадают с именами полей, имена реконструкторов перечисляются после символа
<->. Рассмотрим изложенное на примере типа Gas. Тут заданы следующие функции
- mk_Gas : Real >< Nat -> Gas - создание записи (конструктор)
- v : Gas -> Real - доступ к полям (деструктор)
- p : Gas -> Nat
- v : Real >< Gas -> Gas - изменение записи (реконструктор)
- p : Nat >< Gas -> Gas
Таким образом, определив переменные или величины как x : Gas, y: Real,
z: Nat, мы получаем возможность писать
- mk_Gas(y,z)
- y = v(x) - а не x.v как в большинстве языков программирования
- 5 < p(x)
- x := v(3.141592, x)
- p(22222, x)
db_start
scheme Types =
extend db_start with class
type
TTank = {|n : Nat:- n <=2 |}, -- 0 нет бака, 1 и 2 номера баков
Gas :: v: Real <-> v -- value of gas
p: Nat <-> p, -- what is position
-- типы для описания отдельных характеристик
-- используются в структуре, для передачи состояния
-- кол-во бензина на заданной кнопке
12
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
OnLine :: v: Bool <-> v ,
-- есть ли связь с насосом
Start :: v: Text <-> v, -- момент, когда начал считать счетчик
-- total
Total :: v: Real <-> v, -- количестов горючего протекшего
-- через насос
Measure, -- единица измерения
FreeFill :: v: Bool <-> v, -- нужно ли ожидать разрешения наливать
-- горючее
-- Query :: v: Text <-> v, -- момент сьема состояния
Button :: v: Nat <-> v, -- агент выбрал кнопку для набора
NozzleUp :: v: Bool <-> v, -- снят ли шланг
Filling :: v: Bool <-> v, -- льется ли горючее
Filled :: v: Real <-> v, -- сколько безина налито в текущем
-- /предыдущем
-- работы цикле
CycleEnd :: v: Bool <-> v, -- разрешение закончить цикл и перейти
-- к след.
-- горючего
Paid :: v: Bool <-> v, -- горючее уже оплачено кредитной
-- карточкой через устройство на насосе
FillStart :: v: Bool <-> v, -- оператор разрешил наливать горючее
Limit :: v: Gas <-> v, -- оператор задал кол-во горючего и
-- кнопку
EndWait :: v: Bool <-> v, -- ожидает разрешение перейти к
-- следующему циклу работы
Freeze :: v: Bool <-> v, -- работа насоса остановлена
Restart :: v: Bool <-> v, -- перевести насос в начальное
-- состояние
Error :: v: Text <-> v, -- обнаружена программная ошибка
Proportion :: p: Nat <-> p
-- uid of position/button
v: {|n: Nat:- n <= 100|} <-> v,
-- пропорция смеси горючего на заданной кнопке
EOG :: p: Nat <-> p
isGas: Bool <-> isGas,
-- end of gas на заданной кнопке
Tank :: p: Nat <-> p
tank1: TTank <-> tank1
tank2: TTank <-> tank2,
-- два бака горючего на заданной кнопке
Mark :: p: Nat <-> p
name: Text <-> name,
-- марка бензина на заданной кнопке
Price :: p: Nat <-> p
v: Real <-> v,
-- цена бензина на заданной кнопке
13
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
State1 = -- состояние насосов. в этой структуре
-- записывается один из атрибутов
-- насоса
Gas | OnLine | Total | Start | Freeze |
Error | Restart | --Query |
Proportion | Filled | EndWait | CycleEnd | Filling |
EOG | NozzleUp | Limit | FillStart | FreeFill |
Tank | Measure | Paid |
Mark | Price | Button
,
State :: pump : Nat <-> pump -- uid of pump
state : State1 <-> state --
,
Indicator -- информация, передаваемая от сервера к клиенту
-- (и обратно)
-- по быстрому каналу связи. получатель использует
-- эту информацию для чтения изменения в состоянии
-- и отображения этого изменения
::
messageNo : Nat <->
messageNo -- последов.номер сообщения
-- для решения вопроса было
-- ли потеряно некоторое
-- сообщение при передаче
index : Nat <->
index -- число, которое определяет
-- таблицу и колонку из
-- которой читать
id : Key <->
id -- номер строчки, которая
-- изменилась
get_set : Bool <->
get_set -- поле имеет различный смысл
-- для индикаторов состояний и
-- индикаторов команд
--
-- I am to lazy to modify rest of rsl-code
-- note : Text <->
-- note -- поле предназначено для
-- -- перечи информацией,
-- -- неинтерпретируемой
-- -- рассматриваемой компонентой
,
StateIndicator = Indicator
-- get_set = false => значение поля
-- было потребовано оператором
-- get-set = true => значение поля было вычитано
-- сервером без команды оператора
,
Pump -- описание насосов в БД и
-- параметры насоса (меняются редко)
14
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
--
--
:: uid : Nat <-> uid
onLine : Bool <-> onLine
start : TDate <-> start
total : Real <-> total
measure : Text <-> measure
nPoss : Nat <-> nPoss
-- ? сколько кнопок на насосе
freeFill : Bool <-> freeFill
-- сигналы, поступающие со стороны агента
button : Nat <-> button -- кнопка на насосе,
-- выбранная агентом
nozzleUp : Bool <-> nozzleUp
filling : Bool <-> filling
filled : Real <-> filled
paid : Bool <-> paid
endWait : Bool <-> endWait
-- сигналы, поступающие со стороны оператора
fillStart: Bool <-> fillStart
cycleEnd : Bool <-> cycleEnd
setPos : Nat <-> setPos
setLimit : Real <-> setLimit
freeze : Bool <-> freeze
restart : Bool <-> restart
-- это генерируется программой
error : Text <-> error
query : TDate <-> query
-- name : Nat <-> name
,
Position -- описание кнопок на насосе
:: uid : Nat <-> uid
price : Real <-> price
mark : Text <-> mark
tank1 : TTank <-> tank1
tank2 : TTank <-> tank2
eog : Bool <-> eog
proportion: Nat <-> proportion
pump : Key <-> pump
-- name : Text <-> name
,
Command -- команды оператора
= -- представляют собой пару брать/установить
Bool >< -- false - to get new state of pump
-- true - to set new state of pump
-- и что брать/установить. "что" - определяется
State -- ранее введенным типом состояние
15
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
,
CommandIndicator = Indicator
-- get_set = false => оператор потребовал
-- значение поля
-- get_set = true => оператор устанавливает
-- значение поля
--
-- набор служебных функций приложения
--
value
-- является ли изменение состояния допустимым?
-- функция - "guards" [2] для выражения предусловий
-- в данной работе не используется
--
isConversionValid : State >< State -> Bool
, -- функция восстановления состояние насоса
StateCorrection : State >< State ->
Command
,
pStt : StateIndicator, -- предыдущее состояние
rcvCnt: Int -- recovery count - счетчик попыток восстановления
end
2.2.3. Глобальные обьекты проекта
Авторы RSL рекомендуют после определения схемы (файл с
rsl-спецификациями) Types, содержащий типы и атрибуты для не динамических
обьектов, на ее основе определить глобальный обьект T.
Types
object T : Types
После чего ссылаться на введенные типы и атрибуты в форме T.xxx. Например,
для описания прототипа функции get из раздела "Определение функций
интерфейса с базой данных" используется следующий текст
get: T.CommandIndicator ->
write
Pump.any, Position.any,
Cmd4Pmp.any, Cmd4Pos.any
T.Command
16
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
Запись T.Сommand означает, что всюду определенная (total function,
символ ->, в отличие от частично определенных функций, символ -~->) функция
get вырабатывает значения типа Command из значений типа CommandIndicator,
которые были определены в глобальном обьекте T.
Кроме того, данная функция обладает правом писать в любые атрибуты
переменных - обьектов Pump, .... Функции с правом доступа к каким - либо
переменным также будут называться операторами.
2.2.4. Cхема взаимодействия между GSAU-сервером и GSAU
клиентом
17
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
ver 00.90.10 - some description in DB.rsl have been added
ver 00.90.00 - improvement of the description
ver 00.07.06 - the field note have been added to indicator
ver 00.07.05 - there was a bug in the put - functions
ver 00.07.04 - a lot if needless let-s have been
removed from DB.rsl
ver 00.07.03 - phrase check && unique have been added to Relation
ver 00.07.01
. . . . . . . . . . . . . . . . . . . . . .
. TCP .
. .
/-- < TCPReciever <-------------< TCPSender<--------------------\
| . . . . . . . . . . . . . . . . . . . . . . |
|<-----------------\ |
| |. . . . . . . |
/ --->--\---> server>-\ |. . |
| | |\-<Command<---------------------------------\|
| | |. . |
\<DriverManager<-----<| |. DB . |
| |. . /--------< UserInterface<-\
/----------- / |./>State>\ . | |
| |.| |<--------/ |
| /.|. . . .\. . |
\--->PumpMonitor>-\/ /--> client>------------------------/
| |
/-------------------------/ \-------------------\
| . . . . . . . . . . . . . . . . . . . . . . . |
\----------> UDPSender >---------------->UDPReciever>--/
. .
. UDP .
. . . . . . . . . . . . . . . . . . . . . . .
Взаимодействие между \id - сервером и клиентов заключается в том, что
они посылают друг другу индикаторы команд и состояний через каналы TCP/UDP.
Получатив индикатор команды или состояния, соответствующая компонента
(сервер или клиент) читает необходимую информацию из подходящих таблиц БД.
В первых строчках схемы обьявляется использование схем T и DB. Схема T
содержит описание глобального обьекта проекта (обсуждалось выже), схема DB
используется для наследования (extend DB) ее свойств текущей схемой GSAU, то
есть GSAU порождается из схемы DB.
T
,DB
scheme GSAU =
--hide sqlCode in
18
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
extend DB with
class
channel
TCP : T.CommandIndicator,
UDP : T.StateIndicator
variable
msgCnt : Nat := 0
value
-- work of server
Server: Unit ->
write any in TCP out UDP
Unit
Server() is
(let v = TCP? in UDP! server(v) end
|=| -- оператор внешнего выбора
-- если в канале TCP есть что читать,
-- Server должен прочитать это и отреагировать,
-- иначе он может сам вывести информацию
-- об изменениях на насосах в канал UDP.
UDP! server () --
-- подразумевается, что вызов server()
-- отрабатывает быстрее, чем оператор вводит
-- новые команды, так же как и вызов client()
-- (см. ниже) работает быстрее,
-- чем происходят изменения на насосах.
)
; Server()
,
server : T.CommandIndicator ->
write any
T.StateIndicator
-- реакция на сигнал от клиента
server (ci) is -- сервер отвечает
PumpMonitor( DriverManager( get(ci)))
,
server : Unit ->
write any
T.StateIndicator
server () is
PumpMonitor( DriverManager( )) -- сервер генерирует информацию
, -- без запроса клиента
-- компонента, следящая за состояние
-- системы
PumpMonitor: Bool >< --
T.State -~->
write any
T.StateIndicator
PumpMonitor (g_s, s) is
local
19
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
variable
newS : T.State := s,
cnt : Int := 0
in -- попытки восстановления допустимого
-- состояния
while(T.isConversionValid (newS, get(T.pStt)) = false) do
let
(a, b) = DriverManager(T.StateCorrection(newS,
get(T.pStt)
)
)
in
-- newG_s := a;
newS := b
end
;
cnt := cnt + 1;
if cnt >= T.rcvCnt then
stop
end
end;
msgCnt := msgCnt + 1;
put(g_s, newS, msgCnt)
end
,
-- источник возникновения сообщений
-- о измененном состоянии насоса / контроллера
--
DriverManager: T.Command -> Bool >< T.State, -- (true, state)
DriverManager: Unit -> Bool >< T.State, -- (false, state)
-- work of client
Client: Nat -> -- number of client
write any in UDP out TCP
Unit
Client(n) is
(let v = UDP? in TCP! client(v, n) end
|=|
TCP! client(n)
)
; Client(n)
,
client : T.StateIndicator >< Nat ->
write any
T.CommandIndicator
-- оператор реагирует на изменения
20
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
-- в насосах
client ( si, n) is
put( UserInterface ( get(si), n), n)
,
client : Nat -> -- оператор выдал команду
write any
T.CommandIndicator -- для насосов
client (n) is
put( UserInterface ( n ), n)
,
-- источник возникновения команд
-- этой функцией замаскирован оператор
-- системы, который выдает команды
UserInterface: T.State >< Nat -> T.Command,
UserInterface: Nat -> T.Command
end
Описаны взаимодействие между GSAU - сервером и GSAU - клиентами и
алгоритмы работы наиболее крупных компонент. Мы может перейти
непосредственно к рассмотрении функций работы с БД (какие и есть нашим
главным интересом).
2.2.5. Описание БД и операторов языка манипулирования
данными DML
2.2.6. Функции высокоуровневого интерфейса
Следующая схема языка RSL в действительности содержит директивы
для
1) создания 4 - х таблиц в БД. Эти директивы относятся к группе DDL
языка SQL. По - видимому они должны быть реализованы как SQL- скрипт и,
вообще говоря, будут выполняться на SQL -сервере в момент инициализации
экземпляра БД;
2) создания набора функций для интерфейса между выполняемыми файлами и
БД. Мы имеем два выполняемых файла: GSAU- клиент и выполняемый файл,
располагающийся на GSAU - сервере - некоторый процесс (все кроме собственно
БД). Эти функции должны быть транслированы в язык C.
T
21
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
,Relation
,TPump
,TPosition
scheme DB =
extend db_start with
class
2.2.6.1. Определение таблиц базы данных GSAU
В обьекте DB приводится описание всех обьектов, представляющих таблицы
базы данных, и реляционных связей между ними. Использование параметризованых
rsl - схем позволяет описывать ссылочные ограничения целостности.
(referencial integrity) Это достигается передачей в качестве актуального
параметра второго обьекта - партнера (родителя или ребенка) при описании
первого обьекта. Например, в таблице Position есть поле pump, которое
ссылается на таблицу Pump, этот факт отражается, тем что в обьект Position
(соответствующий таблице Position) передается актуальный параметр (родитель)
- обьект Pump (соответствующий таблице Pump), а в обьект Pump передается
актуальный параметр (ребенок) - обьект Position. В обьекте Position
проверяется наличие первичного ключа для ссылки на обьект Pump, а в обьекте
Pump актуальный параметр используется для спецификации алгоритма операции
delete (on delete restrict) - если в обьекте Position есть строчки, которые
ссылаются на первичный ключ p в Pump, то применение операции
Pump.delete({p}) приведет к каскадному удалению этих записей в таблице
Position.
object
-- в эти две таблицы будем
-- записывать параметры команд оператора
--
Cmd4Pmp : TPump (Cmd4Pos)
, Cmd4Pos : TPosition (Cmd4Pmp)
-- State << Pump >< Position
-- в эти две таблицы будем записывать
-- изменения атрибутов насосов и контроллеров
, Position: TPosition (Pump)
, Pump : TPump (Position)
2.2.6.2. Определение функций интерфейса с базой данных GSAU
Все множество функций представляет собой две пары put и get. Одна пара
- положить/взять команду, вторая - положить/взять состояние параметра.
22
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
value
-- положить / взять команду
get: T.CommandIndicator ->
write
Pump.any, Position.any,
Cmd4Pmp.any, Cmd4Pos.any
T.Command
get (ci) is
let T.mk_Indicator (_, idx, id, g_s) = ci in
if idx < 100 then -- будем использовать атрибуты
let p = if -- насоса
g_s
2.2.6.2.1. Использование оператора SELECT
Это пример использования оператора SELECT. В случае трансляции этого
текста в С++ код, в этом месте можно использовать структура обмена данными
(sde). Тогда преобразование кода представляется очевидным. Смотри для
примера файл src/gsau_up.cpp, строчка #35
GSAU_RCmd4Pmp Cmd4Pmp (database);
...
rc = Cmd4Pos.Select(&id); // строчка #59
p = (GSAU_RPosition *) &Cmd4Pos;
...
здесь происходит создание обьекта - структуры обмена данными (sde) Cmd4Pmp и
чтение заданной строчки из таблицы SQL серверва в эту структуру обмена.
После этого можно использовать поля структуры обмена. Они приняли значения
одноименных столбцов таблицы. Пример использования приводится на строчке
#196 файла gsau_pu.cpp.
p->proportion.toStr(), //
Наблюдается полное совпадения. Практически 1 строчка rsl текста
преобразуется в 1 строчку C++ кода.
then
Cmd4Pmp.select(id)
else
Pump.select (id)
end
in -- после извлечения записи она больше
-- не нужна
23
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
2.2.6.2.2. Использование оператора DELETE
Это пример использования оператора DELETE.
if g_s then Cmd4Pmp.delete({id}) end;
-- из записи p извлечь атрибут uid и какой
( g_s, -- сделать из них пару
-- (признак_команды, состояние)
T.mk_State (
T.uid(p),
case idx of
1 -> T.mk_OnLine(T.onLine(p))
,
2 -> T.mk_Start(T.start(p))
,
3 -> T.mk_Total(T.total(p))
,
4 -> T.mk_Measure(T.measure(p))
,
5 -> T.mk_NPos(T.nPos(p))
,
6 -> T.mk_FreeFill(T.freeFill(p))
,
7 -> T.mk_Button(T.button(p))
,
8 -> T.mk_NozzleUp(T.nozzleUp(p))
,
9 -> T.mk_Filling(T.filling(p))
,
10 -> T.mk_Filled(T.filled(p))
,
11 -> T.mk_CycleEnd(T.cycleEnd(p))
,
12 -> T.mk_Paid(T.paid(p))
,
13 -> T.mk_FillStart(T.fillStart(p))
,
14 -> T.mk_Limit(T.mk_Gas(T.setLimit(p),
T.setPos(p)
)
)
,
15 -> T.mk_EndWait(T.endWait(p))
,
16 -> T.mk_Freeze(T.freeze(p))
,
17 -> T.mk_Restart(T.restart(p))
24
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
,
18 -> T.mk_Error(T.error(p))
end
)
)
end
else -- будем использовать атрибуты
let p = if -- кнопки насоса
g_s
then
Cmd4Pos.select(id)
else
Position.select (id)
end
in
if g_s then Cmd4Pos.delete({id}) end;
( g_s,
T.mk_State (
T.uid(p), -- !!!!!! эта ошибка сюда надо ложить
-- уид насоса
case idx of
--
101 -> T.mk_Proportion(T.pump(p), T.proportion(p))
-- ^^^^
-- а сюда уид позиции
,
102 -> T.mk_EOG(T.pump(p), T.eog(p))
,
103 -> T.mk_Tank(T.pump(p),T.tank1(p), T.tank2(p))
,
104 -> T.mk_Mark(T.pump(p), T.mark(p))
,
105 -> T.mk_Price(T.pump(p), T.price(p))
end
)
)
end
end
end
,
put: T.Command >< Nat -> -- client number
write Pump.any, Position.any,
Cmd4Pmp.any, Cmd4Pos.any
T.CommandIndicator
put ((g_s, stt), n) is
local
variable
p : Nat-set := {},
idx : Nat := 0
in
let T.mk_State(pUid, s) = stt in
-- --
25
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
if g_s then -- в случае команды установить
2.2.6.2.3. Использование оператора INSERT
Это пример использования оператора INSERT. В этом месте используется
перегруженная функция insert, в котороя явно задается только поле uid.
Остальные поля принимают значения по умолчанию.
Cmd4Pmp.insert( -- создал запись и вставил ее в спец.
-- таблицу
pUid -- (ЭТО СПЕЦ. ИНСЕРТ cm Pump.rsl)
);
p := {Cmd4Pmp.identity};-- и взял ее id
Cmd4Pmp.query(T.timeStamp(),p)
-- записал время выдачи команды
else -- для чтения - узнать id существующей
-- записи
p:= Pump.uid2id(pUid)
end
;
if p~= {} then
case s of
T.mk_OnLine(b) ->
2.2.6.2.4. Использование оператора UPDATE
Это пример использования оператора UPDATE. С этим оператором есть
небольшая сложность. В случае rsl - текста я не переживаю про
производительность и, как видно ниже, просто заменяю поле onLine таблицы
Cmd4Pmp во всех строчках, первичный ключ которых содержится во множестве p.
Если понадобится редактировать второе поля необходимо поступать таким же
образом. Это не ДОЛЖНО переносится в C++ текст в такой форме (это будет
снижать производительность). Надо поменять значение соответствующих полей
структуры обмена данными и потом выполнить операцию update сразу для всех
полей записи таблицы (структуры обмена).
if g_s then -- если задавать значение
-- то в новую запись вписать значение
-- онлайн
Cmd4Pmp.onLine (b, p)
end; -- иначе ничего не делать
idx := 1
,
T.mk_Start(t) ->
26
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
if g_s then
Cmd4Pmp.start (t, p)
end;
idx := 2
,
T.mk_Total(t) ->
if g_s then
Cmd4Pmp.total (t, p)
end;
idx := 3
,
T.mk_Measure(t) -> -- не готово
if g_s then
Cmd4Pmp.measure (t, p)
end;
idx := 4
,
T.mk_NPos(t) ->
if g_s then
Cmd4Pmp.nPos (t, p)
end;
idx := 5
,
T.mk_FreeFill(t) ->
if g_s then
Cmd4Pmp.freeFill (t, p)
end;
idx := 6
, --
-- попытка установить атрибут насоса
-- шланг_поднять в тру не несет большого
-- смысла, (шланг от этого не подымется)
-- наверно в драйвере эта команда будет
-- запрещена или будет игнорироваться.
-- этоже отностся к NPos и, вообще, к
-- атрибутам для сигналов, поступающих
-- со стороны атента.
-- введено для однообразия и будущего
-- развития.
T.mk_Button(t) ->
if g_s then
Cmd4Pmp.button (t, p)
end;
idx := 7
,
T.mk_NozzleUp(t) ->
if g_s then
Cmd4Pmp.nozzleUp (t, p)
end;
idx := 8
,
T.mk_Filling(t) ->
if g_s then
Cmd4Pmp.filling (t, p)
27
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
end;
idx := 9
,
T.mk_Filled(t) ->
if g_s then
Cmd4Pmp.filled(t, p)
end;
idx := 10
,
T.mk_CycleEnd(t) ->
if g_s then
Cmd4Pmp.cycleEnd (t, p)
end;
idx := 11
,
T.mk_Paid(t) ->
if g_s then
Cmd4Pmp.paid (t, p)
end;
idx := 12
,
T.mk_FillStart(t) ->
if g_s then
Cmd4Pmp.fillStart (t, p)
end;
idx := 13
,
T.mk_Limit(T.mk_Gas(r,b)) ->
if g_s then
Cmd4Pmp.setLimit (r, p);
Cmd4Pmp.setPos (b, p)
end;
idx := 14
,
T.mk_EndWait (t) ->
if g_s then
Cmd4Pmp.endWait (t, p)
end;
idx := 15
,
T.mk_Freeze(t) ->
if g_s then
Cmd4Pmp.freeze (t, p)
end;
idx := 16
,
T.mk_Restart(t) ->
if g_s then
Cmd4Pmp.restart (t, p)
end;
idx := 17
,
T.mk_Error(t) ->
if g_s then
28
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
Cmd4Pmp.error (t, p)
end;
idx := 18
,
T.mk_Proportion (b, v) -> -- а читаю я правильно
if g_s then -- читаю уид позиции
Cmd4Pos.insert( b, hd p) -- спец. таблицу
;
p := {Cmd4Pos.identity};
Cmd4Pos.proportion (v, p)
else -- по уиду позиции и id насоса взяли
-- id позиции
p := Position.uid_pump2id (b, hd p)
end;
idx := 101
,
T.mk_EOG (b, v) ->
if g_s then -- ошибочка есть
Cmd4Pos.insert( b, hd p)
;
p := {Cmd4Pos.identity};
Cmd4Pos.eog (v, p)
else
p := Position.uid_pump2id (b, hd p)
end;
idx := 102
,
T.mk_Tank (b, t1, t2) ->
if g_s then
Cmd4Pos.insert( b, hd p)
;
p := {Cmd4Pos.identity};
Cmd4Pos.tank1 (t1, p);
Cmd4Pos.tank2 (t2, p)
else
p := Position.uid_pump2id (b, hd p)
end;
idx := 103
,
T.mk_Mark (b, v) ->
if g_s then
Cmd4Pos.insert( b, hd p)
;
p := {Cmd4Pos.identity};
Cmd4Pos.mark (v, p)
else
p := Position.uid_pump2id (b, hd p)
end;
idx := 104
,
T.mk_Price (b, v) ->
if g_s then
Cmd4Pos.insert( b, hd p)
;
29
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
p := {Cmd4Pos.identity};
Cmd4Pos.price (v, p)
else
p := Position.uid_pump2id (b, hd p)
end;
idx := 105
end
end
;
T.mk_Indicator(0, idx,
if p~={} then hd p else T.notFound end, g_s)
end
end
,
-- положить / взять состояние
--
-- the server - client stream
--
get: T.StateIndicator ->
write Pump.any,
Position.any
T.State
get(si) is
let T.mk_Indicator (_, idx, id, _) = si in
if idx < 100 then
let p = Pump.select(id) in
T.mk_State ( T.uid(p),
case idx of
1 -> T.mk_OnLine(T.onLine(p))
,
2 -> T.mk_Start (T.start(p))
,
3 -> T.mk_Total (T.total(p))
,
-- 4 -> T.mk_Measure (T.measure(p))
-- ,
-- 5 -> T.mk_NPos (T.nPos (p))
-- ,
6 -> T.mk_FreeFill (T.freeFill(p))
,
7 -> T.mk_Button(T.button(p))
,
8 -> T.mk_NozzleUp (T.nozzleUp (p))
,
9 -> T.mk_Filling (T.filling (p))
,
10 -> T.mk_Filled(T.filled(p))
,
11 -> T.mk_CycleEnd (T.cycleEnd (p))
,
12 -> T.mk_Paid (T.paid (p))
,
13 -> T.mk_FillStart (T.fillStart(p))
30
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
,
14 -> T.mk_Limit (T.mk_Gas(T.setLimit (p),
T.setPos(p)
)
)
,
15 -> T.mk_EndWait (T.endWait (p))
,
16 -> T.mk_Freeze (T.freeze(p))
,
17 -> T.mk_Restart (T.restart(p))
,
18 -> T.mk_Error (T.error(p))
end
)
end
else
let p = Position.select(id) in
T.mk_State ( T.uid(p),
case idx of
101 -> T.mk_Proportion (T.pump (p),
T.proportion(p))
,
102 -> T.mk_EOG (T.pump (p), T.eog(p))
,
103 -> T.mk_Tank (T.pump (p), T.tank1(p),
T.tank2(p))
,
104 -> T.mk_Mark (T.pump (p), T.mark(p))
,
105 -> T.mk_Price (T.pump (p), T.price(p))
end
)
end
end
end
,
--
-- вывод состояния в БД
-- и создание индикатора состояния
--
put: Bool >< T.State >< Nat
-> -- выводить состояние можно на всякий
write --State.any,
-- надо изменить строчку либо в
Pump.any,
Position.any
T.StateIndicator
-- таблице Position, либо в Pump
put(g_s, stt, cnt) is --
local
variable
31
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
p : Nat-set := {}, -- состояние s
idx : Nat := 0 -- проапдейтили значение кнопки
in -- для насоса с id p
let T.mk_State(pUid, s) = stt in -- для насоса p получили
-- изменение
p := Pump.uid2id(pUid) ;
if p ~= {} then
Pump.query(T.timeStamp(), p);
case s of
T.mk_OnLine(b) -> Pump.onLine(b,p) ;
idx := 1
,
T.mk_Start(t) -> Pump.start(t,p);
idx := 2
,
T.mk_Total(r) -> Pump.total(r,p);
idx := 3
,
-- T.mk_Measure() -> skip 4
-- T.mk_NPos () -> skip 5
T.mk_FreeFill(b) -> Pump.freeFill (b, p);
idx := 6
,
T.mk_Button(n) ->
Pump.button(n,p);
idx := 7
,
T.mk_NozzleUp(b) -> Pump.nozzleUp(b, p);
idx := 8
,
T.mk_Filling(b) -> Pump.filling (b, p);
idx := 9
,
T.mk_Filled(r) -> Pump.filled (r, p);
idx := 10
,
T.mk_CycleEnd(b) -> Pump.cycleEnd (b,p);
idx := 11
,
T.mk_Paid(b) -> Pump.paid (b,p);
idx := 12
,
T.mk_FillStart(b)-> Pump.fillStart (b, p);
idx := 13
,
T.mk_Limit(T.mk_Gas(r,b)) -> -- команда задает два
-- значения
-- кнопку и кол-во горючего
Pump.setLimit (r,p);
Pump.setPos (b,p);
idx := 14
,
32
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
T.mk_EndWait(b) -> Pump.endWait(b,p);
idx := 15
,
T.mk_Freeze(b) -> Pump.freeze(b,p);
idx := 16
,
T.mk_Restart(b) -> Pump.restart(b,p);
idx := 17
,
T.mk_Error(b) -> Pump.error(b,p);
idx := 18
,
2.2.6.2.5. Использование оператора UPDATE #2
T.mk_Proportion(b,v) ->
p := Position.uid_pump2id(b, hd p);
Position.proportion(v, p);
idx := 101
--
-- update Proportion set proportion = :v
-- where id in (select id
-- from Proportion
-- where uid = :b and
-- pump = :p
-- )
--
,
T.mk_EOG(b, v) ->
p := Position.uid_pump2id (b, hd p);
Position.eog(v, p);
idx := 102
,
T.mk_Tank(b, t1, t2) ->
p := Position.uid_pump2id(b, hd p);
Position.tank1(t1, p);
Position.tank2(t2, p);
idx := 103
,
T.mk_Mark(b,v) ->
p := Position.uid_pump2id(b, hd p);
Position.mark(v, p);
idx := 104
,
T.mk_Price(b, v) ->
p := Position.uid_pump2id(b, hd p);
Position.price( v, p);
idx := 105
-- ,
33
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
-- _ -> skip
end
end;
T.mk_Indicator(cnt,
idx,
if p~={}then hd p else T.notFound end,
g_s)
end
end
end
2.2.6.3. Описание таблицы типа TPump.
Этот текст непосредственно должен конвертироваться в SQL-скрипт
генерации БД. Так как RSL по умолчанию не создает функции именения поля
необходимо для полей которые можно редактировать в таблице надо задать
функции изменения поля. Они являются аналогом SQL - оператора
UPDATE Pump SET xxxx=yyyyy WHERE id in {ks}
Примечание
Возможно, что так как в SQL редактирование разрешено по умолчанию,
то надо создать новый тип в RSL (или как - то параметризовать
Short Record Definition), для которого генерировать эти функции
автоматически. И, только, в случае явного запрета редактировать
поля не генерировать их.
Тип создается на основе типа обьявленного в RSL - схеме Relation. Схема
параметризуется подчиненной таблицей типа TPosition. Показано, что в
SQL-скрипте создания подчиненной таблицы должно появится обьявление внешнего
ключа внешнего ключа (ссылочная целостность), ссылающегося на поле id
главной таблицы типа TPump. Кроме того, операция удаления строчки в главной
таблице должна вызывать каскадное удаление строчек в подчиненной таблице.
T
,Relation -- ST - slave table
scheme TPump ( ST: Relation(T{Position for record}) )
=
-- запись record заменил на запись Pump
-- теперь можно редактировать поля
extend hide hideDelete in use hideDelete for delete in
Relation (T {Pump for record} ) with
--
--
class
34
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
value
--
-- функции изменения полей (аналог update)
--
uid : Nat >< Key-set -> write tbl, sqlCode Unit
uid (b, ks) is set_int (b, ks, T.uid)
,
onLine : Bool >< Key-set -> write tbl, sqlCode Unit
onLine (b, ks) is set_bool (b, ks, T.onLine)
,
start : Text >< Key-set -> write tbl, sqlCode Unit
start (b, ks) is set_text (b, ks, T.start)
,
total : Real >< Key-set -> write tbl, sqlCode Unit
total (b, ks) is set_real (b, ks, T.total)
,
measure : Text >< Key-set -> write tbl, sqlCode Unit
measure (b, ks) is set_text (b, ks, T.measure)
,
nPoss : Nat >< Key-set -> write tbl, sqlCode Unit
nPoss (b, ks) is set_int (b, ks, T.nPoss)
,
freeFill: Bool >< Key-set -> write tbl, sqlCode Unit
freeFill(b, ks) is set_bool (b, ks, T.freeFill)
,
query : Text >< Key-set -> write tbl, sqlCode Unit
query (b, ks) is set_text (b, ks, T.query)
,
button : Nat >< Key-set -> write tbl, sqlCode Unit
button (b, ks) is set_int (b, ks, T.button)
,
nozzleUp : Bool >< Key-set -> write tbl, sqlCode Unit
nozzleUp (b, ks) is set_bool (b, ks, T.nozzleUp)
,
filling : Bool >< Key-set -> write tbl, sqlCode Unit
filling (b, ks) is set_bool (b, ks, T.filling)
,
filled : Real >< Key-set -> write tbl, sqlCode Unit
filled (b, ks) is set_real (b, ks, T.filled)
,
cycleEnd : Bool >< Key-set -> write tbl, sqlCode Unit
cycleEnd(b, ks) is set_bool (b, ks, T.cycleEnd)
,
paid : Bool >< Key-set -> write tbl, sqlCode Unit
paid (b, ks) is set_bool (b, ks, T.paid )
,
fillStart: Bool >< Key-set -> write tbl, sqlCode Unit
fillStart(b, ks) is set_bool (b, ks, T.fillStart)
35
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
,
setPos : Nat >< Key-set -> write tbl, sqlCode Unit
setPos (b, ks) is set_int (b, ks, T.setPos)
,
setLimit: Real >< Key-set -> write tbl, sqlCode Unit
setLimit(b, ks) is set_real (b, ks, T.setLimit)
,
endWait : Bool >< Key-set -> write tbl, sqlCode Unit
endWait (b, ks) is set_bool (b, ks, T.endWait)
,
freeze : Bool >< Key-set -> write tbl, sqlCode Unit
freeze (b, ks) is set_bool (b, ks, T.freeze)
,
restart : Bool >< Key-set -> write tbl, sqlCode Unit
restart (b, ks) is set_bool (b, ks, T.restart)
,
error : Text >< Key-set -> write tbl, sqlCode Unit
error (b, ks) is set_text (b, ks, T.error)
,
--
-- поля для оператора Update закончились
--
Необходимо уметь задавать умолчательные значения поля таблицы и уметь
показать эти значения программисту.
Перегруженная функция insert содержит эти значения.
Функция uid2id является примером применения функции where обьекта
Relation.
insert : Nat -> write tbl, sqlCode, identity Unit
insert (uid) is
insert ( T.mk_Pump (uid, false, timeStamp(), 0.0,
"litre", 0, false,
0, false, false, 0.0, false, false,
false, false, 0, 0.0, false, false,
"", timeStamp()
)
)
,
uid2id : Nat -> write tbl, sqlCode
Key-set
uid2id ( u) is where ( -\p:T.Pump:- T.uid(p) = u )
Перегруженная функция delete должна выполнять каскадное удаление ()
записей в подчиненной таблице. Перегруженная операция delete
alter table Position
36
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
add constraint pos_pmp_fk
foreign key (pump) references Pump(id)
ON DELETE CASCADE;
является часть этого оператора alter Table. В действительности она задает
фразу "ON DELETE CASCADE".
Примечание
Таким способом можно моделировать любые триггеры, которые нужно
задать на таблице. Очевидно, что за универсальность языка RSL
приходится расплачиваться большим количеством строчек. Текст на
специализированном языке SQL, естественно, получается короче.
,
delete : Key-set -> write ST.any, tbl, sqlCode
Unit
delete (kPmps) is -- delete from ST where pump in :kPmps
ST.delete( {kPos | kPos: T.Key :-
T.pump(ST.tbl(kPos)) isin kPmps
}
);
hideDelete(kPmps)
axiom
Аксиома задает ограничение UNIQUE для поля uid.
[uid_unique]
unique (-\ (x,y): T.Pump >< T.Pump :- T.uid (x) = T.uid(y))
-- all x, y: Key :-
-- {x,y} <<= dom tbl /\ T.uid(tbl(x)) = T.uid(tbl(y))
-- =>
-- x = y
,
[measure]
check (-\ r: T.Pump :- T.measure(r) isin { "litre", "gallon"} )
end
37
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
2.2.6.4. Описание таблицы типа TPosition.
Параметризация нужна, что бы показать зависимость этой таблицы от
другой. Актуальный параметр используется в аксиоме primary_pump.
T
,Relation
scheme TPosition ( R: class type
record,
relation = Nat -m-> record
variable
tbl : relation
end
)
=
extend Relation ( T {Position for record} ) with
-- запись record заменил на запись Pump
-- теперь можно редактировать поля
class
value
uid : Nat >< Key-set -> write tbl, sqlCode Unit
uid (b, ks) is set_int (b, ks, T.uid)
,
price : Real >< Key-set -> write tbl, sqlCode Unit
price (b, ks) is set_real (b, ks, T.price)
,
mark : Text >< Key-set -> write tbl, sqlCode Unit
mark (b, ks) is set_text (b, ks, T.mark)
,
tank1 : T.TTank >< Key-set -> write tbl, sqlCode Unit
tank1 (b, ks) is set_int (b, ks, T.tank1)
,
tank2 : T.TTank >< Key-set -> write tbl, sqlCode Unit
tank2 (b, ks) is set_int (b, ks, T.tank2)
,
eog : Bool >< Key-set -> write tbl, sqlCode Unit
eog (b, ks) is set_bool (b, ks, T.eog)
,
proportion : Nat >< Key-set -> write tbl, sqlCode Unit
proportion (b, ks) is set_int (b, ks, T.proportion)
,
-- это поле я не разрешаю редактировать после создания
-- pump : Nat >< Key-set -> write tbl, sqlCode Unit
-- pump (b, ks) is set_int (b, ks, T.pump)
-- ,
-- uid2id : Nat -> write tbl, sqlCode -- лишняя функция
38
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
-- Key-set
-- uid2id ( u) is where ( -\p:T.Position:- T.uid(p) = u )
-- ,
insert : Nat >< Key -> write tbl, sqlCode, identity Unit
insert (uid, p) is
insert ( T.mk_Position (
uid, 0.0, "", 0, 0, false, 0, p
)
)
,
uid_pump2id : Nat >< Nat -> write tbl, sqlCode
Key-set
uid_pump2id ( u, pmp) is
where ( -\p:T.Position:-
T.uid(p) = u /\ T.pump(p) = pmp
)
,
foo : Nat -> write tbl , sqlCode Unit
axiom
[uid_pump_unique] -- (uid, pump ) is unique
unique (-\ (x,y): T.Position >< T.Position :-
T.uid (x) = T.uid(y) /\
T.pump(x) = T.pump(y)
)
-- all x, y: Key :-
-- {x,y} <<= dom tbl /\
-- T.uid(tbl(x)) = T.uid(tbl(y)) /\
-- T.pump(tbl(x)) = T.pump(tbl(y))
-- =>
-- x = y
,
Аксиома задает большую часть будущего DDL - оператора
alter table Position
add constraint pos_pmp_fk
foreign key (pump) references Pump(id)
ON DELETE CASCADE;
В действительности она задает все кроме фразы "ON DELETE CASCADE".
[primary_pump] -- pump must be exist
all pos : T.Position :- pos isin rng tbl
=>
T.pump(pos) isin dom R.tbl
39
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
end
2.2.6.5. Описание нового типа данных Relation.
На произвольном типе данных (type record) задана таблица как
отображение из целых чисел в record. Введены операции insert, delete,
select, update. Операция update изменяет всю запись целиком. Функции
set_xxxx будут использоваться в функциях обновления поля позже, когда запись
начнет иметь поля (то есть на основе абстрактного типа Relation будет
построен конкретный тип для некоторой таблицы, например, TPump).
Функции check и unique представляют собой аналоги соответствующих фраз
CHECK и UNIQUE оператора CREATE TABLE.
db_start
--,rel
scheme Relation ( R: class type record end) =
hide hDefined in
extend db_start with
class
type
record = R.record,
relation = Nat -m-> record
variable
tbl : relation
value
garbage: record,
-- функция для проверки ограничений
-- целостности
check : (record -> Bool) -> read tbl Bool
check (p) is
( all x : Key :- x isin dom tbl => p(tbl(x)) )
,
-- функция для проверки ограничения
-- unique
unique : ((record >< record) -> Bool) -> read tbl Bool
unique (p) is
( all x, y : Key :- {x,y} <<= dom tbl =>
( p(tbl(x), tbl(y)) => x = y )
)
,
-- аналог операции Insert
insert : Key >< record -> write tbl, sqlCode, identity
40
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
Unit
insert (k, r) is
if ~hDefined(k) then
tbl := tbl !! [k +> r];
sqlCode :=Ok;
identity := k
else
sqlCode := Err;
identity := k
end
,
insert : record -> write tbl, sqlCode, identity
Unit
insert ( r) is insert (autoInc(dom tbl), r)
,
-- аналог операции Delete
delete : Key-set -> write tbl, sqlCode
Unit
delete (k) is
if hDefined(k) then
tbl := tbl \ k;
sqlCode := Ok
else
sqlCode := notFound
end
,
delete : Unit -> write tbl, sqlCode
Unit
delete () is
delete (dom tbl)
,
-- аналог операции Update
update : Key >< record -> write tbl, sqlCode Unit
update (k, r) is
if hDefined(k) then
tbl := tbl !! [k +> r];
sqlCode :=Ok
else
sqlCode := Err
end
,
-- аналог операции Select
select: Key -> read tbl
write sqlCode
record
select (k) is
if hDefined (k) then
sqlCode := Ok;
41
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
tbl(k)
else
sqlCode := notFound;
garbage
end
,
-- вспомогательная
-- функция where используется для
-- построения функций, отображающих
-- некоторые наборы полей в первичные
-- ключи. может использовться как
-- фраза where языка SQL
where: (record -> Bool) -> read tbl
Key-set
where (p) is
{x| x: Key :- p(tbl(x))}
,
hDefined: Key ->
read tbl
Bool
hDefined (k) is k isin dom tbl
,
hDefined: Key-set ->
read tbl
Bool
hDefined (k) is k inter dom tbl ~= {}
,
set_text : Text >< Key >< (Text >< record -> record)
-> write tbl, sqlCode
Unit
-- s_f - функция, которая
-- меняет поле в записи
set_text (fld, k, s_f) is
update(k, -- заменить запись на новую
s_f(fld, -- изменить поле
select(k) -- взять запись
)
)
,
set_text : Text >< Key-set >< (Text >< record -> record)
-> write tbl, sqlCode
Unit
set_text (fld, ks, s_f) is
if ks ~= {} then
let k = hd ks in
set_text (fld, k, s_f);
set_text (fld, ks \ {k}, s_f)
end
end
42
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
,
set_int : Int >< Key >< (Int >< record -> record)
-> write tbl, sqlCode
Unit
set_int (fld, k, s_f) is
update(k, s_f(fld, select(k)))
,
set_int : Int >< Key-set >< (Int >< record -> record)
-> write tbl, sqlCode
Unit
set_int (fld, ks, s_f) is
if ks ~= {} then
let k = hd ks in
set_int (fld, k, s_f);
set_int (fld, ks \ {k}, s_f)
end
end
,
set_real : Real >< Key >< (Real >< record -> record)
-> write tbl, sqlCode
Unit
set_real (fld, k, s_f) is
update(k, s_f(fld, select(k)))
,
set_real : Real >< Key-set >< (Real >< record -> record)
-> write tbl, sqlCode
Unit
set_real (fld, ks, s_f) is
if ks ~= {} then
let k = hd ks in
set_real (fld, k, s_f);
set_real (fld, ks \ {k}, s_f)
end
end
,
set_char : Char >< Key >< (Char >< record -> record)
-> write tbl, sqlCode
Unit
set_char (fld, k, s_f) is
update(k, s_f(fld, select(k)))
,
set_char : Char >< Key-set >< (Char >< record -> record)
-> write tbl, sqlCode
Unit
set_char (fld, ks, s_f) is
if ks ~= {} then
let k = hd ks in
set_char (fld, k, s_f);
set_char(fld, ks\{k}, s_f)
end
end
,
43
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
set_bool : Bool >< Key >< (Bool >< record -> record)
->
write tbl, sqlCode
Unit
set_bool (fld, k, s_f) is
update(k, s_f(fld, select(k)))
,
set_bool : Bool >< Key-set >< (Bool >< record -> record)
-> write tbl, sqlCode
Unit
set_bool (fld, ks, s_f) is
if ks ~= {} then
let k = hd ks in
set_bool (fld, k, s_f);
set_bool(fld, ks\{k}, s_f)
end
end
end
2.2.7. Описание работы менеджера драйверов
not ready
2.2.8. Описание работы драйверов контроллеров
not ready
2.2.9. Описание работы имитатора контроллера
not ready
2.2.10. Описание работы оператора
not ready
44
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
3. РУКОВОДСТВО ПРОГРАММИСТА
3.1. СХЕМА РЕЛЯЦИОННЫХ СВЯЗЕЙ GSAU
Схема реляционных связей достаточно проста. Она соединяет две пары
таблиц БД отношением один ко многим.
Pump Position
id <------- id
uid | uid
onLine | price
start | mark
total | tank1
measure | tank2
nPoss | eog
freeFill | proportion
button \--------------- pump
nozzleUp
filling one (Pump) to many (Position)
filled
cycleEnd
paid
fillStart
setPos
setLimit
endWait
freeze
restart
error
query
3.2. ВНУТРЕННЯЯ СХЕМА БАЗЫ ДАННЫХ GSAU
Таблицы Cmd4Pmp и Cmd4Pos, служащие для передачи команд от оператора к
насосам, не включаются в документ, так как они полностью совпадают с
таблицами Pump и Position.
45
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
3.2.1. Based datatypes
Don't pay attention to aux columns. It is only the technical trick to
avoid a blocking of a table during of a multyuser work in a LAN.
3.2.1.1. Meassure
В специфакации было задано ограничение на единицу измерения бензина.
//drop table GSAU.TMeassure;
create // short symonym
table GSAU.TMeassure ( // tsz
id unsigned
integer not null
default _AUTOINCREMENT, //
aux TAux,
name TName, //unique, // nm
note TNote, //
primary key (id)
);
//
//revoke all on gsau.Meassure from GSAU;
grant all on gsau.TMeassure to GSAU;
revoke update on gsau.TMeassure from GSAU;
revoke delete, update on gsau.TMeassure from GSAU;
grant update(aux) on gsau.TMeassure to GSAU;
insert into gsau.TMeassure(id, name)
values (0, 'gallon');
insert into gsau.TMeassure(id, name)
values (1, 'litre');
commit;
3.2.1.2. Pump
//drop table GSAU.Pump;
46
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
create
table GSAU.Pump (
id ulong not null
default _AUTOINCREMENT,
aux TAux,
uid TUid,
onLine TNoYes,
start_ datetime not null default timestamp,
total TQtty,
meassure TMeassure, // it is not char(xx) type becouse
// my interface library support only ulong
// as a foreign key
nPoss ulong not null default 0,
freeFill TNoYes,
button ulong not null default 0,
nozzleUp TNoYes,
filling TNoYes,
filled TNoYes,
cycleEnd TNoYes,
paid TNoYes,
fillStart TNoYes,
setPos ulong not null default 0,
setLimit TQtty,
endWait TNoYes,
freeze TNoYes,
restart TNoYes,
error TNote,
query datetime default current timestamp,
primary key (id)
);
//
//revoke all on gsau.Pump from GSAU;
grant all on gsau.Pump to GSAU;
--revoke update on gsau.Pump from GSAU;
--revoke delete, update on gsau.Pump from GSAU;
--grant update(aux) on gsau.Pump to GSAU;
3.2.1.3. Position
//drop table GSAU.Position;
create
table GSAU.Position (
id ulong not null
default _AUTOINCREMENT,
47
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
aux TAux,
uid TUid,
price TQtty,
mark TSName, // it is not char(xx) type becouse
// my interface library support only ulong
// as a foreign key
tank1 ulong not null default 0
CHECK (tank1 >=0 and tank1 <= 2),
tank2 ulong not null default 0
CHECK (tank2 >=0 and tank2 <= 2),
eog TNoYes,
proportion ulong not null default 0
CHECK (proportion >=0 and proportion <= 100),
pump ulong not null, // you can't edit pump
primary key (id),
unique (uid, pump)
);
//
//revoke all on gsau.Position from GSAU;
grant all on gsau.Position to GSAU;
revoke update on gsau.Position from GSAU;
grant update( aux, uid, price, mark, tank1, tank2, eog, proportion)
on gsau.Position to GSAU;
--revoke delete, update on gsau.Position from GSAU;
alter table gsau.Position
add constraint pos_pmp_fk
foreign key (pump) references gsau.Pump(id)
ON DELETE CASCADE;
3.3. MAKEFILEs
Построение базы данных, динамически подгружаемой библиотеки,
выполняемого файла и документации производится утилитой make и
соответствующий makefile.
Параметры для утилиты make задаются в файле gsau/pars.mk. Переменные
среды для корректной работы утилиты make, в случае установленной ViSual
Studio, в первых строчках скрипта gsau/mk.bat
Для построения (перед выполнение бат файла надо зайти в соответствующий
каталог) :
a) базы данных - gsau/main/db.mk. Вызов -
48
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
mk.bat foo
Результат - построенная БД gsau/main/foo.db, промежуточные файлы -
скрипты генерации в gsau/bld/*.sql;
b) библиотеки - gsau/crtdll.mk. Вызов -
mk.bat gsau
Результат - построенные библиотеки gsau/bld/gsau.dll и
gsau/bld/gsau.lib, промежуточные файлы - структуры обмена (sde) в
gsau/bld/x/*.cpp и *.;
c) выполняемого файла - gsau/t_x.mk. Вызов -
mk.bat t_gsau
Результат - построенный выполняемый файл gsau/bld/t_gsau.exe;
d) документации - gsau/docs/ascii/ascii_doc.mk. Вызов -
mk.bat
Результат - построенная документация gsau/docs/ascii/bld/gsau.txt;
Примечание
Для построения скриптов используется утилита sed.exe (смотри
каталог gsau/sed).
Для построения библиотеки используется утилита u_mkSDE.exe
Для построения документации используется форматер plain text
файлов - rio.exe
3.3.1. Зависимости от других проектов
Список хедеров и библиотек, от которых зависит данный проект находится
в файле GSAU/cp_lib.bat.
3.4. ОПИСАНИЕ СТРУКТУР ОБМЕНА ГЕНЕРИРУЕМОГО ИНТЕРФЕЙСА
Структура обмена данными (Structure of DataBase Exchange - sde ) между
приложением и БД есть ключевой обьект библиотеки интерфейса с БД - ASAI
(старая версия - DBI3) [4]
49
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
Эти обьекты позволяют
- с одной стороны - выполнять все 4 операции над таблицей SQL сервера
(delete, insert, update, select) из приложения, написанного на C;
- с другой стороны - обьект предоставляет из приложения доступ ко всем
полям записи, и не требует описания переменных для каждого отдельного поля
таблицы.
Важным свойством библиотеки является наличие генератора структур
u_mkSDE.exe, который позволяет создавать структуры обмена для каждой таблицы
прямо из SQL - скриптов генерации БД.
Для кажной таблицы (Foo - имя таблицы, содержится в файле gsau/src/Foo)
создается своя структура обмена (GSAU_RFoo - имя структуры, которая
содержится в файлах gsau/bld/x/Foo.cpp и gsau/bld/x/Foo). Каждое поле
структуры (кроме ключевого) соответствует одноименной колонке таблицы.
Хедеры с описанием структур обмена подключаются файлом gsau/mkSDE.h
3.5. ОПИСАНИЕ ВЫСОКОУРОВНЕГО ИНТЕРФЕЙСА С БД
3.5.1. Хедер макросов и констант
#include <stdio.h>
# ifndef __GSAUDEF_H
# define __GSAUDEF_H
//
#ifdef GSAUEXP
#define GSAU_API __declspec(dllexport)
#else
#define GSAU_API __declspec(dllimport)
#endif
# define GSAU_NAME "gsau"
# define GSAU_VERSION "gsau-00.90.07"
extern const char * GSAU_version;
# define GSAU_UID_SZ 32
50
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
# include "put_get.h"
//# include "mkSDE.h"
3.5.1.1. Command/State Indicator
Описание структуры подключается в файле mkSDE.h
struct GSAU_RIndicator;
typedef GSAU_RIndicator GSAU_StateIndicator;
typedef GSAU_RIndicator GSAU_CommandIndicator;
3.5.1.2. Command/State
При попытке полностью придерживаться RSL- метода и ДОКАЗЫВАНИЯ
корректности построенного приложения, для записей Command/State необходимо
было бы построить глубоко вложенные С++ обьекты и написать массу программ
для конвертирования из одного обьекта в другой. Я не вижу никакого резона
заниматься этим в данном проекте. Сложные структуры моделируются типом char
* с "интуитивно - понятным" содержанием. ( ))))))))) )
typedef char * GSAU_State;
typedef char * GSAU_Command;
Названия макросов отражают слабую попытку помочь "интуитивно -
понятной" интерпертации конструирования из составных частей /
деконструирования на составные части обьектов State, Command.
#define GSAU_mk_State "State"
51
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
#define GSAU_mk_Online "Online"
#define GSAU_mk_Start "Start"
#define GSAU_mk_Total "Total"
#define GSAU_mk_Meassure "Meassure"
#define GSAU_mk_NPos "NPos"
#define GSAU_mk_FreeFill "FreeFill"
#define GSAU_mk_Button "Button"
#define GSAU_mk_NozzleUp "NozzleUp"
#define GSAU_mk_Filling "Filling"
#define GSAU_mk_Filled "Filled"
#define GSAU_mk_CycleEnd "CycleEnd"
#define GSAU_mk_Paid "Paid"
#define GSAU_mk_FillStart "FillStart"
#define GSAU_mk_Limit "Limit"
#define GSAU_mk_EndWait "EndWait"
#define GSAU_mk_Freeze "Freeze"
#define GSAU_mk_Restart "Restart"
#define GSAU_mk_Error "Error"
#define GSAU_mk_Position "Position"
#define GSAU_get_set "get_set"
#define GSAU_mk_Proportion "Proportion"
#define GSAU_mk_EOG "EOG"
#define GSAU_mk_Mark "Mark"
#define GSAU_mk_Price "Price"
#define GSAU_tank1 "tank1"
#define GSAU_tank2 "tank2"
#define GSAU_pump "pump"
# endif
3.5.2. Хедер основных обьектов системы
#include <stdio.h>
# ifndef __GSAU_H
# define __GSAU_H
//
# if !defined(__ASAI_H)
# include "asai.h"
# endif
# if !defined(__DBI_U_H)
# include "dbi_u.h"
# endif
52
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
# if !defined(__GSAUDEF_H)
# include "gsaudef.h"
# endif
typedef class GSAU_DBI {
char buf [_BIGBUF_SZ + 1];
public:
ASAI_TDB * database;
x_bool debug;
GSAU_DBI (
ASAI_TDB * db
) {
database = db;
debug = false;
*buf = 0;
}
~GSAU_DBI (){
database = 0;
debug = false;
*buf = 0;
}
inline int print(const char * _me, const char * format, ...) const {
int rc = 0;
if (debug) {
rc = x_printf ("\n++ %s: ", _me );
va_list ap;
va_start (ap, format);
rc += x_vprintf (format, ap);
}
return rc;
}
// user - pump - direction
----
get: T.CommandIndicator ->
write
Pump.any, Position.any,
Cmd4Pmp.any, Cmd4Pos.any
T.Command
----
friend GSAU_API const GSAU_Command
GSAU_getCmd (
53
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
const GSAU_DBI * db,
const GSAU_CommandIndicator * ci
)
;
const GSAU_Command
getCmd (
const GSAU_CommandIndicator * ci
)
{
return GSAU_getCmd(this, ci);
}
----
put: T.Command >< Nat -> -- client number
write Pump.any, Position.any,
Cmd4Pmp.any, Cmd4Pos.any
T.CommandIndicator
----
friend GSAU_API GSAU_CommandIndicator *
GSAU_putCmd (
const GSAU_DBI * db,
const GSAU_Command c,
const ulong n
)
;
GSAU_CommandIndicator *
put (
const GSAU_Command c,
const ulong clientNo = 0
)
{
return GSAU_putCmd(this, c, clientNo);
}
// pump - user - direction
----
get: T.StateIndicator ->
write Pump.any,
Position.any
T.State
----
friend GSAU_API const GSAU_State
54
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
GSAU_getStt (
const GSAU_DBI * db,
const GSAU_StateIndicator * si
)
;
const GSAU_State
getStt (
const GSAU_StateIndicator * si
)
{
return GSAU_getStt (this, si);
}
----
put: Bool >< T.State >< Nat
-> -- выводить состояние можно на всякий
write --State.any, -- надо изменить строчку либо в
Pump.any,
Position.any
T.StateIndicator -- таблице Position, либо в Pump
----
friend GSAU_API GSAU_StateIndicator *
GSAU_putStt (
const GSAU_DBI * db,
const x_bool g_s,
const GSAU_State stt,
const ulong cnt
)
;
GSAU_StateIndicator *
put (
const x_bool g_s ,
const GSAU_State stt,
const ulong cnt = 0
)
{
return GSAU_putStt (this, g_s, stt, cnt);
}
}
GSAU_DBI;
# endif
55
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
3.6. ФУНКЦИИ КОНСТРУИРОВАНИЯ/ДЕКОНСТРУИРОВАНИЯ COMMAND/STATE
not ready
# ifndef __GSAU_STT_H
# define __GSAU_STT_H
//
# if !defined(__GSAU_H)
# include "gsau.h"
# endif
# endif
56
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
4. ИСПОЛЬЗОВАНИЕ И ПРОВЕРКА РАБОТОСПОСОБНОСТИ
Все примеры подразумевают, что задачи будут пытаться присоединится к
умолчательному серверу по любому доступному протоколу.
пример запуска сервера (версия Sybase Anywhere 7.x) с именем fv:
dbeng7.exe -n fv c:\gsau/main/foo.db
Подготовлен набор тестов для проверки всего пути преобразования данных:
1) от оператора к TCPSender-у: команда +> индикатор
(bld/t_putCmd1.bat);
2) от TCPReciever-а к драйверу насоса: индикатор +> команда
(bld/t_getCmd2.bat);
3) от драйвера насоса к UDPSender-у: состояние +> индикатор
(bld/t_putStt3.bat);
4) от UPDReciever-а к оператору: индикатор +> состояние
(bld/t_getStt4.bat).
Батч - файлы содержат вызовы тестирующей программы с подготовленными
параметрами в командной строке. В связи с большим количеством тестов, там
могут содержатся неточности. сорри. Главная идея такая - результат
выполнения команды из нечетного (xxxx1.bat или xxxx3.bat) должен быть подан
на вход к команде из соответствующего четного файла (xxxx2.bat или
xxxx4.bat).
4.1. ВЫПОЛНЕНИЕ ТЕСТИРУЮЩЕЙ ПРОГРАММЫ
4.1.1. the put/get command/state/indicator
the put/get command/state/indicator
usage:
t_put_get cnnParm;dbg cmd;record >output
whre
cnnParm is like eng=outtrak;uid=dba;pwd=sql
cmd isin {cmd, ci, stt, si}
cmd : to pass command of client and to recieve command indicator
ci : to pass command indicator and to recieve command
57
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
stt : to pass state of pump and to recieve state indicator
si : to pass state indicator and to recieve state
and ci;record is like ci;index_=zzz;id_=yyy;set_get={false|true}
and si;record is like si;index_=zzz;id_=yyy;set_get={false|true}
4.2. ИСПОЛЬЗОВАНИЕ ФУНКЦИЙ ВЫСОКОУРОВНЕВОГО ИНТЕРФЕЙСА С БД
#include <time.h>
#include "gsau.h"
#include "mkSDE.h"
# define _NM "t_put_get"
# define _FNM "the put/get command/state/indicator"
typedef enum rec {
nothing,
cmd ,
ci ,
stt ,
si
}
rec;
main(int argc, char * argv[])
{
long rc = 0;
char *po = 0, *pars = 0;
char crtdef[_BUF_SZ+1];
strcpy(crtdef, ASAI_USER);
crtdef[strlen(crtdef)-1]=0;// to remove .
if (argc > 2) {
clock_t st, fi;
char separator = 0;
char buf [_BUF_SZ + 1] ;
TBool debug1, debug2, check;
rec whatToDo = nothing;
if (*argv[1] == '?')
goto usage;
if(x_parmValue (buf, _BUF_SZ, argv[1], "-?", ';')==_OK)
goto usage;
{
TDouble foo;
x_printf("\n %s, val=%s/%g", foo.toDbg(buf), foo.toStr(),
foo.v);
pars = argv[2];
58
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
foo.strTo(pars, _equalAdd(GSAU_mk_Total, buf));
x_printf("\n %s, val=%s/%g", foo.toDbg(buf), foo.toStr(),
foo.v);
exit(1);
}
//pars
pars = argv[1];
debug1.strTo ( pars, "dbg");
pars = argv[2];
debug2.strTo ( pars, "dbg");
if (check.isHere(pars, "cmd", buf, _BUF_SZ) ==_OK)
whatToDo = cmd;
else if (check.isHere(pars, "ci", buf, _BUF_SZ) ==_OK)
whatToDo = ci;
else if (check.isHere(pars, "stt", buf, _BUF_SZ) ==_OK)
whatToDo = stt;
else if (check.isHere(pars, "si", buf, _BUF_SZ) ==_OK)
whatToDo= si;
check.strTo ( pars, GSAU_get_set); // i have to remove some records
if (whatToDo != nothing) {
printf("\n// %s have been started, debug1/debug2 is %s/%s",
_NM, x_bool((x_bool)debug1), x_bool((x_bool)debug2));
st = clock();
po = "init";
//
// to initialize Sybase ASA Intreface
//
ASAI_TDB db (argv[1], (x_bool) debug1, (x_bool) debug1);
rc = db.err;
if (rc == _OK) {
//
// to create object of high level access to database
//
GSAU_DBI gsau(&db);
gsau.debug = debug2.v;
GSAU_RIndicator * i = 0;
switch (whatToDo) {
case cmd:
po = "cmd";
if((x_bool) check ) {
//
// to create SDE for usage of table gsau.Cmd4Pmp
//
GSAU_RCmd4Pmp Cmd4Pmp ((ASAI_TDB *)gsau.database);
Cmd4Pmp.Delete();
}
//
// to put a command of operator into database and get command
// indicator
59
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
//
i = gsau.put(pars);
if (i) {
// indicator o
// include to exchange
// all the indicators
i->inds(true, SDE_A_fld);
//
// to show a command indicator
//
i->toStr(buf, _BUF_SZ);
x_printf("\n// %s: command indicator is %s", _NM, buf);
delete i;
}
else {
rc = _ERR;
x_printf("\n// %s: command indicator is empty", _NM);
}
break;
case ci :
po = "ci";
//
// in deed i don't use this SDE to exchage a data
//
i = new GSAU_RIndicator();
if (i) {
//
// to get info for indicator from command line
//
i->strTo(pars);
//
// to get a command from database
//
x_printf("\n// %s: command is %s", _NM,
gsau.getCmd(i));
delete i;
}
else {
rc = _ERR;
x_printf("\n// %s: command indicator is empty", _NM);
}
break;
case stt:
check.strTo ( pars, "get_set");
po = "stt";
i = gsau.put( (x_bool)check, pars);
if (i) {
// indicator o
60
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
// include to exchange
// all the indicators
i->inds(true, SDE_A_fld);
i->toStr(buf, _BUF_SZ);
x_printf("\n// %s: state indicator is %s", _NM, buf);
delete i;
}
else {
rc = _ERR;
x_printf("\n// %s: state indicator is empty", _NM);
}
break;
case si :
po = "si";
i = new GSAU_RIndicator();
if (i) {
i->strTo(pars);
x_printf("\n// %s: state is %s", _NM, gsau.getStt(i));
delete i;
}
else {
rc = _ERR;
x_printf("\n// %s: state indicator is empty", _NM);
}
break;
default:
po = "default";
}
}
fi = clock();
printf("\n// %s have been finished after %2.lf secs of work."
" \n//\trc/position=%d/%s/%s",
_NM,
(double)(fi-st)/ CLOCKS_PER_SEC, rc, ASAI_rc2Txt(rc),po);
if (rc != _OK)
fprintf(stderr,"\n// %s: rc/text/position=%d/%s/%s\n", _NM,
rc, ASAI_rc2Txt(rc), po);
}
else {
printf("\n// %s : nothing to do", _NM);
}
return rc;
}
usage:
if (argc > 1 && *argv[1] == '?') {
printf (
"\n.3 %s"
"\n.x SDE"
61
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
"\n.x %s"
"\n.n", _FNM, _NM
);
}
printf ("\n %s", _FNM);
printf ("\nusage:");
printf ("\n%s cnnParm;dbg cmd;record >output", _NM);
printf( "\n\t whre \n cnnParm is like eng=outtrak;uid=dba;pwd=sql" );
printf ("\n cmd isin {cmd, ci, stt, si}");
printf (
"\n cmd : to pass command of client and to recieve command indicator");
printf ("\n ci : to pass command indicator and to recieve command" );
printf ("\n stt : to pass state of pump and to recieve state indicator");
printf ("\n si : to pass state indicator and to recieve state");
printf (
"\n\t and ci;record is like ci;index_=zzz;id_=yyy;set_get={false|true}");
printf (
"\n\t and si;record is like si;index_=zzz;id_=yyy;set_get={false|true}");
if (argc > 1 && *argv[1] == '?'){
printf (
"\n.f"
);
}
return -1;
}
62
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
5. НЕКОТОРЫЕ ВЫВОДЫ
В завершение, поддерживая тезис о том, что число строк исходного
текста, выдаваемое программистом в час, не зависит от языка программирования
(см. [9] ) , приведем некоторую информацию, о количестве строчек, которое
было потрачено, что бы описать GSAU на языке формальных спецификаций RSL и
на языках реализации задачи: С++ и SQL. От себя хочется добавить, что
количество строчек, которое необходимо написать для решения какой либо
задачи, является важной характеристикой языка программирования.
Примечание
Если наш подход по поводу использования RSL для описания
реляционных баз данных был бы принят, то схемы db_start.rsl и
Relation.rsl должны бы быть частью языка RSL. То есть, их не надо
было бы учитывать в общей сумме строчек. Кроме того, так как
большая часть схемы TPump.rsl, TPosition.rsl является просто
заданием функций доступа к полю таблицы, которые должны
существовать по умолчанию, то количество строчек в этих схемах
было бы в два раза меньше.
RSL клиентская серверная коментарии
часть (С++) часть (SQL)
db_start.rsl: 38 не имеет отношения
Relation.rsl: 227 к текущей задаче
DB.rsl: 690 16
GSAU.rsl: 184
T.rsl: 38
t_GSAU.rsl: 11
TPosition.rsl: 113
TPump.rsl: 210
Types.rsl: 270
1193 604 1797
1797 - 38 - 227 = 1532
1532 - 150 = 1582 пересчитано в
604 - 38 - 227 = 339 соответствие с
339 - 150 = 189 замечанием 1
скрипты генерации БД
Cmd4Pmp.sqs: 50
Cmd4Pos.sqs: 46
63
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
CRT_ALL.SQS: 20 +
DROP_STR.SQS: 25 +
Indicator.sqs: 29
inidata.sqs: 45 +
Position.sqs: 46
Pump.sqs: 50
types.sqs: 43
C++ код, написанный вручную
t_put_get.cpp: 217
dllstart.cpp: 25
gsau_pu.cpp: 438
gsau_up.cpp: 501
gsaugsau.h: 26
include2.c: 4
uid.cpp: 32
gsau.h: 146
gsau_stt.h: 15
gsaudef.h: 96
mkSDE.h: 17
put_get.h: 9
1526 354 1880
С++ код, выход утилиты генерации структур обмена
Cmd4Pmp: 45
Cmd4Pmp.cpp: 128
Cmd4Pos: 32
Cmd4Pos.cpp: 63
Indicator: 29
Indicator.cpp: 47
Position: 32
Position.cpp: 63
Pump: 45
Pump.cpp: 128
612 2492 всего
612 + 1526 = 2138 только клиентская часть
Примечание
Далее, необходимо отметить, что в решении задачи GSAU существенную
роль играет уникальная высокоуровневая библиотека обмена с базой
данных. В случае использования других интерфейсных библиотек,
таких как ODBC или Embedde SQL, размер кода вырос бы существенно.
64
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
Итак получаем
RSL реализация
всего 1522 2492
серверная 189 354
часть
клиентская 1193 2138
часть
Даже в условиях использования библиотеки обмена с базой данных
соотношение строчек С++ / RSL приблизительно равно 2.
В тоже время соотнешение SQL / RSL практически равно 1, так как
скрипты, отмеченные знаком +, в действительности не имеют отношения к
задаче, я есть, так сказать, накладным расходом на создание/удаление
структуры БД и ввод начальных значений.
Отсюда можно сделать (вполне очевидный) вывод, что SQL, являсь
специализированным языком весьма высокого уровня и позволяющий писать
эффективные приложения, является уникальным явлением в мире
программирования.
В качестве второго примера приведем статистику полученную при
реализации проекта Harbour (cm. [5] )
Этот пример является образцом гораздо более абстрактной спецификации,
которая не учитывает особенности проектирования БД для РСУБД и не отвечает
на вопросы, интересующие SQL - программиста. Какие алгоритмы относятся к
серверной части (SQL- скриптам) какие к клиентской части (C++) и т.д.
Спецификация (rsl - код) - 147 строчек, реализация клиента (с- код) -
799 строчек + (хедеры) 207 строчек, реализация сервера ( SQL скрипты) - 482
строчки;
итого 1488 строчек кода. Получаем соотношение приблизительно 1 к 10.
65
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
ПЕРЕЧЕНЬ ТЕРМИНОВ И СОКРАЩЕНИЙ
A
B
C
connection
см. соединение
D
E
F
G
H
I
J
K
L
lambda abstration
см. лямбда абстракция
M
N
O
operator
пользователь ЭВМ, управляющий приложением
P
Q
R
S
T
U
V
W
X
Y
Z
A
администратор
оператор с расширенным набором привилегий и обязанностей в "Gass
Station Advanced Utilities".
Б
В
Г
Д
деление на цело
для деления на цело используется символ '%'
Е
Ё
Ж
З
66
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
И
Й
К
Л
лямбда абстракция
следующее выражение, называемое лямбда абстракцие,
- binding : type_expr :- value_expr
представляет функцию типа
type_expr -~-> T
где T есть типа выражения value_expr. Рассмотрим как можно записать
функцию инкремент:
value
incr : Int -> Int
axiom
incr is - x: Int :- x+1
М
Н
О
оператор
- (operator) человек, выполняющий различные действия на компьютере
с запущенным приложением GSAU,
- лицо с минимальным набором привилегий в "Gass Station Advanced
Utilities".
П
печатный документ
Р
С
соединение
пронумерованный сеанс связи на уровне приложения между SQL-клиентом и
SQL-сервером.
Т
таймер
процесс, регулярно выполняющий некоторые действия через заданный
интервал времени
У
Ф
Х
67
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
хранимая процедура
выполняется не на SQL - клиенте, а на SQL - сервере, где она и
хранится.
Ц
Ч
Ш
Щ
Ъ
Ы
Ь
Э
Ю
Я
68
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
INDEX
"Gass Station Advanced Utilities . . . . . . . . . . . . . . . . . . . . 0
драйвер контроллера. . . . . . . . . . . . . . . . . . . . . . . . . . . 9
деление на цело. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
умолчательные значения поля. . . . . . . . . . . . . . . . . . . . . . . 35
исполнитель. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
ссылочная целостность. . . . . . . . . . . . . . . . . . . . . . . . . . 8
ссылочная целостность. . . . . . . . . . . . . . . . . . . . . . . . . . 33
ссылочное ограничение целостности. . . . . . . . . . . . . . . . . . . . 21
структур обмена. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
структура обмана данными . . . . . . . . . . . . . . . . . . . . . . . . 22
схема. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
триггер. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
триггеры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
хранимая процедура . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
таймер . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
соединение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
функции высокоуровневого интерфейса. . . . . . . . . . . . . . . . . . . 20
генератор структур обмена данными. . . . . . . . . . . . . . . . . . . . 49
библиотека обмена с базой данных . . . . . . . . . . . . . . . . . . . . 8
каскадное удаление . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
бак. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
бачок. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
кнопка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
администратор. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
ограничения целостности. . . . . . . . . . . . . . . . . . . . . . . . . 7
ограничения целостности. . . . . . . . . . . . . . . . . . . . . . . . . 8
оператор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
перегруженная функция insert . . . . . . . . . . . . . . . . . . . . . . 35
нуль - модем . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
выполняемый файл . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
насос. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
наблюдатель состояний. . . . . . . . . . . . . . . . . . . . . . . . . . 9
шланг насоса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
agent. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
check. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
check. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
check. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
com - порт . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
com port . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
GSA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
GSAU_Command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
GSAU_RIndicator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
GSAU_State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Indicator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Insert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
INSERT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
69
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
Meassure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
nozzle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
pump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Pump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
pump monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
RAISE Development Method . . . . . . . . . . . . . . . . . . . . . . . . 8
referencial integrity. . . . . . . . . . . . . . . . . . . . . . . . . . 21
referential integrity. . . . . . . . . . . . . . . . . . . . . . . . . . 8
Relation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
rio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
sde. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
SDE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
sed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
sed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Select . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
select . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
State. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Structure of DataBase Exchange . . . . . . . . . . . . . . . . . . . . . 48
t_put_get. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
tank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
TCP/UDP reciever . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
TCP/UDP sender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
TPosition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
u_mkSDE (смотри бат файл u_bgnSDE1.bat) . . . . . . . . . . . . . . . 48
u_mkSDE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
unique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
unique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
unique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
UPDATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
where. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
where. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
70
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
ПЕРЕЧЕНЬ ССЫЛОЧНЫХ ДОКУМЕНТОВ
1) C.J. Date. An intpoduction to database systems. Sixth edition.
Addison-Wesley Publishing Company.
2) The RAISE Language Group. The RAISE SPECIFICATION LANGUAGE. ISBN
0-13-752833-7. Denmark, Herdfordshire, Prentice Hall Europe, 1992.- 396;
3) Hung Dang Van, Chris George, Tomasz Janovwski, and Richard Moore.
Specification Case Studies in RAISE. ISBN 1-85233-359-6 Springer, 2002;
4) O.G.Piskunov, O. Golovko. Application - SQL server data echange
tools. Canadian Intellectual Property Office. Order # 102928, transaction #
250023, 2001;
5) O.G.Piskunov. Harbour - Example of usage RAISE specification method
to develop SQL - based application, 10.12.2001,
www.i.com.ua/~agp1/software/hrb1.0.tar.gz.
6) Г. Майерс. Надежность программного обеспечения. Перевод с
английского Ю.Ю. Галимова, Под редакцией В.Ш. Кауфмана, Издательство "Мир",
Москва, 1980.
7) C.B. Jones. Systematic Software Development - Using VDM, 2nd
Edition. Prentice-Hall International 1989
8) O.G.Piskunov, V.Ilyuhin. Коммуникационная Компонента Системы
Управления Заправочной Станцией, 22.11.2002,
www.i.com.ua/~agp1/software/gsau0.90.tar.gz.
9) B.W. Boehm, Software Engineering Economics, Prentice Hall, Englewood
Cliffs, N.J., 1981
10) Лутц Прехельт, Эмпирическое сравнение семи языков программирования,
Журнал "Открытые системы", #12, 2000, http://www.osp.ru/os/2000/12/045.htm
11) L. Prechelt and B. Unger, A Controlled Experiment on the Effects of
PSP Trimming: Detailed Description and Evaluation, Tech Report 1/1999,
Fakultat fur Informattik, Universitat Karlsruhe, Germany, Mar. 1999
2
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
СОДЕРЖАНИЕ
1. ОБЩИЕ СВЕДЕНИЯ О "Gass Station Advanced Utilities" . . . 5
1.1. НАЗНАЧЕНИЕ "Gass Station Advanced Utilities" . . . . . 5
1.2. МИНИМАЛЬНАЯ КОНФИГУРАЦИЯ ТЕХНИЧЕСКИХ И ПРОГРАММНЫХ
СРЕДСТВ . . . . . . . . . . . . . . . . . . . . . . . 6
1.3. ПРОЦЕДУРА УСТАНОВКИ GSAU . . . . . . . . . . . . . . . 6
1.4. ЗАПУСК И ОСТАНОВ GSAU . . . . . . . . . . . . . . . . 6
2. ОПИСАНИЕ "Gass Station Advanced Utilities" . . . . . . . 7
2.1. ВВЕДЕНИЕ . . . . . . . . . . . . . . . . . . . . . . . 7
2.2. ОБЩАЯ СХЕМА КОМПОНЕНТ GSAU И ИНТЕРФЕЙСОВ МЕЖДУ НИМИ . 8
2.2.1. Описание взаимодействия GSAU- сервера и GSAU- клиента 10
2.2.2. Типы основных потоков данных между GSAU-сервером и
GSAU- клиентом . . . . . . . . . . . . . . . . . . . 10
2.2.3. Глобальные обьекты проекта . . . . . . . . . . . . . 15
2.2.4. Cхема взаимодействия между GSAU-сервером и GSAU
клиентом . . . . . . . . . . . . . . . . . . . . . . 16
2.2.5. Описание БД и операторов языка манипулирования
данными DML . . . . . . . . . . . . . . . . . . . . 20
2.2.6. Функции высокоуровневого интерфейса . . . . . . . . 20
2.2.6.1. Определение таблиц базы данных GSAU . . . . . . . 21
2.2.6.2. Определение функций интерфейса с базой данных GSAU 21
2.2.6.2.1. Использование оператора SELECT . . . . . . . . . 22
2.2.6.2.2. Использование оператора DELETE . . . . . . . . . 23
2.2.6.2.3. Использование оператора INSERT . . . . . . . . . 25
2.2.6.2.4. Использование оператора UPDATE . . . . . . . . . 25
2.2.6.2.5. Использование оператора UPDATE #2 . . . . . . . 32
2.2.6.3. Описание таблицы типа TPump. . . . . . . . . . . . 33
2.2.6.4. Описание таблицы типа TPosition. . . . . . . . . . 37
2.2.6.5. Описание нового типа данных Relation. . . . . . . 39
2.2.7. Описание работы менеджера драйверов . . . . . . . . 43
2.2.8. Описание работы драйверов контроллеров . . . . . . . 43
2.2.9. Описание работы имитатора контроллера . . . . . . . 43
2.2.10. Описание работы оператора . . . . . . . . . . . . . 43
3. РУКОВОДСТВО ПРОГРАММИСТА . . . . . . . . . . . . . . . . 44
3.1. СХЕМА РЕЛЯЦИОННЫХ СВЯЗЕЙ GSAU . . . . . . . . . . . . 44
3.2. ВНУТРЕННЯЯ СХЕМА БАЗЫ ДАННЫХ GSAU . . . . . . . . . . 44
3.2.1. Based datatypes . . . . . . . . . . . . . . . . . . 45
3.2.1.1. Meassure . . . . . . . . . . . . . . . . . . . . . 45
3.2.1.2. Pump . . . . . . . . . . . . . . . . . . . . . . . 45
3.2.1.3. Position . . . . . . . . . . . . . . . . . . . . . 46
3.3. MAKEFILEs . . . . . . . . . . . . . . . . . . . . . . 47
3.3.1. Зависимости от других проектов . . . . . . . . . . . 48
3.4. ОПИСАНИЕ СТРУКТУР ОБМЕНА ГЕНЕРИРУЕМОГО ИНТЕРФЕЙСА . . 48
3.5. ОПИСАНИЕ ВЫСОКОУРОВНЕГО ИНТЕРФЕЙСА С БД . . . . . . . 49
3.5.1. Хедер макросов и констант . . . . . . . . . . . . . 49
3.5.1.1. Command/State Indicator . . . . . . . . . . . . . 50
3.5.1.2. Command/State . . . . . . . . . . . . . . . . . . 50
3.5.2. Хедер основных обьектов системы . . . . . . . . . . 51
3
UA.'agp1@smtp.ru'.GSAU-0.90/0.12 13 02
3.6. ФУНКЦИИ КОНСТРУИРОВАНИЯ/ДЕКОНСТРУИРОВАНИЯ COMMAND/STATE 55
4. ИСПОЛЬЗОВАНИЕ И ПРОВЕРКА РАБОТОСПОСОБНОСТИ . . . . . . . 56
4.1. ВЫПОЛНЕНИЕ ТЕСТИРУЮЩЕЙ ПРОГРАММЫ . . . . . . . . . . . 56
4.1.1. the put/get command/state/indicator . . . . . . . . 56
4.2. ИСПОЛЬЗОВАНИЕ ФУНКЦИЙ ВЫСОКОУРОВНЕВОГО ИНТЕРФЕЙСА С БД 57
5. НЕКОТОРЫЕ ВЫВОДЫ . . . . . . . . . . . . . . . . . . . . 62
ПЕРЕЧЕНЬ ТЕРМИНОВ И СОКРАЩЕНИЙ . . . . . . . . . . . . . . . 65
INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
ПЕРЕЧЕНЬ ССЫЛОЧНЫХ ДОКУМЕНТОВ . . . . . . . . . . . . . . . 70
в аттаче повербилдер, отображение числа в слово
|