// CreateRange allocates a new range ID and stores range metadata. // On success, returns the new range. func (s *Store) CreateRange(startKey, endKey engine.Key, replicas []proto.Replica) (*Range, error) { rangeID, err := engine.Increment(s.engine, engine.KeyLocalRangeIDGenerator, 1) if err != nil { return nil, err } if ok, _ := engine.GetProto(s.engine, makeRangeKey(rangeID), nil); ok { return nil, util.Error("newly allocated range ID already in use") } // RangeMetadata is stored local to this store only. It is neither // replicated via raft nor available via the global kv store. meta := &proto.RangeMetadata{ ClusterID: s.Ident.ClusterID, RangeID: rangeID, RangeDescriptor: proto.RangeDescriptor{ StartKey: startKey, EndKey: endKey, Replicas: replicas, }, } err = engine.PutProto(s.engine, makeRangeKey(rangeID), meta) if err != nil { return nil, err } rng := NewRange(meta, s.clock, s.engine, s.allocator, s.gossip, s) rng.Start() s.mu.Lock() defer s.mu.Unlock() s.ranges[rangeID] = rng return rng, nil }
// InternalSnapshotCopy scans the key range specified by start key through // end key up to some maximum number of results from the given snapshot_id. // It will create a snapshot if snapshot_id is empty. func (r *Range) InternalSnapshotCopy(args *proto.InternalSnapshotCopyRequest, reply *proto.InternalSnapshotCopyResponse) { if len(args.SnapshotId) == 0 { candidateID, err := engine.Increment(r.engine, engine.KeyLocalSnapshotIDGenerator, 1) if err != nil { reply.SetGoError(err) return } snapshotID := strconv.FormatInt(candidateID, 10) err = r.engine.CreateSnapshot(snapshotID) if err != nil { reply.SetGoError(err) return } args.SnapshotId = snapshotID } kvs, err := r.engine.ScanSnapshot(args.Key, args.EndKey, args.MaxResults, args.SnapshotId) if err != nil { reply.SetGoError(err) return } if len(kvs) == 0 { err = r.engine.ReleaseSnapshot(args.SnapshotId) } reply.Rows = kvs reply.SnapshotId = args.SnapshotId reply.SetGoError(err) }
// createSnapshot creates a new snapshot, named using an internal counter. func (r *Range) createSnapshot() (string, error) { candidateID, err := engine.Increment(r.engine, engine.KeyLocalSnapshotIDGenerator, 1) if err != nil { return "", err } snapshotID := strconv.FormatInt(candidateID, 10) err = r.engine.CreateSnapshot(snapshotID) return snapshotID, err }
// TestIDAllocatorNegativeValue creates an ID allocator against an // increment key which is preset to a negative value. We verify that // the id allocator makes a double-alloc to make up the difference // and push the id allocation into positive integers. func TestIDAllocatorNegativeValue(t *testing.T) { store, _ := createTestStore(false, t) // Increment our key to a negative value. newValue, err := engine.Increment(store.engine, engine.KeyRaftIDGenerator, -1024) if err != nil { t.Fatal(err) } if newValue != -1024 { t.Errorf("expected new value to be -1024; got %d", newValue) } idAlloc := NewIDAllocator(engine.KeyRaftIDGenerator, store.db, 2, 10) value := idAlloc.Allocate() if value != 2 { t.Errorf("expected id allocation to have value 2; got %d", value) } }
// Increment increments the value (interpreted as varint64 encoded) and // returns the newly incremented value (encoded as varint64). If no value // exists for the key, zero is incremented. func (r *Range) Increment(args *proto.IncrementRequest, reply *proto.IncrementResponse) { value, err := engine.Increment(r.engine, args.Key, args.Increment) reply.NewValue = value reply.SetGoError(err) }
// Increment increments the value (interpreted as varint64 encoded) and // returns the newly incremented value (encoded as varint64). If no value // exists for the key, zero is incremented. func (r *Range) Increment(args *IncrementRequest, reply *IncrementResponse) { reply.NewValue, reply.Error = engine.Increment(r.engine, args.Key, args.Increment) }