Example #1
0
func (self *CoordinatorImpl) ReplicateWrite(request *protocol.Request) error {
	id := atomic.AddUint32(&self.requestId, uint32(1))
	request.Id = &id
	location := common.RingLocation(request.Database, request.Series.Name, request.Series.Points[0].Timestamp)
	replicas := self.clusterConfiguration.GetServersByRingLocation(request.Database, &location)
	request.Type = &replicateWrite
	self.sendRequestToReplicas(request, replicas)
	return nil
}
Example #2
0
func (self *CoordinatorImpl) ReplicateDelete(request *protocol.Request) error {
	id := atomic.AddUint32(&self.requestId, uint32(1))
	request.Id = &id
	server := self.clusterConfiguration.GetServerById(request.OwnerServerId)
	_, replicas := self.clusterConfiguration.GetReplicas(server, request.Database)
	request.Type = &replicateDelete
	self.sendRequestToReplicas(request, replicas)
	return nil
}
func (self *LevelDbDatastore) LogRequestAndAssignSequenceNumber(request *protocol.Request, replicationFactor *uint8, ownerServerId *uint32) error {
	// log to this key structure on a different DB sharded by day: <cluster version><owner id><sequence server id><replication sequence>
	var numberKey []byte
	if request.SequenceNumber == nil {
		sequenceNumber, err := self.AtomicIncrement(self.keyForOwnerAndServerSequenceNumber(request.ClusterVersion, replicationFactor, ownerServerId, request.OriginatingServerId), 1)
		if err != nil {
			return err
		}
		request.SequenceNumber = &sequenceNumber
	} else {
		// this is for a replicated write, ensure that it's the next in line for this owner and server
		name := self.keyForOwnerAndServerSequenceNumber(request.ClusterVersion, replicationFactor, ownerServerId, request.OriginatingServerId)
		numberKey = append(ATOMIC_INCREMENT_PREFIX, []byte(name)...)
		numberBytes, err := self.db.Get(self.readOptions, numberKey)
		if err != nil {
			return err
		}
		previousSequenceNumber := self.bytesToCurrentNumber(numberBytes)
		if previousSequenceNumber+uint64(1) != *request.SequenceNumber {
			return SequenceMissingRequestsError{"Missing requests between last seen and this one.", previousSequenceNumber}
		}
	}

	self.requestLogLock.RLock()
	requestLog := self.currentRequestLog
	self.requestLogLock.RUnlock()

	// proxied writes should be logged as replicated ones. That's what is expected if they're replayed later
	if *request.Type == protocol.Request_PROXY_WRITE {
		request.Type = &replicateWrite
	}

	data, err := request.Encode()
	if err != nil {
		return err
	}

	key := self.requestLogKey(request.ClusterVersion, request.OriginatingServerId, ownerServerId, request.SequenceNumber, replicationFactor)
	err = requestLog.db.Put(self.writeOptions, key, data)
	if err != nil {
		return err
	}
	if numberKey != nil {
		currentNumberBuffer := bytes.NewBuffer(make([]byte, 0, 8))
		binary.Write(currentNumberBuffer, binary.BigEndian, *request.SequenceNumber)
		self.db.Put(self.writeOptions, numberKey, currentNumberBuffer.Bytes())
	}
	return nil
}
Example #4
0
func (self *LevelDbDatastore) LogRequestAndAssignSequenceNumber(request *protocol.Request, replicationFactor *uint8, ownerServerId *uint32) error {
	// log to this key structure on a different DB sharded by day: <cluster version><owner id><sequence server id><replication sequence>
	updateSequenceNumber := false
	if request.SequenceNumber == nil {
		sequenceNumber, err := self.AtomicIncrement(self.keyForOwnerAndServerSequenceNumber(request.ClusterVersion, replicationFactor, ownerServerId, request.OriginatingServerId), 1)
		if err != nil {
			return err
		}
		request.SequenceNumber = &sequenceNumber
	} else {
		updateSequenceNumber = true
		previousSequenceNumber, err := self.CurrentSequenceNumber(request.ClusterVersion, replicationFactor, ownerServerId, request.OriginatingServerId)
		if err != nil {
			return err
		}
		// Do a less than comparison because it's ok if we're just getting the same write again. As long as we haven't missed one.
		if previousSequenceNumber+uint64(1) < *request.SequenceNumber {
			log.Warn("MISSING REQUESTS: %d, %d", previousSequenceNumber, *request.SequenceNumber)
			return SequenceMissingRequestsError{"Missing requests between last seen and this one.", previousSequenceNumber, *request.SequenceNumber}
		}
	}

	self.requestLogLock.RLock()
	requestLog := self.currentRequestLog
	self.requestLogLock.RUnlock()

	// proxied writes should be logged as replicated ones. That's what is expected if they're replayed later
	if *request.Type == protocol.Request_PROXY_WRITE {
		request.Type = &replicateWrite
	}

	data, err := request.Encode()
	if err != nil {
		return err
	}

	key := NewWALKey(request.ClusterVersion, request.OriginatingServerId, ownerServerId, request.SequenceNumber, replicationFactor)
	err = requestLog.db.Put(self.writeOptions, key, data)
	if err != nil {
		return err
	}
	if updateSequenceNumber {
		return self.updateSequenceNumber(request.ClusterVersion, replicationFactor, ownerServerId, request.OriginatingServerId, *request.SequenceNumber)
	}
	return nil
}