wtorek, 15 lipca 2008

968... czyli jak zostałem MCP

Powoli, z linuksiarza staję się rasowym windowsiarzem, nie to żebym jakoś specjalnie tego chciał, bardziej z racji wykonywanego zawodu. W związku z tym dzisiaj o godzinie 10:30, rozpocząłem egzamin oznaczony symbolem 70-291, czyli szumnie "Implementing, Managing, and Maintaining a Windows Server 2003 Network Infrastructure".

Zaczęło się całkiem sympatycznie - rejestracja, później kawa w oczekiwaniu aż się egzamin "ściągnie" (cokolwiek by to miało znaczyć ;). Po wejściu do sali egzaminacyjnej, krótki instruktarz i zaczęło się. Wylosowałem 47 pytań, na których rozwiązanie miałem ponad cztery godziny(!). Po pierwszych pięciu stwierdziłem, że to będzie banalnie proste... po dwudziestu już nie byłem tego taki pewien, bo pojawiły się trudniejsze pytania. Po półtorej godzinie udzieliłem odpowiedzi na wszystkie pytania i wykonałem jedną symulacje jaka mi się trafiła.

Zostało duuuuużo czasu. Stwierdziłem, że zastanawiać się nad udzielonymi odpowiedziami, po pierwsze, nie chce mi się, a po drugie, mógłbym jeszcze coś spieprzyć zbyt dużo myśląc, więc zakończyłem egzamin. Chwila niepewności.... i jest wynik - tytułowe 968. Zajebiście. Tego się nie spodziewałem, miałem nadzieję na 900, ale realnie zakładałem 850.

Po wyniku możnaby przypuszczać że zawaliłem jedno, góra dwa, pytania. Być może były to te dwa pytania z WSUSa, na które kompletnie strzelałem.

Następny w kolejce jest 70-290, a na razie czekam na maila z Microsoftu z potwierdzeniem zdania egzaminu.

poniedziałek, 14 lipca 2008

Czwarta cywilizacja czwarta


Dochodzę do wniosku, że jestem chyba graczem-gawędziarzem. Więcej mówię o graniu w swoje ulubione pozycje niż to rzeczywiście robię.

Civilization IV, polska premiera - 25 listopada 2005, pudełko stało na półce 30 listopada, łącznie zagrałem w nią trzy razy (w sensie zagrałem i ukończyłem). Civilization IV: Warlords, polska premiera - 25 sierpnia 2006, pudełko stało na półce dwa dni później, zagrałem raptem jeden raz. Civilization IV: Beyond the Swords, premiera - 30 lipca 2007, pudełko przyszło 10 sierpnia. W tę ostatnią udało mi się zagrać kilka razy(!) w przeciągu bez mała roku.

Teraz czytam informacje o nowym dodatku i już się oczywiście napalam na kupno, sprawdzam czy przypadkiem mój sprzet nie będzie wymagał upgrade'u, notuję w PIMie żeby nie przegapić premiery. Ostatecznie, stanie się kolejną ozdobą na półce, w którą zagram może dwa razy. A może nie ;)

...i jeszcze raz

Trzecia zmiana silnika bloga. Najpierw był NewsBruiser, później blog na bazie TWiki -- teraz przyszedł czas na Bloggera.

poniedziałek, 28 stycznia 2008

Eppur si muove...

Niniejszym mogę z całym spokojem ogłosić oficjalne wydanie pierwszego jądra PLD/FreeBSD, kernel posiada numerek 6.3.0.0 i zamyka pewien etap tego projektu. Z wydaniem tego jądra wiąże się bowiem to, że do przebudowania całości nie bedzie już nigdy potrzebny FreeBSD (na którym do tej pory było produkowane jądro dla PLD/FreeBSD).

Z ciekawostek, jako że nikt mi nigdy nie powiedział, że do budowania jądra nie da się zaprząc autoconfa i automake'a. I z drugiej strony, z braku pomysłu na szybkie w implementacji narzędzie do budowania tegoż, spróbowałem użyć do tego celu właśnie autotoolsy… I udało się. Pomijam, że regeneracja plików configure i wszystkich Makefile'ów trwa dłuzej niż samo budowanie kernela, kto by sie tym przejmował.

Teraz, kolejny duży krok to będzie instalator… ale kiedy?

wtorek, 24 kwietnia 2007

Winowajca odnaleziony

Znalazłem winnego. Byłem prawie pewien, że to był aniou, ale wydawało mi się że to było rok albo dwa wcześniej. W każdym razie taka jest geneza PLD/FreeBSD.

czwartek, 19 kwietnia 2007

New look and feel

Tak się złożyło, że dysponując chwilą wolnego czasu zabrałem się do realizacji od dawna odkładanych zadań. Skutkiem czego wiki (a zatem i blog) doczekało się w końcu nowego, lepszego wyglądu. Stare skórki są (dla ciekawych) nadal dostępne, np. http://wiki.pld-freebsd.org/bin/view/Blog/BlogEntry6?skin=pattern

środa, 7 marca 2007

PLD/FreeBSD Preview 1

Ponieważ zgłosiło się do mnie już kilka osób z pytaniem jak można zainstalować PLD/FreeBSD postanowiłem coś z tym zrobić. Na początek PLD/FreeBSD Preview 1 w postaci spakowanej maszyny wirtualnej do VMWare Workstation. Do pobrania tutaj (41.5 MB). System minimalny jak tylko się dało, więc można sobie popoldkować.

Po uruchomieniu maszyny i zalogowaniu się na roota (hasło puste) trzeba skonfigurować sieć:

ifconfig lnc0 192.168.1.2
route add default 192.168.1.1
echo "nameserver 192.168.1.1" > /etc/resolv.conf
albo wyedytować znane z PLD pliki odpowiedzialne za powyższe i zrestartować usługę network
/etc/rc.d/init.d/network restart
I już można działać. Nie polecam instalowania pakietu kernel i loader bo te które są na FTPie mogą kompletnie rozwalić system.

Zainteresowanym życzę miłej zabawy.

Jak tylko znajdę chwilę czasu postaram się opisać jak zainstalować PLD/FreeBSD na fizycznej maszynie przy pomocy płyty instalacyjnej FreeBSD.

wtorek, 6 marca 2007

Do builderów podejscie trzecie

Po raz trzeci zabrałem się za pisanie builderów dla PLD/FreeBSD. Efekt jest taki, że podstawowe funkcjonalności są już gotowe, a w czasie kiedy na nowych builderach testowo przebudowywane są wszystkie pakiety spłodziłem krótki tekst opisujacy ich działanie. Zainteresowanych zapraszam do lektury.

czwartek, 15 lutego 2007

Ciekawa własność NULLa

W bólach implementacji swoich builderów natknąłem się na ciekawą własność NULLa w MySQL. Nie wiem czy pojawia sie ona również innych SQLach.

Najprościej bedzie na przykladzie. Załózmy, że mamy dwie tabele "process" i "task". Tabela "process" zawiera listę procesów wykonywanych przez pewien abstrakcyjny procesor, na każdy proces składa się pewna ilość zadań, przy czym każde zadanie może należeć tylko do jednego procesu; czyli prosta relacja jeden do wielu. Dodatkowo każde zadanie posiada właściwość "status" określająca stan tego zadania. Dla ustalenia uwagi niech pole "status" może przyjmować trzy wartości: "none", "running" lub "completed". Definicja tych tabel może wyglądac tak:

CREATE TABLE process (
id INT UNSIGNED PRIMARY KEY NOT NULL auto_increment,
name VARCHAR);
CREATE TABLE task (
id INT UNSIGNED PRIMARY KEY NOT NULL auto_increment,
id_process INT UNSIGNED NOT NULL,
status ENUM('none', 'running', 'completed') NOT NULL);

Zapytanie które zwróci nam identyfikator procesu wraz z ilością zadań przyporzadkowanych do tego procesu jest oczywiście trywialne i wyglada tak:

SELECT id_process, COUNT(*) FROM task GROUP BY id_process;

Problemem natomiast jest zapytanie zwracajace identyfikator procesu wraz z ilością zadań przyporzadkowanych do tego procesu, ale takich które nie zostały jeszcze zakończone, czyli mają status różny od 'completed'. Proste:

SELECT id_process, COUNT(status != 'completed') FROM task GROUP BY id_process;
nie wystarcza ponieważ COUNT zlicza zgrupowane wartości bez wzgledu na ich wartość. W tym przypadku zarówno TRUE jak i FALSE jest traktowane jako element to zliczenia. Zatem powyższe zapytanie zwraca to samo co poprzednie, czyli identyfikator procesu wraz z ilością zadań przyporzadkowanych do tego procesu.

Możnaby oczywiście uzyć funkcji SUM i IF w następujący sposób:

SELECT id_process, SUM(IF(status != 'completed), 1, 0) FROM task GROUP BY id_process;
Ale to nie dość, że niezgodne z zasadami sztuki, to jeszcze mało czytelne i pewnie mało wydajne.

Aby w prosty sposób uzyskać oczekiwany wynik wystarczy wykorzystać to że wartości NULLniepoliczalne dla funkcji COUNT. Jeżeli zgrupujemy rekordy które w zadanym polu maja cztery wartości z czego dwie są równe NULL to funkcja COUNT na tym polu zwróci nam 2, a nie 4.

Wystarczy zatem doprowadzić ostatnie zapytanie wykorzystujące funkcję COUNT do takiej postaci, w której wartość argumentu jest policzalna gdy pole "status" jest inne niż 'completed', a niepoliczalna (czyli równa NULL) w przeciwnym wypadku. Wyrażenie

status != 'completed' OR NULL
spełnia te założenia ponieważ przyjmuje jedną z dwóch wartości: TRUE dla pola "status" różnego od 'completed', albo NULL w przeciwnym wypadku.

Ostatecznie zapytanie zwracajace identyfikator procesu wraz z ilością zadań przyporzadkowanych do tego procesu, takich które nie zostały jeszcze zakończone wygląda tak:

SELECT id_process, COUNT(status != 'completed' OR NULL) FROM task GROUP BY id_process;

Śliczne, prawda?

wtorek, 6 lutego 2007

Dlaczego CVS ssie...

W gruncie rzeczy tekst ma być o tym dlaczego SVN jest lepszym wyborem w przypadku repozytorium pakietów. Swoje przemyślenia opieram na bez mała trzy i pół rocznym doświadczeniu z repozytorium http://svn.pld-freebsd.org/svn/packages, dostepnym równiez przez ViewCVS: http://svn.pld-freebsd.org/cgi-bin/viewsvn/.

Struktura repozytorium różni sie znacząco od płaskiego modelu repozytorium stosowanego w PLD. W dużym uproszczeniu wygląda ona tak:

packages
+- trunk
| +- db
| | +- SOURCES
| | | +- patch1.patch
| | | +- patch2.patch
| | +- SPECS
| | +- db.spec
| +- rpm
| +- SOURCES
| | +- patch1.patch
| | +- patch2.patch
| +- SPECS
| +- rpm.spec
+- branches
| +- rpm-4.1.1
| | +- db
| | | +- SOURCES
| | | | +- patch1.patch
| | | | +- patch2.patch
| | | +- SPECS
| | | +- db.spec
| | +- rpm
| | +- SOURCES
| | | +- patch1.patch
| | | +- patch2.patch
| | +- SPECS
| | +- rpm.spec
| +- rpm-4.4.1
| +- db
| | +- SOURCES
| | | +- patch1.patch
| | | +- patch2.patch
| | +- SPECS
| | +- rpm.spec
| +- rpm
| +- SOURCES
| | +- patch1.patch
| | +- patch2.patch
| +- SPECS
| +- rpm.spec
+- tags
+- Ac-rpm-4.4.1-2
+- db
| +- SOURCES
| | +- patch1.patch
| | +- patch2.patch
| +- SPECS
| +- rpm.spec
+- rpm
+- SOURCES
| +- patch1.patch
| +- patch2.patch
+- SPECS
+- rpm.spec

Jak widać na powyższym schemacie dla każdego pakietu została wydzielona osobna gałąź w drzewie repozytorium. Taki zabieg, poza uporzadkowaniem i separacją składników poszczególnych pakietów, pozwala na rozdzielenie przestrzeni nazw plików w pakietach. A co za tym idzie, powoduje że np. nazwa patcha może być dowolna dla zadanego pakietu i nie istnieje konieczność pilnowania żeby nazwy łatek dla różnych pakietów nie kolidowały ze sobą. W szczególności, nie ma potrzeby narzucania nazewnictwa tych łatek do postaci nazwa_pakietu-nazwa_łatki.patch jak ma to miejsce w PLD.

Ściagnięcie całego drzewa trunk może wygląda nastepująco:

svn checkout http://svn.pld-freebsd.org/svn/packages/trunk packages
Natomiast ściagniecie i kompilacja pakietu db z takiego repozytorium wygląda tak:
$ cd ~/packages
$ svn checkout http://svn.pld-freebsd.org/svn/packages/trunk/db
$ cd db/SPECS
$ rpmbuild -ba --define "_topdir ~/packages/db" db.spec
Powyższy przykład nie uwzględnia oczywiście ściagnięcia ewentualnych tarballi z distfiles.

Drzewiastej strukturze repozytorium można zarzucać niemozliwość "przegrepowania" wszystkich specy, albo wprowadzania masowych zmian w specach. Wadę tą można wyeliminować używając polecenia find. I tak odpowiednikiem grep jakisstring * w katalogu SPECS jest

find . -name "*.spec" -exec grep -H jakisstring {} \;
w katalogu packages/trunk.

Praca z takim repozytorium nie jest dużo bardziej skomplikowana, niż z płaskim repozytorium CVSowym. A prawie zupełnie nie różni się gdy użyjemy odpowiednio zmodyfikowanego skryptu builder.

Kolejną przewagą nad CVSem są "atomowe" commity. Polega to na tym, że po wprowadzeniu zmian z pakiecie, zmiany są przekazywane do repozytorium jednym poleceniem, np.

$ cd ~/packages
$ svn commit -m "- updated to 4.5\n- updated patch1 patch" db
Co najważniejsze, takie dokonanie zmiany jest traktowane w repozytorium jako integralna całość identyfikowana numerem rewizji w repozytorium, a nie jest złożeniem zmian w poszczególnych plikach. Co za tym idzie możemy łatwo odszukać, że np. update db do wersji 4.5 pociągneło za sobą usuniecie pliku SOURCES/patch1.patch. W CVSie, niestety, każda tego typu zmiana jest w repozytorium traktowana osobno, dlatego dużo wiecej pracy kosztuje odnalezienie jak zmieniły się pozostałe pliki pakietu, podczas określonej zmiany pliku spec. Takie zachowanie CVSa jest dla mnie szczególnie uciążliwe, ponieważ w swojej pracy intensywnie śledzę zmiany w repozytorium PLD w celu nanoszenia niektórych z nich w PLD/FreeBSD.

Atomowość commitów w repozytorium pociaga za sobą również zwiekszenie przejrzystości commitlogów, dzięki temu są one generowane jako pojedynczy mail, a nie dwa osobne maile zawierajace zmiany odpowiednio, w module SPECS i w module SOURCES.

Kolejna przewagą Subversion jest możliwość przenoszenia plików (z zachowaniem historii zmian) z poziomu użytkownika. W CVSie taka operacja wymaga zaangażowania administratora repozytorium, który musi dokonać takiej zmiany po stronie serwera.

Dla niektórych kolejną wadą SVNa może być niemożliwość generowania sekcji %changelog, tak jak ma to miejsce w chwili obecnej w PLD. Według mnie używanie $Log$ do generowania loga to średnio dobry pomysł, tym bardziej, że taki log nie jest tworzony w formacie przyjmowanym przez RPMa. Słuszniej byłoby gdyby %changelog był generowany z loga SVNa na source-builderach w formacie natywnym dla RPMa.

Na koniec wypada jeszcze wspomnieć o łatwości instalacji serwera Subversion. Po raz pierwszy zajeło mi to kilkanaście minut, podczas gdy na instalację serwera CVSu straciłem kilka(naście) godzin.