Esempio n. 1
0
// Open creates options and opens the database. If the database
// doesn't yet exist at the specified directory, one is initialized
// from scratch. The RocksDB Open and Close methods are reference
// counted such that subsequent Open calls to an already opened
// RocksDB instance only bump the reference count. The RocksDB is only
// closed when a sufficient number of Close calls are performed to
// bring the reference count down to 0.
func (r *RocksDB) Open() error {
	if r.rdb != nil {
		return nil
	}

	if r.memtableBudget < minMemtableBudget {
		return util.Errorf("memtable budget must be at least %s: %s",
			humanize.IBytes(minMemtableBudget), humanizeutil.IBytes(r.memtableBudget))
	}

	var ver storageVersion
	if len(r.dir) != 0 {
		log.Infof("opening rocksdb instance at %q", r.dir)

		// Check the version number.
		var err error
		if ver, err = getVersion(r.dir); err != nil {
			return err
		}
		if ver < versionMinimum || ver > versionCurrent {
			// Instead of an error, we should call a migration if possible when
			// one is needed immediately following the DBOpen call.
			return fmt.Errorf("incompatible rocksdb data version, current:%d, on disk:%d, minimum:%d",
				versionCurrent, ver, versionMinimum)
		}
	} else {
		log.Infof("opening in memory rocksdb instance")

		// In memory dbs are always current.
		ver = versionCurrent
	}

	status := C.DBOpen(&r.rdb, goToCSlice([]byte(r.dir)),
		C.DBOptions{
			cache_size:      C.uint64_t(r.cacheSize),
			memtable_budget: C.uint64_t(r.memtableBudget),
			block_size:      C.uint64_t(envutil.EnvOrDefaultBytes("rocksdb_block_size", defaultBlockSize)),
			wal_ttl_seconds: C.uint64_t(envutil.EnvOrDefaultDuration("rocksdb_wal_ttl", 0).Seconds()),
			allow_os_buffer: C.bool(true),
			logging_enabled: C.bool(log.V(3)),
		})
	if err := statusToError(status); err != nil {
		return util.Errorf("could not open rocksdb instance: %s", err)
	}

	// Update or add the version file if needed.
	if ver < versionCurrent {
		if err := writeVersionFile(r.dir); err != nil {
			return err
		}
	}

	// Start a goroutine that will finish when the underlying handle
	// is deallocated. This is used to check a leak in tests.
	go func() {
		<-r.deallocated
	}()
	r.stopper.AddCloser(r)
	return nil
}
Esempio n. 2
0
// newBookie creates a reservations system and starts its timeout queue.
func newBookie(
	clock *hlc.Clock,
	stopper *stop.Stopper,
	metrics *storeMetrics,
	reservationTimeout time.Duration,
) *bookie {
	b := &bookie{
		clock:              clock,
		metrics:            metrics,
		reservationTimeout: reservationTimeout,
		maxReservations:    envutil.EnvOrDefaultInt("max_reservations", defaultMaxReservations),
		maxReservedBytes:   envutil.EnvOrDefaultBytes("max_reserved_bytes", defaultMaxReservedBytes),
	}
	b.mu.reservationsByRangeID = make(map[roachpb.RangeID]*reservation)
	b.start(stopper)
	return b
}