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 #2
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
}
Example #3
0
func (self *DatastoreMock) LogRequestAndAssignSequenceNumber(request *protocol.Request, replicationFactor *uint8, ownerServerId *uint32) error {
	id := uint64(1)
	request.SequenceNumber = &id
	return nil
}