Merge pull request #589 from smira/api-db-no-lock-fix

Rework the way database is open/re-open in aptly
This commit is contained in:
Andrey Smirnov
2017-07-05 12:57:26 +03:00
committed by GitHub
39 changed files with 143 additions and 117 deletions
+28 -23
View File
@@ -23,11 +23,18 @@ func apiVersion(c *gin.Context) {
c.JSON(200, gin.H{"Version": aptly.Version}) c.JSON(200, gin.H{"Version": aptly.Version})
} }
type dbRequestKind int
const ( const (
acquiredb = iota acquiredb dbRequestKind = iota
releasedb releasedb
) )
type dbRequest struct {
kind dbRequestKind
err chan<- error
}
// Flushes all collections which cache in-memory objects // Flushes all collections which cache in-memory objects
func flushColections() { func flushColections() {
// lock everything to eliminate in-progress calls // lock everything to eliminate in-progress calls
@@ -52,50 +59,48 @@ func flushColections() {
} }
// Periodically flushes CollectionFactory to free up memory used by // Periodically flushes CollectionFactory to free up memory used by
// collections, flushing caches. If the two channels are provided, // collections, flushing caches.
// they are used to acquire and release the database.
// //
// Should be run in goroutine! // Should be run in goroutine!
func cacheFlusher(requests chan int, acks chan error) { func cacheFlusher() {
ticker := time.Tick(15 * time.Minute) ticker := time.Tick(15 * time.Minute)
for { for {
<-ticker <-ticker
// if aptly API runs in -no-lock mode, flushColections()
// caches are flushed when DB is closed anyway, no need
// to flush them here
if requests == nil {
flushColections()
}
} }
} }
// Acquire database lock and release it when not needed anymore. Two // Acquire database lock and release it when not needed anymore.
// channels must be provided. The first one is to receive requests to
// acquire/release the database and the second one is to send acks.
// //
// Should be run in a goroutine! // Should be run in a goroutine!
func acquireDatabase(requests chan int, acks chan error) { func acquireDatabase(requests <-chan dbRequest) {
clients := 0 clients := 0
for { for request := range requests {
request := <-requests var err error
switch request {
switch request.kind {
case acquiredb: case acquiredb:
if clients == 0 { if clients == 0 {
acks <- context.ReOpenDatabase() err = context.ReOpenDatabase()
} else { }
acks <- nil
request.err <- err
if err == nil {
clients++
} }
clients++
case releasedb: case releasedb:
clients-- clients--
if clients == 0 { if clients == 0 {
flushColections() flushColections()
acks <- context.CloseDatabase() err = context.CloseDatabase()
} else { } else {
acks <- nil err = nil
} }
request.err <- err
} }
} }
} }
+13 -13
View File
@@ -20,35 +20,35 @@ func Router(c *ctx.AptlyContext) http.Handler {
// We use a goroutine to count the number of // We use a goroutine to count the number of
// concurrent requests. When no more requests are // concurrent requests. When no more requests are
// running, we close the database to free the lock. // running, we close the database to free the lock.
requests := make(chan int) requests := make(chan dbRequest)
acks := make(chan error)
go acquireDatabase(requests, acks) go acquireDatabase(requests)
go cacheFlusher(requests, acks)
router.Use(func(c *gin.Context) { router.Use(func(c *gin.Context) {
var err error var err error
requests <- acquiredb errCh := make(chan error)
requests <- dbRequest{acquiredb, errCh}
err = <-errCh
if err != nil {
c.Fail(500, err)
return
}
defer func() { defer func() {
requests <- releasedb requests <- dbRequest{releasedb, errCh}
err = <-acks err = <-errCh
if err != nil { if err != nil {
c.Fail(500, err) c.Fail(500, err)
} }
}() }()
err = <-acks
if err != nil {
c.Fail(500, err)
return
}
c.Next() c.Next()
}) })
} else { } else {
go cacheFlusher(nil, nil) go cacheFlusher()
} }
root := router.Group("/api") root := router.Group("/api")
+1
View File
@@ -111,6 +111,7 @@ package environment to new version.`,
}, },
} }
cmd.Flag.Int("db-open-attempts", 10, "number of attempts to open DB if it's locked by other instance")
cmd.Flag.Bool("dep-follow-suggests", false, "when processing dependencies, follow Suggests") cmd.Flag.Bool("dep-follow-suggests", false, "when processing dependencies, follow Suggests")
cmd.Flag.Bool("dep-follow-source", false, "when processing dependencies, follow from binary to Source packages") cmd.Flag.Bool("dep-follow-source", false, "when processing dependencies, follow from binary to Source packages")
cmd.Flag.Bool("dep-follow-recommends", false, "when processing dependencies, follow Recommends") cmd.Flag.Bool("dep-follow-recommends", false, "when processing dependencies, follow Recommends")
+27 -22
View File
@@ -3,6 +3,7 @@ package context
import ( import (
"fmt" "fmt"
"math/rand"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@@ -238,13 +239,34 @@ func (context *AptlyContext) _database() (database.Storage, error) {
if context.database == nil { if context.database == nil {
var err error var err error
context.database, err = database.OpenDB(context.dbPath()) context.database, err = database.NewDB(context.dbPath())
if err != nil { if err != nil {
return nil, fmt.Errorf("can't open database: %s", err) return nil, fmt.Errorf("can't instanciate database: %s", err)
} }
} }
return context.database, nil tries := context.flags.Lookup("db-open-attempts").Value.Get().(int)
const BaseDelay = 10 * time.Second
const Jitter = 1 * time.Second
for ; tries >= 0; tries-- {
err := context.database.Open()
if err == nil || !strings.Contains(err.Error(), "resource temporarily unavailable") {
return context.database, err
}
if tries > 0 {
delay := time.Duration(rand.NormFloat64()*float64(Jitter) + float64(BaseDelay))
if delay < 0 {
delay = time.Second
}
context._progress().Printf("Unable to open database, sleeping %s, attempts left %d...\n", delay, tries)
time.Sleep(delay)
}
}
return nil, fmt.Errorf("unable to reopen the DB, maximum number of retries reached")
} }
// CloseDatabase closes the db temporarily // CloseDatabase closes the db temporarily
@@ -261,26 +283,9 @@ func (context *AptlyContext) CloseDatabase() error {
// ReOpenDatabase reopens the db after close // ReOpenDatabase reopens the db after close
func (context *AptlyContext) ReOpenDatabase() error { func (context *AptlyContext) ReOpenDatabase() error {
context.Lock() _, err := context.Database()
defer context.Unlock()
if context.database == nil { return err
return nil
}
const MaxTries = 10
const Delay = 10 * time.Second
for try := 0; try < MaxTries; try++ {
err := context.database.ReOpen()
if err == nil || !strings.Contains(err.Error(), "resource temporarily unavailable") {
return err
}
context._progress().Printf("Unable to reopen database, sleeping %s\n", Delay)
<-time.After(Delay)
}
return fmt.Errorf("unable to reopen the DB, maximum number of retries reached")
} }
// CollectionFactory builds factory producing all kinds of collections // CollectionFactory builds factory producing all kinds of collections
+13 -7
View File
@@ -32,8 +32,8 @@ type Storage interface {
ProcessByPrefix(prefix []byte, proc StorageProcessor) error ProcessByPrefix(prefix []byte, proc StorageProcessor) error
KeysByPrefix(prefix []byte) [][]byte KeysByPrefix(prefix []byte) [][]byte
FetchByPrefix(prefix []byte) [][]byte FetchByPrefix(prefix []byte) [][]byte
Open() error
Close() error Close() error
ReOpen() error
StartBatch() StartBatch()
FinishBatch() error FinishBatch() error
CompactDB() error CompactDB() error
@@ -66,13 +66,19 @@ func internalOpen(path string, throttleCompaction bool) (*leveldb.DB, error) {
return leveldb.OpenFile(path, o) return leveldb.OpenFile(path, o)
} }
// OpenDB opens (creates) LevelDB database // NewDB creates new instance of DB, but doesn't open it (yet)
func OpenDB(path string) (Storage, error) { func NewDB(path string) (Storage, error) {
db, err := internalOpen(path, false) return &levelDB{path: path}, nil
}
// NewOpenDB creates new instance of DB and opens it
func NewOpenDB(path string) (Storage, error) {
db, err := NewDB(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &levelDB{db: db, path: path}, nil
return db, db.Open()
} }
// RecoverDB recovers LevelDB database from corruption // RecoverDB recovers LevelDB database from corruption
@@ -215,8 +221,8 @@ func (l *levelDB) Close() error {
return err return err
} }
// Reopen tries to re-open the database // Reopen tries to open (re-open) the database
func (l *levelDB) ReOpen() error { func (l *levelDB) Open() error {
if l.db != nil { if l.db != nil {
return nil return nil
} }
+3 -3
View File
@@ -22,7 +22,7 @@ func (s *LevelDBSuite) SetUpTest(c *C) {
var err error var err error
s.path = c.MkDir() s.path = c.MkDir()
s.db, err = OpenDB(s.path) s.db, err = NewOpenDB(s.path)
c.Assert(err, IsNil) c.Assert(err, IsNil)
} }
@@ -46,7 +46,7 @@ func (s *LevelDBSuite) TestRecoverDB(c *C) {
err = RecoverDB(s.path) err = RecoverDB(s.path)
c.Check(err, IsNil) c.Check(err, IsNil)
s.db, err = OpenDB(s.path) s.db, err = NewOpenDB(s.path)
c.Check(err, IsNil) c.Check(err, IsNil)
result, err := s.db.Get(key) result, err := s.db.Get(key)
@@ -223,7 +223,7 @@ func (s *LevelDBSuite) TestReOpen(c *C) {
err = s.db.Close() err = s.db.Close()
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = s.db.ReOpen() err = s.db.Open()
c.Assert(err, IsNil) c.Assert(err, IsNil)
result, err := s.db.Get(key) result, err := s.db.Get(key)
+1 -1
View File
@@ -22,7 +22,7 @@ func (s *ChecksumCollectionSuite) SetUpTest(c *C) {
SHA1: "da39a3ee5e6b4b0d3255bfef95601890afd80709", SHA1: "da39a3ee5e6b4b0d3255bfef95601890afd80709",
SHA256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", SHA256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
} }
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.collection = NewChecksumCollection(s.db) s.collection = NewChecksumCollection(s.db)
} }
+2 -2
View File
@@ -18,7 +18,7 @@ type LocalRepoSuite struct {
var _ = Suite(&LocalRepoSuite{}) var _ = Suite(&LocalRepoSuite{})
func (s *LocalRepoSuite) SetUpTest(c *C) { func (s *LocalRepoSuite) SetUpTest(c *C) {
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.list = NewPackageList() s.list = NewPackageList()
s.list.Add(&Package{Name: "lib", Version: "1.7", Architecture: "i386"}) s.list.Add(&Package{Name: "lib", Version: "1.7", Architecture: "i386"})
s.list.Add(&Package{Name: "app", Version: "1.9", Architecture: "amd64"}) s.list.Add(&Package{Name: "app", Version: "1.9", Architecture: "amd64"})
@@ -83,7 +83,7 @@ type LocalRepoCollectionSuite struct {
var _ = Suite(&LocalRepoCollectionSuite{}) var _ = Suite(&LocalRepoCollectionSuite{})
func (s *LocalRepoCollectionSuite) SetUpTest(c *C) { func (s *LocalRepoCollectionSuite) SetUpTest(c *C) {
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.collection = NewLocalRepoCollection(s.db) s.collection = NewLocalRepoCollection(s.db)
s.list = NewPackageList() s.list = NewPackageList()
+1 -1
View File
@@ -17,7 +17,7 @@ var _ = Suite(&PackageCollectionSuite{})
func (s *PackageCollectionSuite) SetUpTest(c *C) { func (s *PackageCollectionSuite) SetUpTest(c *C) {
s.p = NewPackageFromControlFile(packageStanza.Copy()) s.p = NewPackageFromControlFile(packageStanza.Copy())
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.collection = NewPackageCollection(s.db) s.collection = NewPackageCollection(s.db)
} }
+3 -3
View File
@@ -87,7 +87,7 @@ var _ = Suite(&PublishedRepoSuite{})
func (s *PublishedRepoSuite) SetUpTest(c *C) { func (s *PublishedRepoSuite) SetUpTest(c *C) {
s.SetUpPackages() s.SetUpPackages()
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.factory = NewCollectionFactory(s.db) s.factory = NewCollectionFactory(s.db)
s.root = c.MkDir() s.root = c.MkDir()
@@ -449,7 +449,7 @@ type PublishedRepoCollectionSuite struct {
var _ = Suite(&PublishedRepoCollectionSuite{}) var _ = Suite(&PublishedRepoCollectionSuite{})
func (s *PublishedRepoCollectionSuite) SetUpTest(c *C) { func (s *PublishedRepoCollectionSuite) SetUpTest(c *C) {
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.factory = NewCollectionFactory(s.db) s.factory = NewCollectionFactory(s.db)
s.snapshotCollection = s.factory.SnapshotCollection() s.snapshotCollection = s.factory.SnapshotCollection()
@@ -640,7 +640,7 @@ type PublishedRepoRemoveSuite struct {
var _ = Suite(&PublishedRepoRemoveSuite{}) var _ = Suite(&PublishedRepoRemoveSuite{})
func (s *PublishedRepoRemoveSuite) SetUpTest(c *C) { func (s *PublishedRepoRemoveSuite) SetUpTest(c *C) {
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.factory = NewCollectionFactory(s.db) s.factory = NewCollectionFactory(s.db)
s.snapshotCollection = s.factory.SnapshotCollection() s.snapshotCollection = s.factory.SnapshotCollection()
-2
View File
@@ -395,6 +395,4 @@ func (l *PackageRefList) FilterLatestRefs() {
lastArch, lastName, lastVer = arch, name, ver lastArch, lastName, lastVer = arch, name, ver
} }
return
} }
+3 -3
View File
@@ -44,7 +44,7 @@ func (s *PackageRefListSuite) SetUpTest(c *C) {
} }
func (s *PackageRefListSuite) TestNewPackageListFromRefList(c *C) { func (s *PackageRefListSuite) TestNewPackageListFromRefList(c *C) {
db, _ := database.OpenDB(c.MkDir()) db, _ := database.NewOpenDB(c.MkDir())
coll := NewPackageCollection(db) coll := NewPackageCollection(db)
coll.Update(s.p1) coll.Update(s.p1)
coll.Update(s.p3) coll.Update(s.p3)
@@ -166,7 +166,7 @@ func (s *PackageRefListSuite) TestSubstract(c *C) {
} }
func (s *PackageRefListSuite) TestDiff(c *C) { func (s *PackageRefListSuite) TestDiff(c *C) {
db, _ := database.OpenDB(c.MkDir()) db, _ := database.NewOpenDB(c.MkDir())
coll := NewPackageCollection(db) coll := NewPackageCollection(db)
packages := []*Package{ packages := []*Package{
@@ -238,7 +238,7 @@ func (s *PackageRefListSuite) TestDiff(c *C) {
} }
func (s *PackageRefListSuite) TestMerge(c *C) { func (s *PackageRefListSuite) TestMerge(c *C) {
db, _ := database.OpenDB(c.MkDir()) db, _ := database.NewOpenDB(c.MkDir())
coll := NewPackageCollection(db) coll := NewPackageCollection(db)
packages := []*Package{ packages := []*Package{
+1 -1
View File
@@ -198,7 +198,7 @@ func (repo *RemoteRepo) IndexesRootURL() *url.URL {
if !repo.IsFlat() { if !repo.IsFlat() {
path = &url.URL{Path: fmt.Sprintf("dists/%s/", repo.Distribution)} path = &url.URL{Path: fmt.Sprintf("dists/%s/", repo.Distribution)}
} else { } else {
path = &url.URL{Path: fmt.Sprintf("%s", repo.Distribution)} path = &url.URL{Path: repo.Distribution}
} }
return repo.archiveRootURL.ResolveReference(path) return repo.archiveRootURL.ResolveReference(path)
+2 -2
View File
@@ -92,7 +92,7 @@ func (s *RemoteRepoSuite) SetUpTest(c *C) {
s.flat, _ = NewRemoteRepo("exp42", "http://repos.express42.com/virool/precise/", "./", []string{}, []string{}, false, false) s.flat, _ = NewRemoteRepo("exp42", "http://repos.express42.com/virool/precise/", "./", []string{}, []string{}, false, false)
s.downloader = http.NewFakeDownloader().ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/Release", exampleReleaseFile) s.downloader = http.NewFakeDownloader().ExpectResponse("http://mirror.yandex.ru/debian/dists/squeeze/Release", exampleReleaseFile)
s.progress = console.NewProgress() s.progress = console.NewProgress()
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.collectionFactory = NewCollectionFactory(s.db) s.collectionFactory = NewCollectionFactory(s.db)
s.packagePool = files.NewPackagePool(c.MkDir(), false) s.packagePool = files.NewPackagePool(c.MkDir(), false)
s.cs = files.NewMockChecksumStorage() s.cs = files.NewMockChecksumStorage()
@@ -615,7 +615,7 @@ type RemoteRepoCollectionSuite struct {
var _ = Suite(&RemoteRepoCollectionSuite{}) var _ = Suite(&RemoteRepoCollectionSuite{})
func (s *RemoteRepoCollectionSuite) SetUpTest(c *C) { func (s *RemoteRepoCollectionSuite) SetUpTest(c *C) {
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.collection = NewRemoteRepoCollection(s.db) s.collection = NewRemoteRepoCollection(s.db)
s.SetUpPackages() s.SetUpPackages()
} }
+1 -1
View File
@@ -112,7 +112,7 @@ type SnapshotCollectionSuite struct {
var _ = Suite(&SnapshotCollectionSuite{}) var _ = Suite(&SnapshotCollectionSuite{})
func (s *SnapshotCollectionSuite) SetUpTest(c *C) { func (s *SnapshotCollectionSuite) SetUpTest(c *C) {
s.db, _ = database.OpenDB(c.MkDir()) s.db, _ = database.NewOpenDB(c.MkDir())
s.collection = NewSnapshotCollection(s.db) s.collection = NewSnapshotCollection(s.db)
s.SetUpPackages() s.SetUpPackages()
+4
View File
@@ -1,7 +1,9 @@
package main package main
import ( import (
"math/rand"
"os" "os"
"time"
"github.com/smira/aptly/aptly" "github.com/smira/aptly/aptly"
"github.com/smira/aptly/cmd" "github.com/smira/aptly/cmd"
@@ -17,5 +19,7 @@ func main() {
aptly.Version = Version aptly.Version = Version
rand.Seed(time.Now().UnixNano())
os.Exit(cmd.Run(cmd.RootCommand(), os.Args[1:], true)) os.Exit(cmd.Run(cmd.RootCommand(), os.Args[1:], true))
} }
+5 -1
View File
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "APTLY" "1" "April 2017" "" "" .TH "APTLY" "1" "July 2017" "" ""
. .
.SH "NAME" .SH "NAME"
\fBaptly\fR \- Debian repository management tool \fBaptly\fR \- Debian repository management tool
@@ -392,6 +392,10 @@ list of architectures to consider during (comma\-separated), default to all avai
location of configuration file (default locations are /etc/aptly\.conf, ~/\.aptly\.conf) location of configuration file (default locations are /etc/aptly\.conf, ~/\.aptly\.conf)
. .
.TP .TP
\-\fBdb\-open\-attempts\fR=10
number of attempts to open DB if it\(cqs locked by other instance
.
.TP
\-\fBdep\-follow\-all\-variants\fR=false \-\fBdep\-follow\-all\-variants\fR=false
when processing dependencies, follow a & b if dependency is \(cqa|b\(cq when processing dependencies, follow a & b if dependency is \(cqa|b\(cq
. .
+4 -8
View File
@@ -1,10 +1,6 @@
package query package query
import ( import . "gopkg.in/check.v1"
"fmt"
. "gopkg.in/check.v1"
)
type LexerSuite struct { type LexerSuite struct {
} }
@@ -46,13 +42,13 @@ func (s *LexerSuite) TestConsume(c *C) {
func (s *LexerSuite) TestString(c *C) { func (s *LexerSuite) TestString(c *C) {
l, _ := lex("query", "package (<< 1.3)") l, _ := lex("query", "package (<< 1.3)")
c.Check(fmt.Sprintf("%s", l.Current()), Equals, "\"package\"") c.Check(l.Current().String(), Equals, "\"package\"")
l.Consume() l.Consume()
c.Check(fmt.Sprintf("%s", l.Current()), Equals, "(") c.Check(l.Current().String(), Equals, "(")
} }
func (s *LexerSuite) TestError(c *C) { func (s *LexerSuite) TestError(c *C) {
l, _ := lex("query", "'package") l, _ := lex("query", "'package")
c.Check(fmt.Sprintf("%s", l.Current()), Equals, "error: unexpected eof in quoted string") c.Check(l.Current().String(), Equals, "error: unexpected eof in quoted string")
} }
+1
View File
@@ -13,6 +13,7 @@ package environment to new version.
Options: Options:
-architectures="": list of architectures to consider during (comma-separated), default to all available -architectures="": list of architectures to consider during (comma-separated), default to all available
-config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)
-db-open-attempts=10: number of attempts to open DB if it's locked by other instance
-dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b' -dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b'
-dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-recommends=false: when processing dependencies, follow Recommends
-dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-source=false: when processing dependencies, follow from binary to Source packages
+1
View File
@@ -21,6 +21,7 @@ Use "aptly help <command>" for more information about a command.
Options: Options:
-architectures="": list of architectures to consider during (comma-separated), default to all available -architectures="": list of architectures to consider during (comma-separated), default to all available
-config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)
-db-open-attempts=10: number of attempts to open DB if it's locked by other instance
-dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b' -dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b'
-dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-recommends=false: when processing dependencies, follow Recommends
-dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-source=false: when processing dependencies, follow from binary to Source packages
@@ -15,6 +15,7 @@ Example:
Options: Options:
-architectures="": list of architectures to consider during (comma-separated), default to all available -architectures="": list of architectures to consider during (comma-separated), default to all available
-config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)
-db-open-attempts=10: number of attempts to open DB if it's locked by other instance
-dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b' -dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b'
-dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-recommends=false: when processing dependencies, follow Recommends
-dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-source=false: when processing dependencies, follow from binary to Source packages
+1
View File
@@ -6,6 +6,7 @@ aptly mirror create - create new mirror
Options: Options:
-architectures="": list of architectures to consider during (comma-separated), default to all available -architectures="": list of architectures to consider during (comma-separated), default to all available
-config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)
-db-open-attempts=10: number of attempts to open DB if it's locked by other instance
-dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b' -dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b'
-dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-recommends=false: when processing dependencies, follow Recommends
-dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-source=false: when processing dependencies, follow from binary to Source packages
+1
View File
@@ -17,6 +17,7 @@ Use "mirror help <command>" for more information about a command.
Options: Options:
-architectures="": list of architectures to consider during (comma-separated), default to all available -architectures="": list of architectures to consider during (comma-separated), default to all available
-config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)
-db-open-attempts=10: number of attempts to open DB if it's locked by other instance
-dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b' -dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b'
-dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-recommends=false: when processing dependencies, follow Recommends
-dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-source=false: when processing dependencies, follow from binary to Source packages
+1
View File
@@ -17,6 +17,7 @@ Use "mirror help <command>" for more information about a command.
Options: Options:
-architectures="": list of architectures to consider during (comma-separated), default to all available -architectures="": list of architectures to consider during (comma-separated), default to all available
-config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)
-db-open-attempts=10: number of attempts to open DB if it's locked by other instance
-dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b' -dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b'
-dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-recommends=false: when processing dependencies, follow Recommends
-dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-source=false: when processing dependencies, follow from binary to Source packages
+1
View File
@@ -7,6 +7,7 @@ aptly mirror create - create new mirror
Options: Options:
-architectures="": list of architectures to consider during (comma-separated), default to all available -architectures="": list of architectures to consider during (comma-separated), default to all available
-config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf) -config="": location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)
-db-open-attempts=10: number of attempts to open DB if it's locked by other instance
-dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b' -dep-follow-all-variants=false: when processing dependencies, follow a & b if dependency is 'a|b'
-dep-follow-recommends=false: when processing dependencies, follow Recommends -dep-follow-recommends=false: when processing dependencies, follow Recommends
-dep-follow-source=false: when processing dependencies, follow from binary to Source packages -dep-follow-source=false: when processing dependencies, follow from binary to Source packages
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -15,5 +15,5 @@ Description: Long Term Support for Debian 7
Label: Debian-Security Label: Debian-Security
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.0 Version: 7.0
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -17,5 +17,5 @@ Description: Long Term Support for Debian 7
Label: Debian-Security Label: Debian-Security
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.0 Version: 7.0
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
@@ -15,5 +15,5 @@ Description: Long Term Support for Debian 7
Label: Debian-Security Label: Debian-Security
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.0 Version: 7.0
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
+2 -2
View File
@@ -11,10 +11,10 @@ Information from release file:
Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc
Codename: wheezy Codename: wheezy
Components: main contrib non-free Components: main contrib non-free
Date: Sat, 04 Jun 2016 11:47:54 UTC Date: Sat, 17 Jun 2017 08:55:32 UTC
Description: Debian 7.11 Released 04 June 2016 Description: Debian 7.11 Released 04 June 2016
Label: Debian Label: Debian
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.11 Version: 7.11
+1 -1
View File
@@ -17,5 +17,5 @@ Description: Long Term Support for Debian 7
Label: Debian-Security Label: Debian-Security
Origin: Debian Origin: Debian
Suite: oldstable Suite: oldoldstable
Version: 7.0 Version: 7.0