CDB ile Portage'yi Hizlandirmak

From Lapis Wiki

Jump to: navigation, search
Bu makale NASIL bölümü serisinin bir parçasıdır
MasaÜstü Donanım Dağıtımlar
Tarayıcılar Programlama Linux ve Oyunlar

Konu başlıkları

Giriş

emerge sync komutunu verdiğinizde işlemin çok uzun sürdüğü hepimizin dikkatini çekmiştir. Bu belgede emerge sync komutunu verdikten sonra, nasıl radikal bir şekilde hız kazancı yapabileceğimizi ve bağımlılıkları nasıl hızlı bir şekilde düzenlenebileceğini okuyacaksınız.

emerge sync işleminde çok sayıda dosya okunmaya ve işlenmeye tabi tutulur. Buda size zaman kaybına sebeb verir. Oysa bütün META verilerinin bir veribankasına saklanmış olması ve ordan okunuyor olması size hız kazancı ve aavantajı sağlar. Bu belgede anlatılanları orjinal olarak bulabilirsiniz. Bu yazıda 1:1 tercüme yapılmayacaktır, aksine okunup uygunalacak ve kendi tecrübelerimiz aktarılacaktır.

Gerekli Olanlar

Aslında çok fazla bir şeye ihtiyacımız yok. Herkes bu işlem için en sevdiği bir metin düzenleyiciyi (editor) kullanabilir. Başlamadan önce ilk yapmamız gereken cdb-Modulunu emerge etmek:

emerge -av dev-python/python-cdb

Portage Ayarları

Portage'nin cdb ile uyumlu çalışabilmesi için 2 dosya düzenlememiz yeterli:

Özel Modul Oluşturmak

İlkönce Portage ile iletişimi sağlayacak olan bir dosyayı düzenlememiz gerekli. Bu sayede portage ile cdb ortak ve sorunsuz çalışacaklardır.


Şimdi yeni bir /usr/lib/portage/pym/portage_db_cdb.py dosyası oluşturalım ve aşağıdaki kodu ilave edelim:

File: /usr/lib/portage/pym/portage_db_cdb.py
# Copyright 2004, 2005 Tobias Bell <tobias.bell@web.de>
# Copyright 2004, 2005 Tobias Bell <tobias.bell@web.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import portage_db_template
import os
import os.path
import cPickle
import cdb


class _data(object):

    def __init__(self, path, category, uid, gid):
        self.path = path
        self.category = category
        self.uid = uid
        self.gid = gid
        self.addList = {}
        self.delList = []
        self.modified = False
        self.cdbName = os.path.normpath(os.path.join(
            self.path, self.category) + ".cdb")
        self.cdbObject = None

    def __del__(self):
        if self.modified:
            self.realSync()

        self.closeCDB()

    def realSync(self):
        if self.modified:
            self.modified = False
            newDB = cdb.cdbmake(self.cdbName, self.cdbName + ".tmp")
           
            for key, value in iter(self.cdbObject.each, None):
                if key in self.delList:
                    if key in self.addList:
                        newDB.add(key, cPickle.dumps(self.addList[key], cPickle.HIGHEST_PROTOCOL))
                        del self.addList[key]
                elif key in self.addList:                   
                    newDB.add(key, cPickle.dumps(self.addList[key], cPickle.HIGHEST_PROTOCOL))
                    del self.addList[key]
                else:
                    newDB.add(key, value)
               

            self.closeCDB()

            for key, value in self.addList.iteritems():
                newDB.add(key, cPickle.dumps(value, cPickle.HIGHEST_PROTOCOL))
           
            newDB.finish()
            del newDB
           
            self.addList = {}
            self.delList = []

            self.openCDB()

    def openCDB(self):
        prevmask = os.umask(0)
       
        if not os.path.exists(self.path):
            os.makedirs(self.path, 02775)
            os.chown(self.path, self.uid, self.gid)
           
        if not os.path.isfile(self.cdbName):
            maker = cdb.cdbmake(self.cdbName, self.cdbName + ".tmp")
            maker.finish()
            del maker
            os.chown(self.cdbName, self.uid, self.gid)
            os.chmod(self.cdbName, 0664)

        os.umask(prevmask)
           
        self.cdbObject = cdb.init(self.cdbName)

    def closeCDB(self):
        if self.cdbObject:
            self.cdbObject = None


class _dummyData:
    cdbName = ""

    def realSync():
        pass
    realSync = staticmethod(realSync)


_cacheSize = 4
_cache = [_dummyData()] * _cacheSize


class database(portage_db_template.database):   

    def module_init(self):
        self.data = _data(self.path, self.category, self.uid, self.gid)

        for other in _cache:
            if other.cdbName == self.data.cdbName:
                self.data = other
                break
        else:
            self.data.openCDB()
            _cache.insert(0, self.data)           
            _cache.pop().realSync()
           
    def has_key(self, key):
        self.check_key(key)
        retVal = 0

        if self.data.cdbObject.get(key) is not None:
            retVal = 1

        if self.data.modified:
            if key in self.data.delList:
                retVal = 0
            if key in self.data.addList:
                retVal = 1
           
        return retVal

    def keys(self):
        myKeys = self.data.cdbObject.keys()

        if self.data.modified:
            for k in self.data.delList:
                myKeys.remove(k)
            for k in self.data.addList.iterkeys():
                if k not in myKeys:
                    myKeys.append(k)
                   
        return myKeys

    def get_values(self, key):
        values = None
       
        if self.has_key(key):
            if key in self.data.addList:
                values = self.data.addList[key]
            else:
                values = cPickle.loads(self.data.cdbObject.get(key))

        return values
   
    def set_values(self, key, val):
        self.check_key(key)
        self.data.modified = True
        self.data.addList[key] = val

    def del_key(self, key):
        retVal = 0
       
        if self.has_key(key):
            self.data.modified = True
            retVal = 1
            if key in self.data.addList:
                del self.data.addList[key]
            else:
                self.data.delList.append(key)

        return retVal
                   
    def sync(self):
        pass
   
    def close(self):
        pass


if __name__ == "__main__":
    import portage
    uid = os.getuid()
    gid = os.getgid()
    portage_db_template.test_database(database,"/tmp", "sys-apps", portage.auxdbkeys, uid, gid)


Portage'ye cdb Modulunu kullanmasını söylemek

Yukardaki işlemi yapıp dosyamızı oluşturduktan sonra Portage'ye yeni veribankamızı kullanmasını söylememiz gerekli. Bunu için /etc/portage/modules dosyasını açıp, aşağıdaki 2 satırı ilave etmemiz gerekir. Eğer dosya önceden mevcut ise, o satırın yorum olmamasına, yani satır başında # işaretinin olmamasına dikkat edin:


File: /etc/portage/modules
portdbapi.auxdbmodule = portage_db_cdb.database
eclass_cache.dbmodule = portage_db_cdb.database

Son Adım

Sonrada Portage-Cache'i tekrardan oluşturalım

emerge metadata

Uyarılar

  • Portage de yapılan güncellemeler oldukça hızlı yapılacaktır. Bunu tespit etmek için emerge --searchdesc python komutunu verip kendiniz test edebilir ve aradaki farkı görebilirsiniz.
  • Eğer bu işlem hoşunuza gitmez veya herhangi bir yerde yanlış yapar ve geriye dönmek isterseniz /etc/portage/modules dosyasına ilave ettiğiniz 2 satırı kaldırmanız yeterlidir.
  • DirtyEpic Gentoo Forum da şöyle bir ipucu verdi: Eğer python 2.4 e güncelleme yaparsanız Portagenizin yapısı bozulabilir. Bu durumda /etc/portage/modules dosyasındaki 2 satırı yorum yapın ve portageyi tekrardan emerge edin. CDB de bu sayede düzelecektir.
  • Birçok durumda modul isimlerini yorum haline getirmek ve Metacache'i emerge metadata komutuyla yeniden oluşturmak için yeterlidir. Daha sonra /usr/sbin/python-updater komutu uygulanmalı ve 2 satırı tekrar açmanız yeterlidir. Sonra tekrardan emerge metadata komutu verilmelidir.
  • İlaveten python-cdb tekrar emerge edilmelidir.

Kaynaklar