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 }
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 }
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 }