When it comes to speed the database backend of portage is rather slow because it's implemented as a raw abstraction in the filesystem. It is possible to replace this with a mysql backend which is not ideal, if you don't want to start a full-blown RDBMS. My solution is rather tiny, if you compare the code and the packages you need for that:
- You'll need the python interface python-cdb for DJB's cdb
Code: emerge python-cdb
- Create /usr/lib/portage/pym/portage_db_cdb.py and put this in it:
Code: # 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)
- Create /etc/portage/modules and fill in
Code: portdbapi.auxdbmodule = portage_db_cdb.database
eclass_cache.dbmodule = portage_db_cdb.database
- Now you'll have to regenerate the portage cache with
Code: emerge metadata - Create /usr/lib/portage/pym/portage_db_cdb.py and put this in it:
Now try some searches with emerge especially with --searchdesc
Code: |
emerge --searchdesc python |
db module. Just make a
Code: |
mv /etc/portage/modules /etc/portage/__modules |
Default portage
Code: |
cd /var/cache/edb/dep/usr rm * -Rf time emerge metadata real 0m40.575s user 0m26.260s sys 0m9.592s time emerge -S mozilla real 1m46.003s user 1m36.215s sys 0m8.721s time emerge -upDv world real 0m14.678s user 0m13.289s sys 0m1.130s |
python-cdb powered portage
Code: |
cd /var/cache/edb/dep/usr rm * -Rf time emerge metadata real 2m18.022s user 0m26.538s sys 0m31.505s time emerge -S mozilla real 1m39.624s user 1m32.628s sys 0m5.418s time emerge -upDv world real 0m13.856s user 0m12.986s sys 0m0.727s |
## emerge 명령어 사용법 ##
emerge 옵션 테이블
Option1 | Option2 | 기능 | ||
-s | search | 프로그램 찾기 및 각 프로그램에 대한 설명 참조 가능 | ||
-p | pretend | 프로그램 설치 이전, 설치를 가정하고 어떤 일이 벌어지는지 확인 가능 | ||
-v | -- | pretend 옵션과 더불어 쓰이며, 설정 혹은 비설정 use 옵션 확인 가능 | ||
unmerge | 설치된 패키지 삭제 옵션,(>,<,=)기호 사용시 특정 버젼선택 삭제가능 | |||
help | 자세한 설명 필요할때 | |||
rsync | 포테이지 트리 업데이트 옵션 | |||
fetchonly | 필요한 압축파일을 다운로드(컴파일안함) | |||
emptytree | 포테이지가 패키지및 의존성을 만족하는 패키지들이 모두 설치되지 않은것으로 인식 | |||
nodeps | 의존성을 무시하고 패키지 설치(컴파일 실패 가능성..있음) | |||
onlydeps | 패키지의 의존성을 만족시키기 위한 것들만 설치(지정 패키지 설치안됨) | |||
noreplace | 이미 설치되어 있다면 패키지 설치를 생략 | |||
usepkg | 컴파일이 아닌 이미 컴파일된 바이너리로 설치시도(PKGDIR 환경변수값 이용) | |||
debug | ebuild에 기초한 bash스크립트 문법적 에러를 추적할때 사용 | |||
autoclean | emerge가 패키지의 빌드를 시작하기전에 임시 빌드 디렉토리 강제 청소 | |||
verbose | emerge가 더 많은 정보를 표시 | |||
update | 패키지 업데이트시 사용 | |||
prune | 가장 마지막으로 설치된 버전을 제외하고 모든 패키지의 모든 버전들을 제거 |
사용법 emerging
사용법 1. emerge package_name
# emerge mozilla
사용법 2. emerge dir/package_name rsync처럼 패키지명이 emerge의 특정 옵션으로 사용될 경우에 사용
# emerge net-misc/rsync
사용법 3. emerge emergefile 특정 버전을 설치할 때 사용
# emerge mozilla-1.3-r1.ebuild
portage tree 동기화
# emerge sync
or
# emerge rsync
/usr/portage의 개인 설정이 있다면 전부 삭제됨
sync와 rsync는 완전히 동일하게 작동합니다. /lefthander
메뉴얼에서는 rsync가 sync보다 서버의 부하를 덜 주어서 될수 있으면 rsync를 이용해 달라는 당부의 글이 있습니다.
아마도 sync는 모든 파일을 갱신하고 rsync는 없는 파일만 갱신하는것이 아닌가 싶습니다.
# emerge-webrsyncsync
보다 속도가 더 빠름. 스냅샷 압축파일을 받아와서 동기화
portage tree 갱신
# emerge -up system
# emerge -up world
업데이트할 수 있는 system, world 패키지 확인
# emerge system
시스템 패키지 업데이트
# emerge world
world 패키지 업데이트
system과 world를 업데이트할 때 -u (--update) 옵션을 사용하면 의존성 있는 패키지도 함께 갱신한다.
이 의존성에 걸리는 패키지는 다운그레이드될 수 있다.
패키지 인스톨 전 확인
# emerge --pretend [package name]
or
# emerge -p pornview
# emerge -pv [package_name | ebuildfile]
설치할 패키지가 이미 설치되어 있는지, 의존관계 등의 정보를 확인
패키지 인스톨
#emerge [package name]
변경점 확인
#emerge --changelog [package name] or emerge -pl [package name]
이미 설치된 패키지와 portage상의 최신 패키지와의 차이 표시
패키지 갱신
#emerge [package name]
## 패키지 관리 명령어 비교 (yum / emerge / apt-get) ##
1. 패키지 목록 업데이트
====Fedora==== root@Fedora # yum check-update ====Gentoo==== root@Gentoo # emerge --sync ====Debian==== root@Debian # apt-get update
2. 최신 패키지로 업데이트
====Fedora==== root@Fedora # yum update ====Gentoo==== root@Gentoo # emerge -DNu world ====Debian==== root@Debian # apt-get upgrade
3. 패키지 설치
====Fedora==== root@Fedora # yum install <packagename> ====Gentoo==== root@Gentoo # emerge <packagename> ====Debian==== root@Debian # apt-get install <packagename>
4. 패키지 재설치
====Fedora==== root@Fedora # yum update <packagename> ====Gentoo==== root@Gentoo # emerge --oneshot <packagename> ====Debian==== root@Debian # apt-get install --reinstall <packagename>
5. 패키지 검색
====Fedora==== root@Fedora # yum search <packagename> ====Gentoo==== root@Gentoo # emerge --searchdesc <packagename> ====Debian==== root@Debian # apt-cache search <packagename>
6. 패키지 삭제
====Fedora==== root@Fedora # yum remove <packagename> ====Gentoo==== root@Gentoo # emerge --unmerge <packagename> ====Debian==== root@Debian # apt-get remove <packagename>
참고 : http://wiki.kldp.org/wiki.php/PackageMgmt
댓글