Add pkg auto edge basics with packagekit improvements

This is a monster patch that finally gets the iterative pkg auto edges
working the way they should. For each file, as soon as one matches, we
don't want to keep add dependencies on other file objects under that
tree structure. This reduces the number of necessary edges considerably,
and allows the graph to run more concurrently.
This commit is contained in:
James Shubin
2016-03-07 16:42:05 -05:00
parent a9538052bf
commit f39551952f
6 changed files with 724 additions and 30 deletions

View File

@@ -36,17 +36,30 @@ const (
const (
// FIXME: if PkBufferSize is too low, install seems to drop signals
PkBufferSize = 1000
PkPath = "/org/freedesktop/PackageKit"
PkIface = "org.freedesktop.PackageKit"
PkIfaceTransaction = PkIface + ".Transaction"
dbusAddMatch = "org.freedesktop.DBus.AddMatch"
PkBufferSize = 1000
// TODO: the PkSignalTimeout value might be too low
PkSignalPackageTimeout = 60 // 60 seconds, arbitrary
PkSignalDestroyTimeout = 15 // 15 seconds, arbitrary
PkPath = "/org/freedesktop/PackageKit"
PkIface = "org.freedesktop.PackageKit"
PkIfaceTransaction = PkIface + ".Transaction"
dbusAddMatch = "org.freedesktop.DBus.AddMatch"
)
var (
// GOARCH's: 386, amd64, arm, arm64, mips64, mips64le, ppc64, ppc64le
PkArchMap = map[string]string{ // map of PackageKit arch to GOARCH
// TODO: add more values
"x86_64": "amd64",
// fedora
"x86_64": "amd64",
"aarch64": "arm64",
// debian, from: https://www.debian.org/ports/
"amd64": "amd64",
"arm64": "arm64",
"i386": "386",
"i486": "386",
"i586": "386",
"i686": "386",
}
)
@@ -311,7 +324,7 @@ loop:
// should already be broken
break loop
} else {
return []string{}, errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return []string{}, errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
}
}
}
@@ -381,9 +394,10 @@ func (bus *Conn) InstallPackages(packageIds []string, transactionFlags uint64) e
if call.Err != nil {
return call.Err
}
timeout := -1 // disabled initially
finished := false
loop:
for {
// FIXME: add a timeout option to error in case signals are dropped!
select {
case signal := <-ch:
if signal.Path != interfacePath {
@@ -392,22 +406,29 @@ loop:
}
if signal.Name == FmtTransactionMethod("ErrorCode") {
return errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
} else if signal.Name == FmtTransactionMethod("Package") {
// a package was installed...
// only start the timer once we're here...
timeout = PkSignalPackageTimeout
continue loop
} else if signal.Name == FmtTransactionMethod("Finished") {
// TODO: should we wait for the Destroy signal?
break loop
finished = true
timeout = PkSignalDestroyTimeout // wait a bit
continue loop
} else if signal.Name == FmtTransactionMethod("Destroy") {
// should already be broken
break loop
return nil // success
} else {
return errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
}
case _ = <-TimeAfterOrBlock(timeout):
if finished {
log.Println("PackageKit: Timeout: InstallPackages: Waiting for 'Destroy'")
return nil // got tired of waiting for Destroy
}
return errors.New(fmt.Sprintf("PackageKit: Timeout: InstallPackages: %v", strings.Join(packageIds, ", ")))
}
}
return nil
}
// remove list of packages
@@ -440,7 +461,7 @@ loop:
}
if signal.Name == FmtTransactionMethod("ErrorCode") {
return errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
} else if signal.Name == FmtTransactionMethod("Package") {
// a package was installed...
continue loop
@@ -451,7 +472,7 @@ loop:
// should already be broken
break loop
} else {
return errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
}
}
}
@@ -485,7 +506,7 @@ loop:
}
if signal.Name == FmtTransactionMethod("ErrorCode") {
return errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
} else if signal.Name == FmtTransactionMethod("Package") {
// a package was installed...
continue loop
@@ -496,7 +517,7 @@ loop:
// should already be broken
break loop
} else {
return errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
}
}
}
@@ -505,6 +526,8 @@ loop:
// get the list of files that are contained inside a list of packageids
func (bus *Conn) GetFilesByPackageId(packageIds []string) (files map[string][]string, err error) {
// NOTE: the maximum number of files in an RPM is 52116 in Fedora 23
// https://gist.github.com/purpleidea/b98e60dcd449e1ac3b8a
ch := make(chan *dbus.Signal, PkBufferSize) // we need to buffer :(
interfacePath, err := bus.CreateTransaction()
if err != nil {
@@ -533,7 +556,7 @@ loop:
}
if signal.Name == FmtTransactionMethod("ErrorCode") {
err = errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
err = errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
return
// one signal returned per packageId found...
@@ -560,7 +583,7 @@ loop:
// should already be broken
break loop
} else {
err = errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
err = errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
return
}
}
@@ -596,7 +619,7 @@ loop:
}
if signal.Name == FmtTransactionMethod("ErrorCode") {
return nil, errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return nil, errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
} else if signal.Name == FmtTransactionMethod("Package") {
//pkg_int, ok := signal.Body[0].(int)
@@ -620,7 +643,7 @@ loop:
// should already be broken
break loop
} else {
return nil, errors.New(fmt.Sprintf("PackageKit error: %v", signal.Body))
return nil, errors.New(fmt.Sprintf("PackageKit: Error: %v", signal.Body))
}
}
}
@@ -667,7 +690,8 @@ func (bus *Conn) PackagesToPackageIds(packageMap map[string]string, filter uint6
s := strings.Split(packageId, ";")
//if len(s) != 4 { continue } // this would be a bug!
pkg, ver, arch, data := s[0], s[1], s[2], s[3]
if goarch, ok := PkArchMap[arch]; !ok || goarch != runtime.GOARCH {
// we might need to allow some of this, eg: i386 .deb on amd64
if !IsMyArch(arch) {
continue
}
@@ -811,3 +835,12 @@ func FlagInData(flag, data string) bool {
func FmtTransactionMethod(method string) string {
return fmt.Sprintf("%s.%s", PkIfaceTransaction, method)
}
func IsMyArch(arch string) bool {
goarch, ok := PkArchMap[arch]
if !ok {
// if you get this error, please update the PkArchMap const
log.Fatalf("PackageKit: Arch '%v', not found!", arch)
}
return goarch == runtime.GOARCH
}