diplomamunka - lpds.sztaki.hu · nyújtó infrastruktúra konfigurációjának rugalmas, naprakész...
TRANSCRIPT
DIPLOMAMUNKA
KONFIGURÁCIÓ-MENEDZSMENT
VERZIÓKÖVETETT OBJEKTUMOKKAL
Budapesti Műszaki és Gazdaságtudományi Egyetem
Irányítástechnika és Informatika Tanszék
Készítette:
Fülöp Balázs
EIWMWH
Konzulens:
Dr. Szeberényi Imre
Budapest, 2009
DIPLOMATERV FELADAT
Fülöp Balázs
szigorló műszaki informatikus hallgató részére
Konfiguráció-menedzsment verziókövetett objektumokkal
Összetett, gyakran változó rendszerek konfiguráció-menedzsmentje nem egyszerű feladat. Kis- és nagyvállalatokon belül egyaránt fontos az informatikai szolgáltatásokat nyújtó infrastruktúra konfigurációjának rugalmas, naprakész nyilvántartása, egyszerű módosítása. A diplomaterv feladat során a cél egy rugalmas konfiguráció-menedzsment környezet fő elemeinek objektum orientált megvalósítása, amely verziókövetett módon nyújtja az objektum orientált rendszerek előnyeit.
Feladatok:1. Elemezze a konfiguráció-menedzsmenttel kapcsolatos fő feladatokat egy
feltételezett cég belső informatikai infrastruktúra szolgáltatásának szempontjából.
2. Tervezzen meg egy olyan keretrendszert, mely alapját képezheti a konfiguráció-menedzsment feladatok verziókövetett megoldásának
3. Válasszon az implementáláshoz megfelelő, lehetőleg gyors fejlesztéshez jól használható nyelvet és implementálja a megtervezett keretrendszert.
4. Demonstrálja az elkészített rendszer működését, és készítse a fejlesztői dokumentációját.
A feladat beadási határideje: 2009. május 15.
Tanszéki konzulens: Dr. Szeberényi Imre
Záróvizsga tárgyak: Rendszerintegráció (BMEVIFO4367)Operációs rendszerek (BMEVIM3231)Adatbázisok (BMEVIIA3232)
Budapest, 2009. február 20.
Dr. Szirmay-Kalos Lászlóegyetemi tanárTANSZÉKVEZETŐ
Budapesti M szaki és Gazdaságtudományiű Egyetem
Villamosmérnöki és Informatikai KarIrányítástechnika és Informatika Tanszék
1117 Budapest, Magyar tudósok körútja 2. I. ép. 317.Postacím: 1521 Budapest, Pf.: 91.Tel: 463-2699, Fax: 463-2204, http://www.iit.bme.hu
Konfiguráció-menedzsment verziókövetett objektumokkal 6
Nyilatkozat
Alulírott Fülöp Balázs, a Budapesti Műszaki és Gazdaságtudományi Egyetem hallgatója
kijelentem, hogy jelen diplomatervet meg nem engedett segítség nélkül, saját magam
készítettem, és a diplomatervben csak a megadott forrásokat használtam fel. Minden olyan részt,
amelyet szó szerint, vagy azonos értelemben, de átfogalmazva más forrásból átvettem,
egyértelműen, a forrás megadásával megjelöltem.
Budapest, 2009. május 14.
......................................
Fülöp Balázs
Konfiguráció-menedzsment verziókövetett objektumokkal 8
Tartalomjegyzék
I. Előszó............................................................................................................................................9
II. Abstract......................................................................................................................................10
III. Konfiguráció-menedzsment.....................................................................................................111. A konfiguráció-menedzsment célja.......................................................................................112. IBM Tivoli platform..............................................................................................................133. BMC......................................................................................................................................144. Modellezési kihívások...........................................................................................................155. XML alapú modellezés.........................................................................................................166. LDAP alapú modellezés........................................................................................................187. Objektum-relációs leképezés................................................................................................208. Gyenge sémájú relációs modellezés.....................................................................................219. CM modellezési eljárások összehasonlítása.........................................................................23
IV. Adatmodell gyenge sémájú modellezéshez.............................................................................241. Az adatmodell követelményei...............................................................................................242. Entitás-relációk tervezése.....................................................................................................253. Relációs séma tervezése........................................................................................................284. ActLog tábla..........................................................................................................................305. ObjTree tábla.........................................................................................................................306. ObjRev tábla..........................................................................................................................317. ObjType tábla........................................................................................................................328. ObjAttr tábla..........................................................................................................................329. AttrKey tábla.........................................................................................................................3310. AttrVal tábla.........................................................................................................................34
V. A Perl nyelv................................................................................................................................351. A nyelv eredete......................................................................................................................352. A Perl adattípusai...................................................................................................................363. A Perl és az OOP...................................................................................................................374. Beépített típusok egyedi implementációja............................................................................40
VI. A Calf keretrendszer.................................................................................................................451. A keretrendszer célja.............................................................................................................452. A keretrendszer áttekintése....................................................................................................463. Calf csomag...........................................................................................................................484. Calf::Tie csomagok...............................................................................................................485. Calf::Object csomagok..........................................................................................................496. Calf::DB csomagok...............................................................................................................507. Calf::Data csomag.................................................................................................................518. A keretrendszer használatának bemutatása...........................................................................51
Konfiguráció-menedzsment verziókövetett objektumokkal 9
I. Előszó
Jelen dokumentum a 2008/09. tanév tavaszi félévében, a Budapesti Műszaki és
Gazdaságtudományi Egyetem műszaki informatikus szakán írt diplomamunkámat tartalmazza.
Önállóan választott témám a Perl 5 programozási környezet objektum-perzisztencia
képességeinek feltérképezése és továbbfejlesztése, valamint ezek egyedi konfiguráció-
menedzsment rendszerekben való alkalmazhatóságának vizsgálata.
A téma és a kitűzött feladatok hálás kihívást jelentettek abból a szempontból, hogy egy olyan –
jellemzően nagyvállalati környezetben felmerülő – igény problémáit érintik, melyekre magától
értetődően jó gyakorlat, tipikus és szélesebb körben elismert megoldás egyelőre nem létezik.
Ezért a munka nagy része izgalmas kísérletezésből és kreatív fejlesztésből állt.
Másrészről a témaválasztás kevéssé mondható szerencsésnek, mert nem egyértelmű meghúzni
azt a határvonalat, ahol a szűkös időkeret szorításában a kutatás-fejlesztés szakasza le kell, hogy
záruljon. Mivel a diplomamunka gerincét adó dolgozatnak egy ponton össze kell foglalnia az
eredményeket, a szerteágazó problémakör egyes elemei természetszerűleg több hangsúlyt
kaptak, mint mások.
Végeredményben jelen diplomamunka egyik fő eredménye egy Perl5-höz készült, széles körű
felhasználásra alkalmas, verziókövető képességekkel bíró perzisztencia-réteg.
E sokrétű feladat meghatározó elemeinek kiemelésében rendkívüli segítséget nyújtott
számomra Dr. Szeberényi Imre, akinek támogatásáért ezúton szeretnék köszönetet mondani.
Szeretném továbbá megköszönni mindazoknak az együttműködését, akik elolvasták a
dolgozatomat, és kritikáikkal, építő megjegyzéseikkel segítették a munkámat: Fülöp Edinának,
Hámor Tamásnak, Kornai Tamásnak, Köllő Tamásnak és Székely Gergőnek.
Budapest, 2009. május 14.
......................................
Fülöp Balázs
Konfiguráció-menedzsment verziókövetett objektumokkal 10
II. Abstract
This document contains my final thesis for the Faculty of IT Engineering at the Budapest
University of Technology and Economics, written in the spring semester of 2008/09. The main
topic of the thesis that has been chosen independently is the examination and enhancement of
the object persistence capacities of the Perl5 programming environment. The question of the
strengths and weaknesses of deploying a custom configuration management system built on top
of that has been addressed as well.
The topic and the actual tasks imposed a number of exciting challenges concerning enterprise-
level problems, for which apparent best practices, or widely deployed universal solutions are not
available. Because of that a great amount of efforts has been spent on experimental
development.
Defining the actual point where the phase of research and development needs to be closed due
to time limitation was a challenge by itself. Since the documentation part of the thesis needs to
summarize the results of the work in the end of the day, certain elements of the diversified
problem scope have gotten a greater emphasis than others.
One of the main accomplishments of the thesis is a fully featured persistence layer for Perl5
with versioning capabilities, intended for general use.
I would like to thank Imre Szeberényi, Dr. for his tiredless efforts to help in finding the key
points to focus on. I would also like to say thank you to all of those who have read an earlier
revision of my thesis and provided feedback: Edina Fülöp, Tamás Hámor, Tamás Kornai, Tamás
Köllő and Gergő Székely.
Budapest, 14th May 2009
......................................
Fülöp Balázs
Konfiguráció-menedzsment verziókövetett objektumokkal 11
III. Konfiguráció-menedzsment
Mottó: Nehéz úgy érvényes általánosításokatkijelenteni, hogy mondunk is valamit. Ez nincs
másként az előző mondat esetében sem.
1. A konfiguráció-menedzsment célja
Általános értelemben a konfiguráció-menedzsment (a továbbiakban: CM) az informatikában
inkább egy koncepció, mint egy valódi szabvány. Pontosabban fogalmazva, a kiadott
szabványok nagy, és a referencia implementációk kis száma miatt igen nehéz egy olyan
definíciót adni rá, amely minden szervezet CM rendszerére illeszkedne. A Wikipedia
Configuration management[1] szócikke az alábbi szabványok listáját tartalmazza:
• ANSI/EIA-649-1998 National Consensus Standard for Configuration Management
• EIA-649-A 2004 National Consensus Standard for Configuration Management
• ISO 10007:2003 Quality management systems - Guidelines for configuration management
• Federal Standard 1037C
• GEIA Standard 836-2002 Configuration Management Data Exchange and Interoperability
• IEEE Std. 828-1998 IEEE Standard for Software Configuration Management Plans
• MIL-STD-973 Configuration Management (2000. szeptember 20-án visszavonták)
• STANAG 4159 NATO Material Configuration Management Policy and Procedures for
Multinational Joint Projects
• STANAG 4427 Introduction of Allied Configuration Management Publications (ACMPs)
Közös vonásuk, hogy egy informatikai rendszer komponenseinek konfigurációit állapotként
kezelik és elsődleges célként a rendszer konzisztens állapotból konzisztens állapotba történő
váltását tűzik ki az elérhető legkevesebb tranzienssel. Ez a meghatározó tulajdonság viszont
még nem tekinthető definíciónak.
Példaként tekintsük egy UNIX rendszer klasszikus felhasználói adatbázisát. Ez a legtöbb
UNIX implementációban két fájlban testesül meg: a /etc/passwd tartalmazza a felhasználói
fiókokat némi metainformációval, a /etc/shadow pedig a jelszavak hashelt változatát. Mindkét
állomány sima szöveges és soronként egy rekordot tartalmaz. Csak fokozott
elővigyázatossággal lehet őket szerkeszteni, mivel egyetlen hibás sor is megjósolhatatlan
Konfiguráció-menedzsment verziókövetett objektumokkal 12
működést eredményezhet, továbbá a két fájl egy-egy sora együttesen ír le egy felhasználói
fiókot, ezért módosítások esetén a konzisztencia fenntartása nem triviális.
Emiatt minden modern UNIX tartalmaz olyan segédprogramokat, melyekkel a felhasználói
adatbázis közvetlen szerkesztés nélkül módosítható. Ilyen a szinte mindenhol elérhető useradd
család. Ezek a parancssoros programok garantálják, hogy az adatbázis felhasználók által
érzékelhető tranziensek nélkül módosítható. Ha a CM rendszerek fenti tulajdonságát
tekintenénk definíciónak, akkor ez alapján a useradd család egy CM megoldás lenne. A
gyakorlatban mégsem tekintik annak, mert nem skálázható egy számítógépnél többre, és
hiányzik belőle sok olyan fejlett szolgáltatás, ami egy menedzsment megoldás igazi erejét adja.
Az esetek többségében egy CM rendszernek része egy általános modellező környezet. Ez egy
absztrakciós szintet ad a rendszer elképzelt modellje és a valódi konfiguráció között, ami
lehetővé teszi az adminisztrátor számára, hogy modell szinten meghatározott összefüggések
alapján dolgozzon. Így a tényleges konfigurációt ez a köztes réteg szolgáltatja, nem pedig
valamilyen manuális beállítás. A modellezés jellemzően valamilyen speciális deklaratív
nyelvvel történik.
Visszatérve a UNIX felhasználói adatbázisának problémájára: egy felhasználó létrehozása a
useradd segítségévél még megoldható magas szinten, viszont egy e-mail alias felvétele
hagyományosan már csak kézzel, a /etc/aliases fájl szerkesztésével valósítható meg. Ha
ezek után egy felhasználói fiókhoz tartozó bejelentkezési név megváltozik, azt két helyen kell
módosítani: egyrészt a usermod használatával az adatbázisban, másrészt az előbb említett
állományban. A CM például az ilyen jellegű helyzetekben nyújt informatikai támogatást, az
emberi hibák és a tranziens jelenségek kiküszöbölésének érdekében.
Egy CM rendszertől általában elvárhatóak még az alábbiak:
• változáskövetés
A rendszer lehetőséget biztosít legalább a változások lekérdezésére, azaz az entitások
élettörténetének megtekintésére. Fejlettebb rendszerek megvalósítják a rollbacket is,
vagyis adott egy korábbi, helyesnek ítélt konfigurációra történő visszaállás lehetősége.
• öndokumentáló modell
A konfigurációk absztrakt modellje felhasználóbarát leírását adja az elérhető
állapotoknak.
Konfiguráció-menedzsment verziókövetett objektumokkal 13
• biztonság
A rendszerben tárolt konfigurációhoz a hozzáférés finoman szabályozott. Ez tipikusan
Access Control List (ACL) segítségévél történik.
• validálás
A rendszer garantálja, hogy a modellbe csak érvényes konfiguráció vihető fel.
• verifikáció
A rendszer ellenőrzi, hogy a valódi konfiguráció a modellnek megfelelő-e.
• automatizmus
A rendszer kevés ponton igényel felhasználói beavatkozást és legfeljebb annyira
időigényes a használata, mintha minden beállítás kézzel történne.
• csoportmunka
A rendszer támogatja a csoportos adminisztrációt és felkészítették a konkurrens
módosítások kezelésére.
A lista közel sem teljes – egyes CM rendszerek többet, mások kevesebbet valósítanak meg a
fentiekből. A legnagyobb nehézséget ilyen rendszerek vizsgálatakor mégis az jelenti, hogy a
szempontok helyenként távolról sem objektívek. Egyetemes megoldás erre a problémakörre
egyelőre nem létezik, és az elérhető rendszerek versenyeztetése csak élő, gyakorlati példához
viszonyítva lehet releváns. Bár ez jelen dolgozat tárgyán túlmutat, lássuk milyen
szolgáltatásokat ígér két nagyobb kereskedelmi CM rendszer.
2. IBM Tivoli platform
Az IBM Tivoli megoldása egy olyan integrációs platform, amely hardver- és szoftver-
konfigurációk, folyamatok és emberi tevékenységek menedzsmentjéhez nyújt nagyvállalati
szintű infrastruktúrát. A termék komponenseinek megcélzott előnyei között szerepel az
egységesített és átlátható adatmodell, illetve az erre építő automatizmusok – beleértve a
validálást és a verifikációt – kialakításának támogatása.
A Tivoli platform egyik sarokkövét képező Change and Configuration Management Database
(CCMDB) az alábbi szolgáltatásokat biztosítja[2]:
• Elosztott konfigurációs adatbázis
Az alapértelmezésben szállított, DB2 technológiára építő adatbázisháttér mellett
lehetőség van egyedi konfigurációs adatbázis használatára.
Konfiguráció-menedzsment verziókövetett objektumokkal 14
• Kiterjeszthető adatmodell
A CCMDB képességei kiterjeszthetőek egyedi CI (configuration item), illetve attribútum
elemekkel.
• Programozható felület
Egy jól definiált API-n keresztül lekérdezhető és menedzselhető a konfiguráció. Erre
építve egyedi igényeket kielégítő tooling is létrehozható.
• Intelligens jelentések
A megoldás teljes mértékben testre szabható és áttekinthető jelentéskészítési funkciókkal
bír.
• Konfigurálható munkafolyamatok
Mélyebb szintű fejlesztési ismeretek nélkül is, fogd-és-vidd jellegű felületeken gyorsan
leírhatóak vállalati munkafolyamatok.
• Audit napló
A konfigurációk korábbi változatai összehasonlíthatóak, a CI élettörténetek
megtekinthetőek.
• Integrációs pontok külső megoldásokhoz
A rendszer mind az adat, mind a funkcionális szinten könnyedén integrálható külső
szállító termékeihez.
3. BMC
A BMC Configuration Manager integrált nagyvállalati megoldás az ismétlődő rendszergazdai
feladatok automatizálására. Különleges szolgáltatásai az alábbiak[3]:
• Házirend-alapú menedzsment
Az aktuális és a modellezett konfiguráció közötti eltérések folyamatos ellenőrzésével a
verifikációs folyamatok önműködőek.
• Önműködő operációs rendszer migráció
Automatikus, best-practice alapú frissítés és migrációs folyamatok jellemzik a rendszert.
• Szoftver-használati jelentések
A vállalatban alkalmazott szoftverekről jelentések készülnek a licenszek megfelelő
kihasználásának felmérése érdekében.
Konfiguráció-menedzsment verziókövetett objektumokkal 15
• Patch-menedzsment megoldások
A rendszer megoldást nyújt a hibajavításokat, frissítéseket tartalmazó patchek
automatikus csomagolásához.
• Egységesített adminisztráció
A termékfüggetlen, egységesített felületű telepítési és adminisztrációs segédprogramok
elfedik a különböző külső szállítók termékeinek specialitásait.
4. Modellezési kihívások
A fentiek alapján érezhető, hogy az adatmodell a CM esetén kulcsfontosságú. Egy túlzottan
specifikus modell behatárolja a CM alkalmazhatóságának körét, ugyanakkor elengedhetetlen,
hogy megkötéseket tartalmazzon, ellenkező esetben a validáció egyáltalán nem, vagy csak
nagyon körülményesen oldható meg. Bizonyos modellezési eljárások természetükből adódóan
nyújtanak megoldást az előzőekben ismertetett szempontokra, míg másokkal egyes pontok
eleve megoldhatatlanok.
A kályhától indulva vizsgáljunk meg négyet egy CM rendszer adatmodelljének lehetséges
backendjei közül:
• XML alapú: a modell entitásai XML dokumentum formátumban kerülnek tárolásra.
• LDAP: a modell entitásai LDAP objektumok.
• RDBMS objektum-relációs leképezéssel: a modell entitásai egy OOP környezet objektumai,
melyeket leképezzük egy rögzített relációs adatbázis sémába.
• Gyenge sémájú RDBMS: A modell entitásai egy OOP környezet objektumai, melyek a
relációs adatbázis sémájának módosítása nélkül szabadon mutálhatók.
A következőkben az alábbi kérdésekre keresünk választ a vázolt backend megoldások
összehasonlítási alapjának meghatározása érdekében:
• Milyen formátumban kerülnek tárolásra az entitások?
Hogyan azonosítja a backend az entitást? Hogyan tárolja az attribútumokat? Mennyire
hatékony az adatszervezési eljárás? Van-e lehetőség ezen a szinten típusellenőrzésre,
illetve ellenőrzött referenciák létrehozására?
• Milyen kommunikációs protokollon érhetőek el az adatok?
A használt protokoll sima szöveges vagy bináris, illetve mennyire mondható ipari
szabványnak? Eleve adott-e a titkosítás lehetősége, vagy ez csak egyedileg oldható meg?
Konfiguráció-menedzsment verziókövetett objektumokkal 16
A konfiguráció alkalmazási oldalról közvetlenül felhasználható, vagy generálni kell?
• Mennyire könnyű a séma kiterjesztése?
Mit szükséges megváltoztatni annak érdekében, hogy egy entitás új attribútummal
bővüljön? Megoldható-e ez a szolgáltatás megállítása nélkül?
• A backend az API-n túl milyen felületeken érhető el?
Az adminisztrátornak milyen lehetőségei vannak az adatok közvetlen elérésére? Ezek a
módszerek mennyire biztonságosak az adatintegritás szempontjából?
• Hogyan oldható meg a verziókövetés?
Mennyire körülményes a változások folyamatos követése? Korábbi verzióra vissza lehet-
e állni szolgáltatás-leállítás nélkül?
• Hogyan valósítható meg az adatvédelem?
Van-e beépített megoldás az adatokhoz való hozzáférés szabályozására? Ha nincs,
mennyire körülményes megvalósítani, és milyen fokú biztonság érhető el vele?
• Milyen a csoportmunka támogatás?
Van-e lehetőség az entitások párhuzamos szerkesztésére? Mi történik konkurrens
hozzáférés esetén? A megjósolható működéshez milyen zárolásokat használ a rendszer?
Van-e tranzakciókezelés?
5. XML alapú modellezés
Az első, talán legkézenfekvőbb megoldás az XML[4] (Extensible Markup Language) alapú
modellezés. Tekintve, hogy a végcél tetszőleges konfigurációk előállítása, az XML egy
természetes általánosítása a problémának. Ugyanakkor, mivel az XML önmagában pusztán egy
fájlformátum, a hálózati elérés, a verziókövetés, és egy sor további fejlett szolgáltatás csak egy
megfelelő kiszolgáló mellett lehetséges. A továbbiakban feltesszük, hogy ez adott, lévén, hogy
egy “XML szerver” egy közönséges fájlkiszolgálóval megvalósítható.
Az entitások tárolása ebben az esetben egy vagy több XML dokumentum formájában történik.
Ha minden entitás külön dokumentum, az entitások azonosíthatóak egyszerűen a dokumentum
mint erőforrás egyértelmű meghatározásával. Ellenkező esetben az entitást a tartalmazó
dokumentum megjelölése mellett az azon belüli helye azonosítja, melyhez használható az XPath
szabvány. Az attribútumok tárolása az XML strukturált felépítése miatt nem bonyolult, továbbá
CDATA blokkok segítségévél és megfelelően megválasztott kódolás mellett elvileg tetszőleges
értéket vehetnek fel.
Konfiguráció-menedzsment verziókövetett objektumokkal 17
Az adatszervezés hatékonysága megkérdőjelezhető. Legrosszabb esetben minden betöltött
entitás külön fájlból származik, ami nagy bonyolultságú rendszereknél komoly teljesítménybeli
problémákhoz vezethet. A megoldás ilyen értelemben vett ára elsősorban a használt
fájlrendszertől, a fájlszerver gyorsaságától, az egyidejűleg használt objektumok számától és a
párhuzamos elérés esetén fellépő zárolások számától függ.
Típusellenőrzés ebben az esetben backend szinten akkor van, ha az XML dokumentumhoz
tartozik előre definiált DTD (Document Type Definition). Ez az XML feldolgozást, ha lehet,
még inkább lassítja. További probléma, hogy a DTD módosítása élő rendszerben előre nehezen
látható következményekkel jár, ugyanis az ellenőrzés csak a dokumentum betöltésekor történik
meg. Így elvileg elképzelhető, hogy a séma módosítása meglévő adatok érvénytelenítésével jár,
és ami még rosszabb, ez csak az adatok későbbi felhasználásakor derül ki.
Az XML szabvány lehetőséget nyújt referenciák elhelyezésére a dokumentumon belül, viszont
ezeknek a feloldása az XML parser felelőssége, és a lehetőség valójában C-szerű
terminológiával élve, inkább a makrókra hasonlít. Dokumentumokon átívelő referenciák
használatára nincs lehetőség, így általánosságban erre a kérdésre csak alkalmazásszintű válasz
adható.
A kommunikációs protokoll a használt fájlszervertől függ. Szolgáltatásokban gazdag megoldás
érhető el egy alkalmasan megválasztott WebDAV kiszolgálóval. A DAV (Distributed Authoring
and Versioning) az ipari szabványnak tekinthető, sima szöveges HTTP protokoll kiterjesztett
utasításkészletű változata, amely gond nélkül használható SSL-lel titkosított csatornán is. A
konfigurálandó alkalmazások sajnos a legritkább esetben támogatják a beállítások WebDAV
szerverről történő letöltését. Ez igaz a többi klasszikus fájlmegosztó szolgáltatásra is, ezért az
XML alapú modellezés általános esetben megköveteli a konfiguráció generálását és offline
használatát.
Az XML létrehozásakor tervezési döntés volt a sima szöveges formátum, így a
dokumentumok akár tetszőleges szövegszerkesztővel vagy specifikus segédprogrammal
megtekinthetők és szerkeszthetők. Azonban a dokumentumok felépítése elsősorban a CM
rendszer igényeit szolgálja, és ebből adódóan a CM rendszer mélyebb ismerete nélkül az XML
dokumentumok közvetlen szerkesztése nem csak nehézkes, de adatintegritási szempontból
veszélyes művelet is lehet.
A verziókövetés lehetősége és az ehhez kapcsolódó szolgáltatások szintén szerverfüggők. A
fájlszerver használhat verziókövető fájlrendszert, ennek szolgáltatásai viszont alkalmazási
Konfiguráció-menedzsment verziókövetett objektumokkal 18
oldalról csak nehezen és az esetek többségében komoly biztonsági problémákat felvetve
vehetők igénybe. Például a jelenleg elérhető implementációkkal WebDAV használata mellett
sem lehet a protokoll verziókövető funkcióit kihasználni. Az, hogy a szerver mögött egy
verziókövető motor gondoskodik a változások követéséről, pusztán a szerveren adminisztratív
privilégiumokkal rendelkező felhasználók életét segíti, a korábbi verziók megtekintése és
visszaállítása csak számukra elérhető.
Az adatok védelme fájlrendszerszintű jogosultságkezeléssel, nagy biztonsággal
megvalósítható. Szervertől függően szóba jöhet a klasszikus UNIX-os hármas
jogosultságrendszer vagy a POSIX ACL-ek is.
A csoportmunka támogatás a választott fájlszerver lehetőségeiből következik. Ha a szerver
támogatja a fájlzárolást, a konkurrens hozzáférés megvalósítható, viszont több állomány
kezelése mellett ez könnyen dead-lock-hoz vezethet. Ami leginkább megkérdőjelezi a
többfelhasználós üzemmódot, az a tranzakciók teljes hiánya, pontosabban, hogy azok kezelése
az alkalmazás felelősségi körébe tartozik.
6. LDAP alapú modellezés
Az LDAP[5] (Lightweight Directory Access Protocol) a címtárszolgáltást biztosító
protokollok legnépszerűbb szabványa. Sokkal többet nyújt a hagyományos telefonkönyvszerű
szolgáltatásoknál, melyet mi sem bizonyít jobban, mint hogy a Microsoft Windows Serverek
Active Directory[6] nevű megoldása LDAP alapú. Az említetten kívül minden nagyobb
informatikai szállító rendelkezik saját LDAP implementációval, a Sun Microsystems-től az
Oracle-ig.
Az LDAP adatbázis fastruktúrában tárolt objektumok halmaza. Fontos hangsúlyozni, hogy a
legtöbb LDAP implementáció nem alkalmazásszerver, és az objektumokhoz egyéni műveletek
adatbázisszinten nem társíthatóak. Az objektumok egy előre rögzített sémának megfelelő
attribútumokat tartalmazó entitások. Azonosítójuk az ún. DN (distinguished name), amely a fa
gyökeréből kiindulva az objektumhoz vezető egyértelmű elérési út.
Az LDAP szervereket tipikusan keresésre és olvasásra optimalizálják, egyéb műveletekre
jellemzően rosszabbul teljesítenek, mint a relációs adatbázisok. Ez konfiguráció tárolása esetén
nem feltétlenül jelent gondot, mivel a problémakör természeténél fogva a műveletek döntő
többsége olvasás. A legtöbb LDAP szerver legalább read-only replikák felállításának
lehetőségével erősíti a skálázhatóságot.
Konfiguráció-menedzsment verziókövetett objektumokkal 19
A típusellenőrzés előre rögzített sémával adatbázisszinten megoldható. A sémában értelmezett
az öröklődés, aminek köszönhetően átláthatóan leírható egy objektum attribútumainak halmaza.
Az attribútumok lehetnek többértékűek, és tárolhatnak bináris értéket is. Az LDAP fa egyes
elemei hivatkozhatnak más objektumokra. Nem minden LDAP szerver támogatja a séma
dinamikus frissítését.
Az LDAP egy széles körben támogatott bináris protokoll, melynek létezik SSL-el védett
változata (LDAPS). Nagyszámú programnyelvhez elérhető megbízható, kliensoldali API, ezért
a legtöbb nyílt forrású szerveralkalmazás támogatja a konfiguráció LDAP szerverről történő,
dinamikus lekérdezését. Jó példa erre az Apache webszerver, a Postfix SMTP szerver vagy a
Bind9 DNS kiszolgáló.
Számos jól használható LDAP kliens létezik, amik közül vannak, melyek webes felületet is
adnak egy LDAP adatbázis közvetlen eléréséhez. Ezekkel az adatbázis kényelmesen és
adatintegritási szempontból biztonságosan szerkeszthető.
Verziókövetésre egyetlen nagyobb LDAP szerver sem nyújt támogatást. A változások
lekérdezése és visszaállítása integrált módon nem megvalósítható. Mivel az LDAP szabványban
definált LDIF (LDAP Interchange Format) sima szöveges dumpját képezi az adatbázisnak, az
erről készült rendszeres pillanatképekkel követhetőek a verziók, ez viszont csak a probléma
megkerülése; a változások rögzítése így nem folyamatos, a szerver adminisztrátorának kézi
beavatkozása szükséges, és a visszaállítás szolgáltatáskimaradással jár.
Az LDAP szerverek jellemzően egy nagyon fejlett biztonsági modellt valósítanak meg. Akár
attribútumszinten is korlátozható a hozzáférés az objektumokhoz. Többek közt ezért is népszerű
az LDAP a központi felhasználó-menedzsment megoldásokban, ahol a felhasználói fiókok
LDAP objektumokként tárolódnak, és azok bizonyos attribútumai akár a felhasználó által is
szerkeszthetők (pl. a jelszó), mások pedig akár rejtettek is lehetnek megfelelő privilégiumok
nélkül.
A többfelhasználós üzemmód korlátokkal támogatott. Az LDAP nem tartalmaz
tranzakciókezelő utasításokat, így az adatbázison végzett műveletek egyik implementációban
sem izolálhatóak. Ez komoly gondot jelenthet a konkurens hozzáférések kezelésében, ha
ugyanazon logikai művelet több objektum módosításával jár.
Konfiguráció-menedzsment verziókövetett objektumokkal 20
7. Objektum-relációs leképezés
Ennek a modellezési eljárásnak a lényege, hogy a CM rendszer objektumait még tervezési
fázisban leképezzük egy relációs adatbázisháttérre. A leképezés lehet dinamikus olyan
értelemben, hogy az objektumok egyfajta leírásából automatikusan generálódik mind a relációs
séma, mind az azt használó programkódnak egy része, végeredményben viszont a séma az
adatbázisban rögzített lesz és nem frissíthető a kód módosítása nélkül.
Az objektumok azonosításának módszere a leképezést végző szoftver megvalósításától függ. A
legtöbb esetben az azonosítót természetes módon az objektum osztályát jelképező tábla
elsődleges kulcsa adja. Az attribútumok tipikusan az ezen kulccsal jelölt rekord további mezői.
Többértékű attribútumok implementációja külső táblában történő tárolással lehetséges. A
típusok ez esetben szigorú SQL típusok, melyek adatbázisszinten ellenőrzöttek. A referenciák
idegen kulcsként jelentkeznek az adatmodellben, melyek integritásáról szintén az
adatbáziskezelő gondoskodik.
A relációs adatbáziskezelők az előző két megoldással szemben mind az olvasásra, mind az
írásra jól optimalizáltak, ezért egy gondosan megtervezett objektummodellt feltételezve az
optimálist megközelítő teljesítmény érhető el. A legtöbb SQL szerver továbbá beépített
megoldást nyújt clusterek kialakítására, és így a skálázhatóság csak milliós nagyságrendű
objektumszám mellett jelent sématervezési kihívást.
A relációs adatbáziskezelők egytől-egyig saját, jellemzően bináris protokollon érhetőek el,
amely SSL-lel tehető biztonságossá. Bár ezek mind különbözőek, alkalmazási oldalról minden
programozási nyelv alatt elérhető valamilyen szabványos adatelérési könyvtár – C/C++ alatt az
ODBC, Java alatt a JDBC, Perl alatt a DBI – aminek köszönhetően a különböző
adatbáziskezelők azonos API-n keresztül használhatóak. Ezért sok nyílt forráskódú
szerveralkalmazás (az LDAP mellett) relációs adatbáziskezelőből történő dinamikus
konfigurálást is támogat.
A séma kiterjesztése, mint az a korábbiakban említésre került, nem lehetséges a kód és az
adatbázis együttes módosítása nélkül. Ahhoz, hogy ez éles rendszeren leállítás nélkül
végbemenjen, gondosan tervezett migrálás szükséges. Egy új attribútum felvétele tehát nem
kivitelezhetetlen, de nem is tekinthető mindennapi rutinfeladatnak.
Az adatbázis közvetlen szerkesztésére a legtöbb RDBMS egy SQL konzolt nyújt. Ezzel mind a
séma, mind az adatok szabadon lekérdezhetőek és szerkeszthetőek. A CM rendszer alapos
Konfiguráció-menedzsment verziókövetett objektumokkal 21
ismerete szükséges ahhoz, hogy ez ne vezessen adatintegritási problémákhoz.
A verziókövetésre az adatbázisszerverek nem nyújtanak támogatást, mivel ez nem képezi
egyik SQL szabvány részét sem. Így a változatok követése vagy része az objektummodellnek,
és ebből adódóan az alkalmazás felelőssége a verziókezelés, vagy az LDAP-ról elmondottak
érvényesek ez esetben is. Azaz, az adatbázisról készülhet egy sima szöveges SQL nyelvű dump,
amelynek manuális verziókövetését végezheti az adminisztrátor.
Az adatvédelem a legtöbb SQL szerverben tábla szintű jogosultságkezeléssel valósítható meg.
Ez meglehetősen szegényes biztonsági házirendhez vezetne, ezért komolyabb alkalmazások
egyszerűen megtiltják az adatbázis közvetlen elérését, és egyedileg gondoskodnak a hozzáférés-
szabályozásról. Nem ritka az sem, hogy egy alkalmazás a felhasználók azonosításához és
hitelesítéséhez egy másik külső adatforrást (pl. egy LDAP szervert) vesz igénybe.
A csoportmunka támogatás SQL szerverek esetén a legkiemelkedőbb. ACID jellegű
tranzakciók és ebből következően írásra és olvasásra egyaránt valódi többfelhasználós
üzemmód a jellemző. A zárolások megvalósítása szerverenként különböző, de bizonyos
esetekben elérhető a sor szintű locking is.
8. Gyenge sémájú relációs modellezés
Jelen dolgozat gyenge sémájúként hivatkozik arra a relációs adatbázisra, amely a lehetséges
entitásokat és azok attribútumainak halmazát nem írja elő, valamint az attribútumok típusait
séma szinten nem kényszeríti ki. A megoldás bizonyos értelemben magasabb szabadságfokkal
bír az objektum-relációs leképezéshez képest, aminek a nem titkolt árát teljesítményben fizeti
meg.
Ez a megközelítés röviden összefoglalva egy olyan sémát használ, amely az adatmodell
metamodelljét rögzíti. Leegyszerűsítve az entitás és az attribútumok közötti 1-n kapcsolat
reprezentálása egy-egy táblával történik. Így az objektum azonosítója az első tábla elsődleges
kulcsa, az attribútumok táblája pedig ezt, mint idegen kulcsot használja. Ebből adódóan típusok
csak különböző attribútumtáblákkal, vagy ugyanazon táblában tárolt redundáns mezőkkel
valósíthatók meg. A referenciák ettől függetlenül idegen kulcsok segítségével lehetnek
ellenőrzöttek.
A módszer nagy előnye a rugalmas modell, amely éles üzem mellett szabadon módosítható,
ami gyengén típusos, dinamikus programozási környezetkben jól kihasználható. Látható viszont
Konfiguráció-menedzsment verziókövetett objektumokkal 22
az is, hogy egy objektum lekérdezése legalább 1 JOIN művelet nélkül nem lehetséges, ami
teljesítménykorlátokat hordoz magában. Ezen meghatározó különbségtől eltekintve az előző
alfejezetben említettek itt is érvényesek.
Konfiguráció-menedzsment verziókövetett objektumokkal 23
9. CM modellezési eljárások összehasonlítása
XML LDAP RDBMS (ORM) RDBMS (gyenge séma)
Entitások tárolása fájlrendszerben adatbázisban adatbázisban adatbázisban
Attribútum típusok + + + -
Referenciák - + + +
Hálózati protokoll egyedi, pl. WebDAV LDAP egyedi egyedi
SSL támogatás + (ha támogatott) + + +
Séma módosítás adatintegritásra veszélyes újraindítást igényel újrafordítást igényel szabadon (nincs séma)
Dinamikus konfiguráció - + + +
Generált konfiguráció + + + +
Olvasási sebesség - ++ ++ +
Írási sebesség - + ++ ++
Közvetlen elérés fájlok szerkesztése LDAP kliens SQL konzol SQL konzol
Verziókövetés - - + (ha implementált) + (ha implementált)
Jogosultságkezelés fájlrendszer szintű attribútum szintű tábla szintű -
Tranzakciókezelés - - + +
Zárak fájl szintű (ha támogatott) - rekord szintű rekord szintű
Konfiguráció-menedzsment verziókövetett objektumokkal 24
IV. Adatmodell gyenge sémájú modellezéshez
Mottó: Különböző filozófiájú technológiák házasításaegyszerre egyesítheti azok minden jó és rossz tulajdonságát.
1. Az adatmodell követelményei
Jelen dolgozat egyik célja egy egyedi CM rendszerben felhasználható adatmodell
megtervezése[7]. Az előző fejezetben említett módszerek közül a választás a gyenge sémájú
modellezésre esett, melyre megszorításokkal ugyan, de kijelenthető, hogy egy gondosan
implementált keretrendszer mellett a gyengén típusos környezetek rugalmasságát ötvözi a
relációs adatbáziskezelők teljesítményével.
A gyenge sémájú modellezésből származó előnyöket értelemszerűen csak egy gyengén
típusos, dinamikus programozási környezetben lehet kamatoztatni. Ezen programozási
környezetek közül sok vagy eleve objektum-orientált szemléletű (pl. Python, Ruby), vagy
legalábbis kényelmesen alkalmazhatóak bennük az OOP paradigmák (pl. Perl). Egy CM
megoldás entitásai természetes módon képezhetők le egy objektum rendszerre, tekintve a valós
élet objektumaival vett kapcsolatukat: egy felhasználói fiók egy objektum, amelyen értelmes
művelet a bejelentkezési név megváltoztatása.
További példák az OOP és a CM kapcsolatára:
• adatrejtés
UNIX alatt a /etc/passwd fájl rekordjai sorokba rendezettek, és a sorokon belül a
mezőhatároló karakter a ':'. Ha ezzel a részletkérdéssel a felhasználói kvótákról jelentést
készítő programkód nem kell, hogy foglalkozzon, az nem csak átláthatóbb, de jobban
újrafelhasználható megoldást eredményez.
• öröklődés
Egy webszerver és egy e-mail szerver is egy hálózati kiszolgáló – mindkettőn értelmes
művelet az indításuk előtt az általuk használt port foglaltságának ellenőrzése.
• polimorfizmus
Egy webszervert és egy e-mail szervert jelképező objektum start metódusa azonos
programozói felületet kíván, viszont a műveletek megvalósítása természetesen
különbözhet.
Konfiguráció-menedzsment verziókövetett objektumokkal 25
A tervezendő adatmodelltől azt várjuk, hogy jól illeszkedjen egy gyengén típusos objektum-
orientált környezethez. Támogatnia kell az objektum és a műveleteit implementáló osztály
összerendelését, a referenciákat, és valamilyen objektum-hierarchiát. Ezeken kívül a következő
igényeket támasztjuk a fejlettebb szolgáltatások kialakításához:
• objektumfa
Az objektumok fastruktúrában tárolódjanak és ugyanazon objektum a fa több
csúcspontjához legyen linkelhető.
• verziókövetés
Az objektumok és attribútumaik legyenek verziókövetés alatt. Legyen lehetőség egy
objektum korábbi állapotának megtekintésére – ez adatmodell szinten csak az
adattagokra garantálható, a metódusok implementációiban keletkezett változtatásokra
nem érvényes.
• auditálás
Legyen nyomon követhető az adatbázison végzett műveletek listája, időbélyeggel ellátott
műveleti napló segítségével.
2. Entitás-relációk tervezése
Mint az a korábbiakban említésre került, a gyenge sémájú modellezés alapötlete a metamodell
implementálása a végleges adatmodell helyett. Ez a következő leegyszerűsített kapcsolatot
feltételezi:
Az attribútumok mindig kulcs-érték párok, függetlenül attól, hogy az érték adott esetben egy
egyszerű szám, vagy további objektumok kollekciója. A kulcsokat és az értékeket önálló
entitásként ábrázolva a következő modellhez jutunk:
Objektum Attribútumtartalmaz
Konfiguráció-menedzsment verziókövetett objektumokkal 26
Ez az elképzelés egyszerűsége mellett számos pozitív lehetőséget hordoz magában. A
verziókövetés megvalósítása az entitás-relációk érintése nélkül implementálható, ha az
Objektum entitásra, mint az objektum egy verziójára tekintünk. Ehhez mindössze arra van
szükség, hogy a nevezett entitás azonosítóját az objektum azonosítója és a verziószám összetett
kulcsként adja. A modellben akár a kulcsok neveinek, akár az értékeknek a változatlansága
természetszerűleg leírható, amivel a redundancia elfogadható szintre csökkenthető.
A fenti Objektum entitást a valódi objektum egy változataként kezelve felmerül a kérdés, hogy
ha egy attribútum értéke egy másik objektum referenciája, akkor a hivatkozás tartalmazza-e a
verziószámot. Azaz, amikor egy objektum tartalmazza egy másik referenciáját, azzal egy
konkrét, rögzített verzióra hivatkozik vagy annak a legfrissebb állapotára.
Az első megközelítésből kiindulva a modell nem veszít általánosságából, és leírhatóak vele
olyan különleges esetek is, amikor egy attribútumérték egy időközben frissült objektum régebbi
verziójával dolgozik. Ez egy további problémát vet fel. A műveletek nem az adatbázisban
tárolódnak, és mivel így nem állnak verziókövetés alatt, a metódusokat megvalósító
osztályoknak visszafele kompatibilisnek kellene lenniük minden olyan objektumverzióra,
amelyre létezik referencia.
A második megközelítés, azon túl, hogy lemond a régebbi objektumok hivatkozásának
lehetőségéről, egy kényelmesebben kezelhető adatszerkezetet nyújt. Ha egy objektum frissül,
nem szükséges az összes rá hivatkozó objektumot frissíteni annak érdekében, hogy az új
változat elérhetővé váljon. Ez a viselkedés programozói szemmel sokkal inkább nevezhető
elvártnak az előzőhöz képest.
Objektum
Kulcs
attribútum
Érték
Konfiguráció-menedzsment verziókövetett objektumokkal 27
Az objektumok fába rendezése egy hasonló, de talán még nehezebben megválaszolható
tervezői döntés kérdését veti fel. A fa lehet önmagában verziókövetett, azaz működhet egy
modern verziókövető rendszer könyvtárstruktúra-kezelésének mintájára. A másik lehetőség,
hogy a fa nem követi a változásokat, csak objektumreferenciákat tartalmaz, ami további két
opcióként ismét vonatkozhat az objektum verziójára vagy magára az objektumra.
A fa verziókövetése akkor valósítható meg, ha létezik egy globális verziószám a teljes
fastruktúrára, és ezt a verziószámot használják az abban szereplő objektumok. Ez azzal járna,
hogy a rendszerben lévő bármely objektum bármely attribútumán történő változtatás az
objektumrendszer egészének egy új verzióját eredményezné, amit ezen a ponton önkényes
választás alapján elkerülünk. A fa tehát nem verziókövetett, és az attribútumértékeknél kifejtett
indokok miatt a benne tárolt referenciák objektumokat címeznek és nem verziókat.
Mindezt összefoglalva az alábbi ER-diagram adja az objektummodellt:
Objektumverzió
Kulcs
attribútum
Érték
Objektumgyermeke
tartalmaz
Konfiguráció-menedzsment verziókövetett objektumokkal 28
3. Relációs séma tervezése
Mielőtt a bemutatott entitás-relációk alapján relációs adatbázisban felhasználható séma
készülhetne, a modell még egy kis kiegészítésre szorul. Egyrészt nem esett szó még az audit log
megvalósításáról. Erre egy külön tábla fog szolgálni, a modelltől valamilyen szinten
függetlenül, kizárólag naplózási célra.
Másrészt a modell objektumai – bár gyengén típusos környezetben fognak CM célokat
szolgálni – minden esetben tartalmaznak legalább olyan szintű típusinformációt, hogy a
műveletek megvalósításai milyen osztályban vagy csomagban keresendők, illetve mi az a
befoglaló adatszerkezet, amelyen keresztül a kulcs-érték párok elérhetőek. Ez nyelvspecifikus
kérdés, az adott programozási környezet határozza meg ezeknek a tulajdonságoknak a
lehetséges értékeit.
Itt ismét önkényesen a modellt úgy alakítjuk, hogy az típusosság szempontjából a Perl
programozási nyelvnek kedvezzen. A későbbiekben még szó esik a Perl és az OOP
kapcsolatáról, egyelőre fogadjuk el, hogy a tervezett rendszer objektumai egy csomagnévvel
azonosított osztályból veszik a metódusaikat, és az adataikat egy tetszőleges méretű skalár,
tömb vagy asszociatív tömb írja le.
A relációs séma tábláit és azok jelentésék a következő alfejezetek tárgyalják. Mivel a fejlesztés
MySQL[8] adatbáziskezelővel történt, a táblák DDL leírásai ezen RDBMS SQL dialektusát
tükrözik. A mellékelt diagramon vastag betűvel szedettek azok a mezők, amelyek nem vehetnek
fel NULL értéket. Az elsődleges kulcsokat a kulcs szimbólum jelzi, összetett kulcsok esetén
értelemszerűen több mezőt jelölve. A nyilak az idegen kulcsokat jelentik, egy táblából akkor
mutat nyíl egy másikra, ha az első idegen kulcsként használja a második tábla valamely
mezőjét.
Konfiguráció-menedzsment verziókövetett objektumokkal 29
Konfiguráció-menedzsment verziókövetett objektumokkal 30
4. ActLog tábla
Az ActLog (Action Log) tábla az audit logot hivatott megvalósítani. Minden rekordja egy
adott időpillanatban egy objektumon végrehajtott műveletet naplóz. Kényszerként nem
tartalmaz idegen kulcsokat annak érdekében, hogy az objektumok a naplóbejegyzések
érvénytelenítése nélkül törölhetőek legyenek.
• act_ts
TIMESTAMP típusú mező a művelet időbélyegének leírásása.
• obj_id
INT típusú mező a művelet tárgyát jelentő objektum azonosításához. Az act_ts mezővel
együtt elsődleges kulcsa a táblának.
• role
VARCHAR típusú mező a műveletet végző szerepkör azonosítására. Ez tartalmazhatja
például annak a felhasználónak a belépési nevét, aki az adatbázison dolgozó szkriptet
futtatja.
• action
VARCHAR típusú mező a művelet leírásása.
• comment
TEXT típusú mező a szabadszöveges megjegyzések tárolásához.
CREATE TABLE `ActLog` ( `act_ts` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `obj_id` int(11) NOT NULL, `role` varchar(128) NOT NULL, `action` varchar(128) NOT NULL, `comment` text, PRIMARY KEY (`act_ts`,`obj_id`), KEY `ActLog_role` (`role`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
5. ObjTree tábla
Az ObjTree (Object Tree) tábla az objektumfát valósítja meg. Minden rekordja a fa egy
csúcspontja. Az objektumok névvel azonosítottak, és a fában teljes elérési útjuk alapján
találhatóak meg.
Konfiguráció-menedzsment verziókövetett objektumokkal 31
• name
VARCHAR típusú mező, az objektum nevét tartalmazza.
• parent
INT típusú mező, az objektum szülőjének azonosítóját tartalmazza. Idegen kulcs
ugyanezen tábla obj_id mezőjére. A name mezővel együtt elsődleges kulcsa a táblának.
• obj_id
INT típusú mező az objektum azonosítójának tárolására.
CREATE TABLE `ObjTree` ( `name` varchar(128) NOT NULL default '', `parent` int(11) NOT NULL default '1', `obj_id` int(11) NOT NULL auto_increment, PRIMARY KEY (`name`,`parent`), KEY `Object_ID` (`obj_id`), KEY `Parent object must exist` (`parent`), CONSTRAINT `Parent object must exist` FOREIGN KEY (`parent`) REFERENCES `ObjTree` (`obj_id`) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8;
6. ObjRev tábla
Az ObjRev (Object Revision) tábla az objektumok verzióit tárolja. Minden rekordja egy adott
objektum verzióját jelképezi.
• obj_id
INT típusú mező az objektum azonosítójának tárolására. Idegen kulcs az ObjTree tábla
azonos nevű mezőjére.
• obj_rev
INT típusú mező, az objektum verziószámát tartalmazza. Az obj_id mezővel együtt a
tábla elsődleges kulcsa.
• type_id
INT típusú mező, az objektum típusát leíró ObjType rekord idegen kulcsa.
CREATE TABLE `ObjRev` ( `obj_id` int(11) NOT NULL, `obj_rev` int(11) NOT NULL default '0', `type_id` int(11) NOT NULL, PRIMARY KEY (`obj_id`,`obj_rev`), UNIQUE KEY `obj_id` (`obj_id`,`obj_rev`), KEY `Object_type` (`type_id`), CONSTRAINT `Object must exist` FOREIGN KEY (`obj_id`) REFERENCES `ObjTree` (`obj_id`) ON DELETE CASCADE,
Konfiguráció-menedzsment verziókövetett objektumokkal 32
CONSTRAINT `Type must exist` FOREIGN KEY (`type_id`) REFERENCES `ObjType` (`type_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
7. ObjType tábla
Az ObjType (Object Type) tábla az objektumok típusának leírására szolgál. Minden rekordja
egy típusdefiníció.
• type_id
INT típusú mező, a típus egyértelmű azonosítója, a tábla elsődleges kulcsa.
• class
INT típusú mező, az objektum osztályát tartalmazó csomag jelölésére szolgál. A csomag
nevét a rendszer egy másik objektumának value nevű attribútuma adja, ezért ez a mező
az ObjTree tábla obj_id mezőjére hivatkozó idegen kulcs. Ha ez a mező NULL, akkor az
objektum a tie mezőben tárolt információ alapján egy alapértelmezett osztály példánya
lesz.
• tie
ENUM típusú mező, amely azt az adattípust jelöli, amelyen keresztül később az objektum
attribútumai elérhetőek lesznek. Ha ez SCALAR, az objektum value nevű attribútuma adja
a skalár értékét, ha pedig ARRAY vagy HASH, akkor az attribútum kulcs-érték párjai a
megfelelő tömbszerkezet kulcsához tartozó értékek lesznek.
CREATE TABLE `ObjType` ( `type_id` int(11) NOT NULL auto_increment, `class` int(11) default NULL, `tie` enum('SCALAR','ARRAY','HASH') NOT NULL default 'HASH', PRIMARY KEY (`type_id`), KEY `Object_class` (`class`), CONSTRAINT `Object class must exist` FOREIGN KEY (`class`) REFERENCES `ObjTree` (`obj_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
8. ObjAttr tábla
Az ObjAttr (Object Attribute) tábla az objektumok attribútumainak kapcsolótáblája. Minden
rekordja egy attribútumot jelképez.
• obj_id
INT típusú mező az objektum azonosítójának tárolására.
Konfiguráció-menedzsment verziókövetett objektumokkal 33
• obj_rev
INT típusú mező az objektum verziószámának tárolására. Az obj_id mezővel együtt
idegen kulcs az ObjRev tábla azonos nevű mezőire.
• attrkey_id
INT típusú mező az attribútum kulcsának jelölésére. Idegen kulcs az AttrKey tábla
azonos nevű mezőjére, továbbá az obj_id és obj_rev mezőkkel együtt képezi a tábla
elsődleges kulcsát.
• attrval_id
INT típusú mező az attribútum értékenek jelölésére. Idegen kulcs az AttrVal tábla
azonos nevű mezőjére. Ha a mező NULL, az azt jelenti, hogy az objektum attribútumát
törölték.
CREATE TABLE `ObjRev` ( `obj_id` int(11) NOT NULL, `obj_rev` int(11) NOT NULL default '0', `type_id` int(11) NOT NULL, PRIMARY KEY (`obj_id`,`obj_rev`), UNIQUE KEY `obj_id` (`obj_id`,`obj_rev`), KEY `Object_type` (`type_id`), CONSTRAINT `Object must exist` FOREIGN KEY (`obj_id`) REFERENCES `ObjTree` (`obj_id`) ON DELETE CASCADE, CONSTRAINT `Type must exist` FOREIGN KEY (`type_id`) REFERENCES `ObjType` (`type_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
9. AttrKey tábla
Az AttrKey (Attribute Key) tábla az attribútumok kulcsát tartalmazza. Minden rekordja egy
névvel ellátott kulcs.
• attrkey_id
INT típusú mező az attribútumkulcs egyértelmű azonosítására, a tábla elsődleges kulcsa.
• attr_key
VARCHAR típusú mező, az attribútum nevét tartalmazza.
CREATE TABLE `AttrKey` ( `attrkey_id` int(11) NOT NULL auto_increment, `attr_key` varchar(128) NOT NULL, PRIMARY KEY (`attrkey_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Konfiguráció-menedzsment verziókövetett objektumokkal 34
10. AttrVal tábla
Az AttrVal (Attribute Value) tábla az attribútumok értékét tartalmazza. Minden rekordja egy
gyenge típusú érték.
• attrval_id
INT típusú mező az attribútum értékének egyértelmű azonosítására, a tábla elsődleges
kulcsa.
• attr_type
ENUM típusú mező az attribútum gyenge típusának meghatározására. Ennek jelentését a
későbbiekben tárgyaljuk, a lehetséges értékek: string, delegate és object. Értéke
befolyásolja, hogy a további mezők közül melyik szolgáltatja az attribútum értékét.
• attr_ref
INT típusú mező objektum-referencia tárolására. Idegen kulcs az ObjTree tábla obj_id
nevű mezőjére. Ha az attr_type értéke delegate vagy object, ez a referencia számít
az attribútum értékének meghatározásakor.
• attr_val
BLOB típusú mező egyszerű értékek tárolására. Ha az attr_type értéke string, ez a
referencia számít az attribútum értékének meghatározásakor.
Az adatbázisban nem tárolt integritási feltétel, hogy az attr_ref és az attr_val mezők közül
legfeljebb az egyik vehet fel nem NULL értéket, és a nem NULL értékű mezőt az attr_type jelzi.
CREATE TABLE `AttrVal` ( `attrval_id` int(11) NOT NULL auto_increment, `attr_type` enum('string','delegate','object') NOT NULL default 'string', `attr_ref` int(11) default NULL, `attr_val` blob, PRIMARY KEY (`attrval_id`), KEY `AttrVal_ref` (`attr_ref`), CONSTRAINT `Reference must exist` FOREIGN KEY (`attr_ref`) REFERENCES `ObjTree` (`obj_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Konfiguráció-menedzsment verziókövetett objektumokkal 35
V. A Perl nyelv
Mottó: A könnyű dolgok legyenek egyszerűek,a nehezebb dolgok pedig megvalósíthatóak.
– Larry Wall
1. A nyelv eredete
A Perl[9] egy általános célú, C-szerű szintaktikával bíró dinamikus, interpretált programozási
nyelv, melyet 1987-ben hozott létre az akkor a NASA-nál rendszeradminisztrátorként dolgozó
Larry Wall. Eredetileg a ksh-sed-awk klasszikus UNIX-os hármas kiváltására született,
elsősorban a mindennapi adminisztrátori feladatok, ezek közül is a riportkészítés egyszerűbbé
tétele érdekében. Azóta a nyelv számos verziót megélt, melyek közül a legfontosabb mérföldkő
az 1994-ben bemutatott Perl 5. Ebben a változatban jelentek meg azok a fejlett nyelvi elemek,
melyek nélkül a Perl a gyakorlatban nehezen volna használható kisebb szkriptelési feladatokon
kívül bármire is; így a referenciák, az objektumok, vagy a modulok kezelése mind a Perl 5
sajátja.
Ma a Perl egyike a legsikeresebb dinamikus nyelveknek. Elsősorban UNIX adminisztrátorok
körében népszerű, de a bioinformatikától a webprogramozásig számos helyen alkalmazzák.
Elterjedtségét többek között korlátlan rugalmasságának és a rapid alkalmazásfejlesztés
támogatásának köszönheti, továbbá annak a ténynek, hogy a Perl modulok hivatalos
gyűjtőhelye, a CPAN[10] az írás pillanatában több, mint 65.000 modult tartalmaz, melyek a
jelenlegi stabil 5.10-es változathoz ingyenesen elérhetőek.
A Perl megalkotója, Larry Wall eredeti foglalkozása szerint nyelvész, és talán nem véletlen,
hogy a programnyelv filozófiáját tekintve sok közös vonást mutat a természetes nyelvekkel. Pl.
nem szükségszerű a nyelvet teljes egészében ismerni ahhoz, hogy valaki elkezdjen vele
foglalkozni – ugyanúgy, ahogy bizonyos helyzetekben egy angolul társalgási szinten tudó is
elboldogul, és nem szükséges felsőfokú nyelvvizsga ahhoz, hogy valaki egy étteremben
rendeljen egy steaket.
Ez a tulajdonság tette egyszerre híressé és hírhedté a nyelvet. Viszonylag könnyű beletanulni,
viszont már a legalapvetőbb programozási feladatokat is rendkívül sokféle módon lehet benne
megvalósítani. Ez egy nagyobb projekt esetén megnehezítheti egy programozó csapat feladatát
akkor, ha a csapat tagjai különböző szinten “beszélik” a Perlt, és nincsenek szigorú kódolási
Konfiguráció-menedzsment verziókövetett objektumokkal 36
konvenciók. A nyelv maga ugyanis nem kényszerít rá semmilyen – olykor nagyon hasznos –
szabályosságra. Azaz, a szabálykövetés egyéni ízlés kérdése.
Mindez csak ízelítő ahhoz, hogy egyesek miért svájci bicskaként, míg mások láncfűrészként
gondolnak a Perlre. Nekem személyesen egyik nem titkolt célom jelen dolgozattal az, hogy
példát mutassak átlátható, robusztus és újrafelhasználható Perl kód írására.
2. A Perl adattípusai
A Perl beépített típusai az alábbiak[11]:
• SCALAR
• ARRAY
• HASH
• CODE
• REF
• GLOB
• LVALUE
• FORMAT
• IO
• VSTRING
• Regexp
Ezen primitívek közül a mindennapi gyakorlatban az átlagos programozó az első három típust
alkalmazza, a többit pedig vagy egyáltalán nem használja, vagy csak az interpreter dolgozik
velük a háttérben. Például a VSTRING használata az 5.8.1-es változat óta ellenjavallt, Regexp
pedig implicit módon jön létre a reguláris kifejezést váró operátoroknál.
A SCALAR típus az egyszerű skalár – fedi az elterjedt, erősen típusos nyelvek közel összes
primitív típusát, így az egész és a lebegőpontos számokat, a karaktert és a sztringet. Egy skalár
felveheti az undef értéket (nem definiált) – ez inicializálatlan változók esetén a kezdőérték.
Külön boolean típus nincs Perlben. Minden érték, amely nem 0, nem üres sztring és nem undef,
igaz, a többi hamis. Egy skalár továbbá értékként felvehet egy referenciát.
Az ARRAY egészekkel indexelt, sorrendezett, dinamikus tömb, amelynek értékei skalárok.
Értelmezettek rá a következő veremműveletek: push, pop, shift, unshift.
Konfiguráció-menedzsment verziókövetett objektumokkal 37
A HASH sztringekkel indexelt, nem sorrendezett, dinamikus tömb, amelynek értékei skalárok.
Az iterátor tervezési mintának megfelelően bejárható.
A Perl megköveteli, hogy a változók neveikben prefixumként jelöljék a típusukat (megj.: erre
a fogalomra az angol szakirodalom a sigil[12] elnevezést használja). A skalár típust a $, a
tömböt a @, a hash tömböt pedig a % jelöli. Minden változóhoz képezhető referencia a \ operátor
segítségével. A referencia tárolható skalár változóban, és dereferálható a hivatkozott változó
típusának megfelelő sigil használatával. Ez az alábbi táblázatban foglalható össze.
Referenciaképzés Dereferálás
SCALAR $ref = \$var $$ref
ARRAY $ref = \@var @$ref
HASH $ref = \%var %$ref
3. A Perl és az OOP
A referenciát tartalmazó skalár változókra értelmes művelet a megáldás[13] (angolul:
blessing). Ez az operáció egy névteret definiáló Perl csomagot rendel a változóhoz. Az így
létrejövő referencia egy hagyományos Perl objektum. Osztálya az a csomag, amelynek nevével
a referencia áldott, adatait pedig a hivatkozott adatstruktúra tárolja. Egy Perl objektum újra
megáldható, ebben az értelemben az objektumok típusai dinamikusan módosíthatóak.
A metódushívás a nyíl operátorral (->) történik. Akkor, ha ennek bal oldalán egy csomagnév
áll, a jobb oldalon álló szubrutint az értelmező az adott névtérben keresi, és meghívásakor átadja
a csomag nevét nulladik paraméterként. Ez a működés tükrözi a tisztán objektum-orientált
környezetek statikus tagfüggvény-hívásait. Ha a nyíl operátor bal oldalán egy megáldott
referencia áll, a jobb oldalon álló szubrutint az értelmező abban a névtérben keresi, amellyel a
referencia áldott, és meghívásakor átadja a referenciát nulladik paraméterként. Ez leginkább a
C++-os metódushíváshoz hasonlítható, ha a nulladik paraméterre úgy tekintünk, mint a this
pointerre.
A Perl támogatja a többszörös öröklődést. Ez egy csomag szinten globális változó formájában
valósul meg, melynek neve @ISA. Az ISA tömb elemei csomagnevek. Ha a nyíl operátorral egy
olyan metódust próbálunk meghívni, amely a bal oldalon álló szimbólumból kikövetkeztetett
Konfiguráció-menedzsment verziókövetett objektumokkal 38
csomagban nem található, az interpreter az @ISA elemeit egyenként végigpróbálva próbálja meg
feloldani a hivatkozást.
Az eddig ismertetett szabályok összefoglalásaként lássunk egy példát Perl OOP kódra. A
példaprogram egy absztrakt állat osztályt, egy tehén osztályt és egy azt felhasználó csomagot
mutat be.
#!/usr/bin/perl -w
package Animal;use strict;use Carp;
sub speak($){ my $name = ( caller 0 )[3]; croak "Subroutine $name is abstract and cannot be invoked directly.\n";}
sub DESTROY{ warn __PACKAGE__ . " object destroyed.\n";}
package Cow;use strict;use base 'Animal';
sub new($$){ my ( $class, $name ) = @_; my %self = ( name => $name ); return bless \%self, $class;}
sub speak($){ my $self = shift; print "$$self{name} says moooo.\n";}
package main;use strict;use Data::Dumper;
my $cow = new Cow( 'Dazy' );warn Data::Dumper->Dump( [ $cow ], [ 'cow' ] );eval { $cow->speak };warn "\$cow->speak failed: $@\n" if ( $@ );
Konfiguráció-menedzsment verziókövetett objektumokkal 39
A szkript kimenete a következő (a dőlt betűvel szedett kimenet a STDERR, a többi a STDOUT
csatornán jelenik meg):
$cow = bless( { 'name' => 'Dazy' }, 'Cow' );Dazy says moooo.Animal object destroyed.
A fenti kódból látható még a Perl OOP támogatásának néhány további fontos tulajdonsága.
Az objektumok legtöbbször hash referenciák, mivel ez az adatstruktúra közelít leginkább a
szigorú objektum-orientált környezetek tagváltozóihoz. Egy hash referencia által mutatott
adattagok az osztályon kívülről egyszerűen lekérdezhetőek és módosíthatóak. A hagyományos
Perl objektumok tehát nem rejtik el az adattagjaikat.
Absztrakt metódusok létrehozására szigorú értelemben nincs lehetőség. Pontosabban
fogalmazva, az interpreter egy osztály interfészét fordítási időben nem ellenőrzi, ezért csak
futásidejű hibák generálásával lehet emulálni a klasszikus absztrakt metódusokat.
Az @ISA módosítható a base pragmatikus modul használatával. Ez gyakorlatilag szintaktikai
édesítőszer, és itt is tetten érhető az a tulajdonság, hogy az öröklődés megvalósításához az
ősosztály neve sztringként tárolódik, vagyis fordítási idejű hibaellenőrzés nincs.
A megáldás szintén sztringgel történik, a Cow::new szubrutinban definiált $class változó
értéke a 'Cow' karakterlánc lesz. A bless művelettel még futásidőben sem ellenőrzi az
interpreter azt, hogy az operációhoz felhasznált csomagnév érvényes-e. Ebből adódik, hogy
objektumok konstruktorai elhelyezhetők az osztályokon kívülre is, és még be nem töltött
csomagnevekkel is végezhető blessing.
Perlben van szemétgyűjtő mechanizmus (garbage collector). Ez az objektum által foglalt
memóriaterület felszabadítása előtt meghívja az objektum DESTROY metódusát, ha az létezik. A
DESTROY, ahogy bármely másik metódus, örökölhető és garantáltan lefut.
A metódushívás a nyíl operátor explicit kiírása mellett történhet úgy is, hogy a csomagnév,
vagy objektum elé írjuk a metódus nevét. A main csomagban a new Cow kifejezés ismét
szintaktikai édesítőszer, és pontosan ugyanazt jelenti, mint a Cow->new. A new tehát nem
kulcsszó, és az, hogy a konstruktor szerepét betöltő metódust így hívják, csupán programozói
konvenció.
Konfiguráció-menedzsment verziókövetett objektumokkal 40
A kivételkezelésre beépített nyelvi megoldás nincs. Mégis meg lehet valósítani úgy, hogy azt a
kifejezést, amely hibát válthat ki, egy eval blokkba helyezzük. Ha a blokkon belül die, vagy
ahhoz hasonló, abortálást eredményező művelet történik, akkor a szkript nem lép ki és utána a
$@ változó értékének ellenőrzésével elkapható a kivétel. A kivételek ebből adódóan nem
típusosak.
Ezek a tulajdonságok első ránézésre veszélyesnek tűnhetnek, sőt, azt is megkockáztatom, hogy
egyfajta módosult tudatállapot szükséges a Perl objektummodelljének szeretetéhez. Azt azonban
nem szabad figyelmen kívül hagyni, hogy a programnyelv szabadságából adódó lehetséges
hibák vagy az első futás során kiderülnek (pl. elírt csomagnév az öröklődésnél), vagy ha nem,
akkor a programozó szándékos, rendszerszemléletet nélkülöző munkájának az eredményei (pl.
privátnak szánt adattagok módosítása az osztályon kívülről). A Perl egyik legnagyobb hibája és
egyúttal igazi ereje az, hogy nem korlátozó.
4. Beépített típusok egyedi implementációja
A blessing mellett egy másik izgalmas lehetőség Perlben a kötés[14] (tie). Ezzel a programozó
a következő primitív típusokhoz adhat egyéni implementációt:
• SCALAR
• ARRAY
• HASH
• IO
A kötéshez szükség van egy, az adattípusra értelmes műveletek megvalósításait tartalmazó
osztályra. A tie operáció során egy deklarált változóhoz egy megadott osztály példányát
rendeljük, és onnantól kezdve a változón végzett beépített műveletekre az objektum metódusai
hívódnak meg. Ez hasonló a C++ operátor-túlterheléséhez, azzal a különbséggel, hogy beépített
típusokra működik és nem a programozó által létrehozott osztályokra.
Példaként lássunk egy olyan szkriptet, amely egy hash kötést implementál az első tíz
négyzetszám meghatározásához.
#!/usr/bin/perl -w
package Pow;use strict;use Carp;
Konfiguráció-menedzsment verziókövetett objektumokkal 41
sub TIEHASH{ my $class = shift; my ( $power ) = @_; my %self = ( pow => defined $power ? $power : 1, first => 1, last => 10 ); return bless \%self, $class;}
sub FETCH{ my $self = shift; my ( $key ) = @_; $$self{cache}{$key} = $key ** $$self{pow} unless ( exists $$self{cache}{$key} ); return $$self{cache}{$key};}
sub immutable { croak "This hash is immutable" }sub STORE { shift->immutable }sub DELETE { shift->immutable }sub CLEAR { shift->immutable }
sub EXISTS { return 1 }
sub FIRSTKEY{ shift->{first}}
sub NEXTKEY{ my ( $self, $lastkey ) = @_; if ( $lastkey == $$self{last} ) { undef } else { ++ $lastkey }}
sub SCALAR{ my $self = shift; return "$$self{first} .. $$self{last}";}
package main;use strict;
tie my %square, 'Pow', 2;print scalar( %square ), ":\n";
Konfiguráció-menedzsment verziókövetett objektumokkal 42
while ( my ( $key, $val ) = each %square ) { print "$key ^ 2 = $val\n";}$square{1} = 2;
A szkript kimenete a következő (a dőlt betűvel szedett sor a STDERR, a többi a STDOUT
csatornán jelenik meg):
1 .. 10:1 ^ 2 = 12 ^ 2 = 43 ^ 2 = 94 ^ 2 = 165 ^ 2 = 256 ^ 2 = 367 ^ 2 = 498 ^ 2 = 649 ^ 2 = 8110 ^ 2 = 100This hash is immutable at ./square.pl line 59
Ez az implementáció azt sugallja, hogy a számok négyzeteit egy szótárszerű adatszerkezetben
tároljuk, ahol a kulcs a hatványalap, az érték pedig a hatványérték. Ez egy természetes
szintaktikát ad a programozó kezébe úgy, hogy a mögöttes bonyolult számítás megvalósítását
nem kell ismernie. A tie művelet után a $square{alap} kifejezéssel tetszőleges négyzetszám
megkapható.
A szintaktika szépségén túl ez a megoldás egy további nagy előnnyel bír. Mivel a
hatványraemelés művelete számításigényes, a %square hasht felhasználó programozó joggal
várhatja el, hogy az értékek meghatározása a mögöttes implementációt adó objektumban csak
egyszer történjen meg, függetlenül attól, hogy az értéket a szkript hányszor használja. Ez a
caching mechanizmus a Pow::FETCH szubrutinban néhány sorban implementált, és teljesen
transzparens módon, az erre építő kódból észrevétlenül működik.
A példaprogram tartalmaz még Perl különlegességeket:
• Ha egy szubrutinban nincs explicit return, akkor a visszatérési érték az utoljára kiértékelt
kifejezés értéke. Erre jó példa a Pow::FIRSTKEY és a Pow::NEXTKEY.
• Egy hashreferencia által mutatott adatstruktúra adott kulcsához tartozó érték nem csak a
$$ref{key}, de a $ref->{key} alakú, C-szerű szintaktikával is elérhető. Erre példa a
Pow::FIRSTKEY.
• Blokkok utolsó utasításai esetén elhagyható a pontosvessző – lásd Pow::EXISTS.
Konfiguráció-menedzsment verziókövetett objektumokkal 43
• Függvények visszatérési értéke lehet lista, így az each iterátor két skalárral; egy kulccsal és
egy értékkel tér vissza.
Ezeken kívül összetett hash természetes módon képezhető és a további dimenziók struktúráit
nem szükséges deklarálni, mert az autovivifikációnak nevezett mechanizmus gondoskodik az
életre keltésükről. A Pow::FETCH úgy használja a $$self{cache} hashreferenciát, hogy
feltételezi annak önműködő létrehozását.
Végül érdemes megjegyezni, hogy a Pow osztály egy olyan hashre ad egyedi implementációt,
amely értelemszerűen nem módosítható, ezért néhány metódus esetén futásidejű hibát ad. A
kimenet utolsó sorában látható hibaüzenet annak köszönhető, hogy a main csomag végső
utasításában megkísérli felüldefiniálni az 1 négyzetét, – sajnálatos módon rosszul – amit a Pow
osztálypéldány megakadályoz a matematika szabályainak érvényben tartása érdekében.
Konfiguráció-menedzsment verziókövetett objektumokkal 45
VI. A Calf keretrendszer
Mottó: Egy keretrendszer nagysága a kiterjeszthetőségbenrejlik és nem a korlátoltságban.
1. A keretrendszer célja
Jelen diplomamunka fő eredménye egy olyan Perlben implementált keretrendszer, amely
segítségével verziókövetett objektum-perzisztencia valósítható meg, a korábban bemutatott
gyenge sémájú adatmodellt felhasználva. Erre a keretrendszerre építve kialakítható egy egyedi
CM rendszer a következő szempontok azonnali teljesülésével:
• relációs adatbázisháttér
• verziókövetés
• könnyű szkriptelhetőség
• objektum-orientált szemlélet
A Calf alapgondolata egy olyan objektumrendszer, amelyben az objektumok mindig olyan
adatstruktúrára mutató referenciák, amelyek belső implementációja a keretrendszer által adott.
Perl nyelvi szinten ez azt jelenti, hogy előre elkészített osztályokhoz kötött változók
referenciáinak megáldása szolgáltatja az objektumokat.
Ennek köszönhetően a keretrendszer objektumai szabadon kiterjeszthetőek és azok minden
metódusa felüldefiniálható anélkül, hogy a belső adatok integritási szabályai megkerülhetőek
lennének. Az ábrán látható folytonos vonalon belül lévő adatok az azokra hivatkozó objektum
elől is rejtettek. A kötéshez felhasználásra kerülő osztályok ezeket az adatokat a verziókövetés
megkönnyítéséhez Copy-On-Write módon kezelik. A módszer angol nevének rövidítése a COW,
melyből sejthető a keretrendszer névválasztásának oka.
Tied variable
Reference
Object
Konfiguráció-menedzsment verziókövetett objektumokkal 46
2. A keretrendszer áttekintése
A Calf Perlben megvalósított objektum-orientált perzisztencia réteg. Az osztályok ebből
adódóan Perl csomagok. A forráskód könnyebb kezelhetőségét szem előtt tartva minden csomag
önálló fájlban került megvalósításra.
A következőkben bemutatott UML osztálydiagram az alábbi egyedi jelöléseket alkalmazza:
• Az adattagok csak statikus esetben kerültek feltüntetésre, mivel a Perl objektumok adattagjait
minden esetben egy referencia által hivatkozott dinamikusan változó, gyengén típusos
struktúra tartalmazza.
• A műveletek sztereotípusa <<constructor>>, ha a szubrutin felhasználása konstruktor
jellegű, <<auto>>, ha a szubrutint minden esetben az interpreter hívja, <<sub>>, ha
hagyományos Perl szubrutin, és végül <<method>>, ha OOP tagfüggvény. Utóbbi esetben
az első átadott paraméter jelzi, hogy statikus ($class), vagy objektumra értelmezett
($self).
• A műveletek típusa scalar, array, vagy hash, ha a megfelelő primitív típussal térnek
vissza, scalarrref, arrayref, vagy hashref, ha értékük ezekre hivatkozó, nem
megáldott referencia, illetve object, ha megáldott referencia.
• A műveletek paraméterlistájában a gyenge típusokat sigil jelzi, megáldott referencia esetén a
:object jelöléssel együtt. Az opcionális paraméterek neve mögött ? áll.
• A dőlt betűvel szedett osztályok absztraktnak szánt ősosztályok.
• A dőlt betűvel szedett metódusok implementációja nem teljes.
• A Calf::Debug csomag az összes többi függősége, ezek a nyilak az áttekinthetőség
megtartása érdekében hiányoznak.
A metódusok teljes listáját a részletes megjegyzésekkel ellátott forráskódra való tekintettel
mellőzöm.
Konfiguráció-menedzsment verziókövetett objektumokkal 47
Konfiguráció-menedzsment verziókövetett objektumokkal 48
3. Calf csomag
A Calf csomag és az azonos nevű osztály a keretrendszer belépési pontja. Az osztály egy
példánya egy, az objektum élettartamán keresztül folyamatos adatbáziskapcsolatot jelent.
Legfontosabb metódusa a checkout, amellyel a perzisztált objektumok visszanyerhetőek az
adatbázisból. Az így visszaállított objektumok később a Calf objektum nélkül újból
perzisztálhatóak, sőt, a mögöttes Calf::DB::Proxy objektum autocommit beállításától
függően az akár önműködően is történhet.
Felhasználási példa:
my $calf = new Calf( 'dsn' => 'DBI:mysql:database=calf;host=localhost;port=3306', 'user' => 'calf', 'pass' => 'secret');my $obj = $calf->checkout( 'name' => '/my/object', 'rev' => 2);print $obj->value( 'key' );
4. Calf::Tie csomagok
A Calf::Tie névtér alatt található csomagok nyújtják a korábbiakban bevezetett kötéshez
szükséges egyedi típus-implementációkat. A Calf::Tie::Scalar, Calf::Tie::Array,
valamint a Calf::Tie::Hash rendre egy Calf::Data objektumot rejtő skalár, tömb, illetve
hash implementáció. Ezek absztraktnak szánt ősosztálya a Calf::Tie::Base, amely
közvetlenül sehol sem kerül példányosításra.
Felhasználására jó példa a Calf::wrap szubrutin vonatkozó része:
my $object;my $type = $data->type;my $prefix = $type eq 'Scalar' ? '$' : $type eq 'Array' ? '@' : '%';eval "tie my ${prefix}var, 'Calf::Tie::$type', \$proxy, \$data; \$object = \\${prefix}var";
A bemutatott kódrészlet két szempontból is érdekes. Egyrészről látható, hogy a típusnak
megfelelő Calf::Tie osztály példányosításakor a konstruktor paraméterként kapja a $proxy
változót, amely egy Calf::DB::Proxy objektum. A kötés létrejötte után az
adatbázisműveleteket igénylő metódusok erre az objektumra fognak támaszkodni, azaz a fő
Konfiguráció-menedzsment verziókövetett objektumokkal 49
$calf objektum referenciája nélkül, önállóan képesek a megfelelő feladatok végrehajtására.
Másrészről tetten érhető a dinamikus programozási környezet előnyeinek kihasználása. A kód
szemantikailag egy var nevű változót köt egy típusának megfelelő osztályhoz. A szintaktika
elvárja a statikus sigilt, ami az eval használatával dinamikusan, futásidőben kerül
meghatározásra. Az eval beépített függvény használata nélkül ez csupán egy nehezebben
átlátható if-else szerkezettel lehetne megvalósítható, mi több, feleslegesen kellene deklarálni a
három típusnak megfelelően három különböző változót, melyek közül végül csak egyet
használna a program a kötéshez.
5. Calf::Object csomagok
A Calf::Object nyújtja a keretrendszer kiterjeszthetőségéhez szükséges névteret. A
Calf::Object önmagában egy absztraktnak szánt ősosztály, amely kényelmes metódusokat ad
egy keretrendszerbeli objektum megvalósításához. A három primitív típusnak megfelelően előre
adott három olyan osztály, amelyek kiterjesztik (Calf::Object::Scalar,
Calf::Object::Array, Calf::Object::Hash). Az ősosztály szolgáltatás-gazdagságát jól
mutatja, hogy ezek gyakorlatilag üres Perl csomagok.
A Calf::Object csomagban definiált metódusok a verziókövetett objektumok tipikus
műveleteit adják, többek között:
• type
Az objektum, mint referencia által mutatott adatstruktúra típusát adja sztringként.
Lehetséges értékei: Scalar, Hash, Array.
• value
Az objektum értéke, ha az objektum Scalar, vagy az objektum a paraméterben megadott
kulcsához tartozó érték. A metódus lehetővé teszi a sigilek egységesítését, ugyanis
használatával adattípustól függetlenül alkalmazható a $obj->value jelölés. A metódus
balértéket szolgáltat, tehát valóban mindenhol alkalmazható.
• commit
Az objektumon adatain végzett módosítások perzisztálására szolgál.
• copy
Másolatot készít az objektumról, és a másolat referenciájával tér vissza. A művelet egy
dimenzióig deep copy.
Konfiguráció-menedzsment verziókövetett objektumokkal 50
• attrs
Az objektum attribútumainak listáját adja.
• children
Az objektumfa alapján a gyermekek neveit szolgáltatja.
• name
Az objektum neve.
• id
Az objektum belső azonosítója.
• class
Az objektum osztályának perzisztált azonosítója. Ez nem egy csomagnév, hanem egy
másik Calf-beli objektum belső azonosítója, amely értékként szolgáltatja a csomagnevet.
• bind
Arra szolgál, hogy egy másik objektum adattagja – azonos néven – az adott objektum
attribútum-halmazához dinamikusan kötődjön. Azaz, egyszerűen megvalósítható egyfajta
szigorú öröklés az objektumok között és a következő állítás mindig igaz:
HA $A->bind( 'x', $B->id ) AKKOR $A->value( 'x' ) eq $B->value( 'x' )
6. Calf::DB csomagok
A Calf::DB::Proxy egy olyan objektumot ad, amelyen keresztül a keretrendszer többi
objektuma közvetlen adatbázisműveleteket képes elvégezni. Egy Calf objektum egy példányt
hoz belőle létre, melynek referenciáját minden adatbázisból lehívott objektumhoz kötött
típusimplementáció példányosításakor átadja.
A proxy egy Calf::DB objektumot használ a metódusainak megvalósításához, amely már a
közvetlen DBI hívásokat implementálja. A Calf::DB sem tartalmaz viszont SQL utasításokat a
keretrendszer hordozhatóságának érdekében. Ez a csomag úgymond a DBI-specifikus kódokat
tartalmazza.
Minden SQL utasítás egy SQL-dialektusnak megfelelő alcsomagban található. A jelenlegi
implementáció a MySQL adatbáziskezelőt támogatja, ezért az ehhez szükséges SQL kódok a
Calf::DB:mysql csomagból érhetőek el.
Konfiguráció-menedzsment verziókövetett objektumokkal 51
7. Calf::Data csomag
A Calf::Data a keretrendszer lelke. Ez egy olyan osztályt nyújt, amely az adatbáziskezelő
rutinoktól teljesen független, és példányai az egyedi típusimplementációkat nyújtó
objektumokat segítik. Az összes alacsony szintű, memóriában történő művelet megvalósítása itt
található. A Calf::Data szerepének és a többi osztályhoz való viszonyának jobb megértéséhez
lássunk egy szekvencia diagramot:
A diagram azt az esetet szemlélteti, amikor egy skalár típust rejtő objektum kap egy value
üzenetet. A Calf::Object osztályból örökölt value metódus ebben az esetben a $$self skalárt
szolgáltatja balértékként. Ennek elérésekor a Perl értelmező meghívja a változóhoz kötött
Calf::Tie::Scalar objektum megfelelő metódusát, amely az elrejtett Calf::Data objektum
attr metódusának segítségével fogja a hivatkozott értéket lekérdezni vagy módosítani. Utóbbi
művelet szükség esetén Copy-On-Write technikával történik.
8. A keretrendszer használatának bemutatása
A keretrendszer lehetőségeit jól demonstrálja a Calf::CLI csomag. Ez egy parancssoros
felületet biztosít a Calf által nyújtott szolgáltatásokhoz. A példa kedvéért tételezzük fel, hogy a
modellezendő feladat egy hoszt és egy rajta futó Tomcat kiszolgáló konfigurációjának
menedzsmentje.
Konfiguráció-menedzsment verziókövetett objektumokkal 52
Tegyük fel továbbá, hogy az adatbázis lényegében üres, viszont adott egy proto objektum,
amelynek gyermekei a scalar, array és hash objektumok, melyek rendre üres skalár, tömb és
hash objektumokat adnak.
$ bin/calf list /ROOT (1)proto (2)$ bin/calf list /protoscalar (3)hash (5)array (4)
Először hozzunk létre két objektumot az objektumfa gyökerében, amelyekre mint kollekciókra
fogunk a későbbiekben tekinteni, attribútumaik érdektelenek (hasonlóan a proto objektumhoz):
$ bin/calf copy proto/scalar hosts$ bin/calf copy proto/scalar servers$ bin/calf list /ROOT (1)hosts (6)proto (2)servers (7)
Ezután hozzunk létre egy objektumot a hosts objektum alatt, és állítsuk be:
$ bin/calf copy proto/hash hosts/localhost$ bin/calf set hosts/localhost hostname localhostlocalhost$ bin/calf set hosts/localhost ip 127.0.0.1127.0.0.1$ bin/calf set hosts/localhost port_tomcat 80808080$ bin/calf show hosts/localhost8#3port_tomcat : stringip : stringhostname : string
Ezt követően hozzunk létre egy tomcat objektumot a servers objektum alatt, és
konfiguráljuk:
$ bin/calf copy proto/hash servers/tomcat$ bin/calf set servers/tomcat name tomcattomcat$ bin/calf bind servers/tomcat hostname hosts/localhost$ bin/calf set servers/tomcat host hosts/localhosthosts/localhost
Konfiguráció-menedzsment verziókövetett objektumokkal 53
$ bin/calf show servers/tomcat9#3name : stringhostname : delegatehost: string$ bin/calf get servers/tomcat hostnamelocalhost
Az eddigi beállítások eredménye egy olyan modell, amely tartalmaz egy hoszt objektumot,
amelynek értelemszerű tulajdonsága a hostname és az ip, továbbá van egy port_tomcat
attribútuma, amely a rajta futó szerver portszámát jelképezi. A modellben a port a hoszt
tulajdonsága és nem a szerveralkalmazásé, ami pontosan tükrözi a valóságot.
Létrehoztunk ezen kívül egy Tomcat objektumot egy egyedi szolgáltatás-azonosítóval,
valamint hozzákötöttük a hostname attribútumot a host/localhost objektumhoz. Ennek
köszönhetően a tomcat objektum hostname attribútumának értéke mint konfigurációs paraméter
mindig a host/localhost objektum azonos nevű attribútumától függ. Beállítottunk továbbá
egy host attribútumot, amelynek felhasználására a következőkben láthatunk példát.
Adjunk saját implementációt ezeknek az objektumoknak az alábbi osztályokkal:
package Calf::Object::Host;
use strict;use warnings;
use base 'Calf::Object';
sub showip($@){ my $self = shift; my $ip = $self->value( 'ip' ); print "IP: $ip\n";}
sub getport($@){ my $self = shift; my $calf = shift; my $service = shift; my $port = $self->value( "port_$service" ); return $port;}
Konfiguráció-menedzsment verziókövetett objektumokkal 54
package Calf::Object::Tomcat;
use strict;use warnings;
use base 'Calf::Object';
sub config($@){ my $self = shift; my $calf = shift; my $hostname = $self->value( 'hostname' ); my $host = $calf->checkout( name => $self->value( 'host' ) ); my $port = $host->getport( $calf, $self->value( 'name' ) ); print "host = $hostname\n"; print "port = $port\n";}
Miután ezek adottak, változtassuk meg a meglévő localhost és tomcat objektumok típusát.
Ehhez létrehozunk egy classes kollekciót, és azon belül az objektumoknak megfelelő
osztályok neveit adó objektumokat.
$ bin/calf copy proto/scalar classes$ bin/calf copy proto/scalar classes/Host$ bin/calf set classes/Host Calf::Object::HostCalf::Object::Host$ bin/calf copy proto/scalar classes/Tomcat$ bin/calf set classes/Tomcat Calf::Object::TomcatCalf::Object::Tomcat$ bin/calf cast hosts/localhost classes/Host$ bin/calf cast servers/tomcat classes/Tomcat
A modellezés ezzel lényegében kész. Az elkészített objektumok a parancssoros felület által
nem definiált metódusaikat a Calf::Object::Host, illetve Calf::Object::Tomcat
osztályokból veszik, így a Tomcat szerver konfigurációja a config metódus egyszerű hívásával
kapható:
$ bin/calf config servers/tomcathost = localhostport = 8080
A portszám valóban dinamikus beállítás, az eredeti hoszt objektumon történő módosítás
hatással van a tomcat objektumra is:
$ bin/calf set hosts/localhost port_tomcat 42424242$ bin/calf config servers/tomcathost = localhostport = 4242
Konfiguráció-menedzsment verziókövetett objektumokkal 55
Továbbá megtekinthető az eredeti objektum korábbi változatában található attribútum értéke:
$ bin/calf get hosts/localhost#4 port_tomcat8080
Végezetül lássuk a keretrendszer lényeges függvényhívásait és a fontosabb adatszerkezeteket
egy attribútum értékének beállításakor:
$ bin/calf set servers/tomcat dir /var/www/tomcat -dINFO: Calf::DB::Proxy::lookup: 1/servers is 7 (db)INFO: Calf::DB::Proxy::lookup: 7/tomcat is 9 (db)INFO: Calf::DB::Proxy::head: 9#HEAD is 4 (db)INFO: Calf::DB::Proxy::fetch: fetched 9#4 (db)DEBUG: Calf::DB::Proxy::fetch: fetched object data $data = { 'obj' => { 'obj_id' => '9', 'type_id' => '5', 'tie' => 'HASH', 'class' => '12', 'obj_rev' => '4' }, 'attr' => { 'name' => { 'attr_key' => 'name', 'attr_val' => 'tomcat', 'attr_type' => 'string', 'attr_ref' => undef, 'attrval_id' => '5', 'attrkey_id' => '5' }, 'hostname' => { 'attr_key' => 'hostname', 'attr_val' => undef, 'attr_type' => 'delegate', 'attr_ref' => '8', 'attrval_id' => '6', 'attrkey_id' => '6' }, 'host' => { 'attr_key' => 'host', 'attr_val' => 'hosts/localhost', 'attr_type' => 'string', 'attr_ref' => undef, 'attrval_id' => '7', 'attrkey_id' => '7' } } };INFO: Calf::DB::Proxy::head: 12#HEAD is 1 (db)INFO: Calf::DB::Proxy::fetch: fetched 12#1 (db)
Konfiguráció-menedzsment verziókövetett objektumokkal 56
DEBUG: Calf::DB::Proxy::fetch: fetched object data $data = { 'obj' => { 'obj_id' => '12', 'type_id' => '1', 'tie' => 'SCALAR', 'class' => undef, 'obj_rev' => '1' }, 'attr' => { 'value' => { 'attr_key' => 'value', 'attr_val' => 'Calf::Object::Tomcat', 'attr_type' => 'string', 'attr_ref' => undef, 'attrval_id' => '9', 'attrkey_id' => '9' } } };/var/www/tomcatDEBUG: Calf::DB::Proxy::store: store object data $diff = { 'obj' => { 'obj_id' => '9', 'dirty' => 1, 'type_id' => '5', 'tie' => 'HASH', 'class' => '12', 'obj_rev' => '5' }, 'attr' => { 'dir' => { 'attr_key' => 'dir', 'attr_val' => '/var/www/tomcat', 'attr_type' => 'string' } } };INFO: Calf::DB::Proxy::store: 9#5 stored
A fenti példában a hibakereső módban indított calf szkript egy attribútum értékének frissítése
közben meghívott metódusokat és a közben felépített adatszerkezeteket mutatja. Jól látható,
hogy először az elérni kívánt objektum nevének rekurzív feloldása történik, majd az objektum
belső azonosítójának ismeretében (9) a legfrissebb verziószám (#4) meghatározása. Ezt követi
annak az objektumnak a betöltése amely az előző csomagnevét tartalmazza. Végezetül a
frissített attribútum egy új objektum-verzióval eltárolódik az adatbázisban.
Konfiguráció-menedzsment verziókövetett objektumokkal 57
A CD mellékleten megtalálható a keretrendszer teljes forráskódja, a használatbavételhez
szükséges SQL szkripttel és a bemutatott példakóddal együtt.
Konfiguráció-menedzsment verziókövetett objektumokkal 58
Irodalomjegyzék
1: http://en.wikipedia.org/wiki/Configuration_management
2: ftp://ftp.software.ibm.com/software/tivoli/datasheets/TID10375-USEN-00.pdf
3: http://documents.bmc.com/products/documents/82/35/48235/48235.pdf
4: http://www.w3.org/XML/
5: http://tools.ietf.org/html/rfc4511
6: http://www.microsoft.com/windowsserver2008/en/us/active-directory.aspx
7: Gajdos Sándor: Adatbázisok
8: http://mysql.com/
9: Larry Wall, Tom Christiansen, Jon Orwant: Programming Perl, Third Edition
10: http://search.cpan.org/
11: http://perldoc.perl.org/functions/ref.html
12: http://en.wikipedia.org/wiki/Sigil_(computer_programming)
13: http://perldoc.perl.org/perlboot.html
14: http://perldoc.perl.org/perltie.html