| 305 | } |
| 306 | |
| 307 | func (context *AptlyContext) _database() (database.Storage, error) { |
| 308 | if context.database == nil { |
| 309 | var err error |
| 310 | switch context.config().DatabaseBackend.Type { |
| 311 | case "leveldb": |
| 312 | dbPath := filepath.Join(context.config().GetRootDir(), "db") |
| 313 | if len(context.config().DatabaseBackend.DBPath) != 0 { |
| 314 | dbPath = context.config().DatabaseBackend.DBPath |
| 315 | } |
| 316 | context.database, err = goleveldb.NewDB(dbPath) |
| 317 | case "etcd": |
| 318 | context.database, err = etcddb.NewDB(context.config().DatabaseBackend.URL) |
| 319 | default: |
| 320 | context.database, err = goleveldb.NewDB(context.dbPath()) |
| 321 | } |
| 322 | if err != nil { |
| 323 | return nil, fmt.Errorf("can't instantiate database: %s", err) |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | var tries int |
| 328 | if context.config().DatabaseOpenAttempts == -1 { |
| 329 | tries = context.flags.Lookup("db-open-attempts").Value.Get().(int) |
| 330 | } else { |
| 331 | tries = context.config().DatabaseOpenAttempts |
| 332 | } |
| 333 | |
| 334 | const BaseDelay = 10 * time.Second |
| 335 | const Jitter = 1 * time.Second |
| 336 | |
| 337 | for ; tries >= 0; tries-- { |
| 338 | err := context.database.Open() |
| 339 | if err == nil || !strings.Contains(err.Error(), "resource temporarily unavailable") { |
| 340 | return context.database, err |
| 341 | } |
| 342 | |
| 343 | if tries > 0 { |
| 344 | delay := time.Duration(rand.NormFloat64()*float64(Jitter) + float64(BaseDelay)) |
| 345 | if delay < 0 { |
| 346 | delay = time.Second |
| 347 | } |
| 348 | |
| 349 | context._progress().PrintfStdErr("Unable to open database, sleeping %s, attempts left %d...\n", delay, tries) |
| 350 | time.Sleep(delay) |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | return nil, fmt.Errorf("unable to reopen the DB, maximum number of retries reached") |
| 355 | } |
| 356 | |
| 357 | // CloseDatabase closes the db temporarily |
| 358 | func (context *AptlyContext) CloseDatabase() error { |