func (mut *mutation) executeObjectOperation(db *Db, replay bool) (err os.Error) { vs := db.viewstateManager.getViewState(mut.token, mut.vs) if vs == nil { log.Warning("Viewstate not found to execute object mutation: token=%d, vs=%d", mut.token, mut.vs) return os.NewError(fmt.Sprintf("Unknown ViewState to execute object operation on (token=%d, vs=%d)", mut.token, mut.vs)) } container := mut.op.getContainer() key := mut.op.getKey() newObj := object{ segment: mut.seg.id, position: mut.segEntry.relativePosition(), } // unless we are replaying, we mutate the object if !replay { curObj, err := vs.getObject(container, key, true) if err != nil { return err } newObj.data = curObj.data // TODO: CLONE DATA!! err = mut.op.mutateObject(&newObj) } vs.setObject(container, key, newObj) return }
func (comm *Comm) startMessageTracker() { // track messages for { if comm.running { for hash, msgTrack := range comm.messageTrackers { diff := int((time.Nanoseconds() - msgTrack.lastTime) / 1000000) // TODO: Use the right retry delay // check the acknowledgement if msgTrack.message.Timeout != 0 && diff >= msgTrack.message.Timeout { comm.trackersMutex.Lock() msgTrack, found := comm.messageTrackers[hash] // make sure the message tracker is still there // we may have received an ack while locking if found { msgTrack.retries++ msgTrack.lastTime = time.Nanoseconds() + int64(msgTrack.message.RetryDelay*1000*1000) if msgTrack.retries > msgTrack.message.Retries { log.Warning("%d: Comm: Timeout for message %s after %d ms. Not retrying!\n", comm.Cluster.MyNode.Id, msgTrack.message, diff) // remove from acknowledgable messages list comm.messageTrackers[hash] = nil, false go func() { if msgTrack.message.OnTimeout != nil { msgTrack.message.OnTimeout(true) } if msgTrack.message.LastTimeoutAsError { msgTrack.message.OnError(msgTrack.message, ErrorTimeout) } msgTrack.message.Release() }() } else { go func() { retry := true handled := false if msgTrack.message.OnTimeout != nil { retry, handled = msgTrack.message.OnTimeout(false) } if retry && !handled { seekable, _ := msgTrack.message.DataIsSeekable() if msgTrack.message.Data != nil && !seekable { log.Error("%d: Comm: Cannot automatically retry message %s after %d ms because data is not seekable!", comm.Cluster.MyNode.Id, msgTrack.message, diff) } else { log.Warning("%d: Comm: Timeout for message %s after %d ms. Retrying %d of %d\n", comm.Cluster.MyNode.Id, msgTrack.message, diff, msgTrack.retries, msgTrack.message.Retries) comm.SendNode(msgTrack.destination, msgTrack.message) } } }() } } comm.trackersMutex.Unlock() // cleanup for OnError and OnResponse tracked messages } else if diff >= TRACKER_CLEAN_TIME { comm.trackersMutex.Lock() _, found := comm.messageTrackers[hash] // make sure the message is still there // we may have received an error or response // while waiting for the locking if found { comm.messageTrackers[hash] = nil, false } comm.trackersMutex.Unlock() } } } // sleep time.Sleep(TRACKER_LOOP_SLEEP * 1000 * 1000) } }