Esempio n. 1
0
func RunNewPusher(schedule RunSchedule, name string, c *api.SyncGatewayClient, channel string, size int, sendAttachment bool, dist DocSizeDistribution, seqId, sleepTime int, wg *sync.WaitGroup) {
	defer wg.Done()

	glExpvars.Add("user_active", 1)
	// if config contains DocSize, always generate this fixed document size
	if size != 0 {
		dist = DocSizeDistribution{
			&DocSizeDistributionElement{
				Prob:    100,
				MinSize: size,
				MaxSize: size,
			},
		}
	}

	docSizeGenerator, err := NewDocSizeGenerator(dist)
	if err != nil {
		Log("Error starting docuemnt pusher: %v", err)
		return
	}

	docIterator := DocIterator(seqId*DocsPerUser, (seqId+1)*DocsPerUser, docSizeGenerator, channel, sendAttachment)

	docsToSend := 0

	online := false
	scheduleIndex := 0
	start := time.Now()
	timer := time.NewTimer(schedule[scheduleIndex].start)
	var lastSend time.Time
	var pushTimer <-chan time.Time

	for {
		select {
		case <-timer.C:
			// timer went off, transition modes
			timeOffset := time.Since(start)
			if online {
				glExpvars.Add("user_awake", -1)
				online = false
				pushTimer = nil
				scheduleIndex++
				if scheduleIndex < len(schedule) {
					nextOnIn := schedule[scheduleIndex].start - timeOffset
					timer = time.NewTimer(nextOnIn)
					Log("Pusher %s going offline, next on at %v", name, nextOnIn)
					if nextOnIn < 0 {
						log.Printf("WARNING: pusher %s negative timer nextOnTime, exiting", name)
						return
					}
				}
			} else {
				glExpvars.Add("user_awake", 1)
				online = true
				pushTimer = time.NewTimer(0).C
				if schedule[scheduleIndex].end != -1 {
					nextOffIn := schedule[scheduleIndex].end - timeOffset
					timer = time.NewTimer(nextOffIn)
					Log("Pusher %s going online, next off at %v", name, nextOffIn)
					if nextOffIn < 0 {
						log.Printf("WARNING: pusher %s negative timer nextOffTime, exiting", name)
						glExpvars.Add("user_awake", -1)
						return
					}
				}
			}
		case <-pushTimer:

			if lastSend.IsZero() {
				docsToSend = 1
			} else {
				//log.Printf("time since last %v", time.Since(lastSend))
				//log.Printf("durration: %v", (time.Duration(sleepTime) * time.Millisecond))
				docsToSend = int(time.Since(lastSend) / (time.Duration(sleepTime) * time.Millisecond))
				//log.Printf("docs to send: %v", docsToSend)
			}
			if docsToSend > 0 {
				Log("Pusher online sending %d docs", docsToSend)
				// generage docs
				docs := make([]api.Doc, docsToSend)
				for i := 0; i < docsToSend; i++ {
					nextDoc := <-docIterator
					docs[i] = nextDoc
				}
				// send revs diff
				revsDiff := map[string][]string{}
				for _, doc := range docs {
					revsDiff[doc.Id] = []string{doc.Rev}
				}

				c.PostRevsDiff(revsDiff)
				// set the creation time in doc id
				nowString := "_" + strconv.Itoa(int(time.Now().UnixNano()/1e6)) // time since epoch in ms as string
				for i, doc := range docs {
					doc.Id = doc.Id + nowString
					docs[i] = doc
				}
				// send bulk docs
				bulkDocs := map[string]interface{}{
					"docs":      docs,
					"new_edits": false,
				}
				Log("Pusher #%d saved %d docs", seqId, docsToSend)
				if c.PostBulkDocs(bulkDocs) {
					glExpvars.Add("total_doc_pushed", int64(docsToSend))
				} else {
					glExpvars.Add("total_doc_failed_to_push", int64(docsToSend))
				}
				docsToSend = 0
				lastSend = time.Now()
				// reset the timer
				pushTimer = time.NewTimer(time.Duration(sleepTime) * time.Millisecond).C
			}
		}
	}

	glExpvars.Add("user_active", -1)

}