Exemple #1
0
// Adds a new change to a channel log.
func (db *Database) AddToChangeLog(channelName string, entry channels.LogEntry, parentRevID string) error {
	if channelName == "*" && !EnableStarChannelLog {
		return nil
	}
	var fullUpdate bool
	var removedCount int
	fullUpdateAttempts := 0

	logDocID := channelLogDocID(channelName)
	err := db.Bucket.WriteUpdate(logDocID, 0, func(currentValue []byte) ([]byte, walrus.WriteOptions, error) {
		// (Be careful: this block can be invoked multiple times if there are races!)
		// Should I do a full update of the change log, removing older entries to limit its size?
		// This has to be done occasionaly, but it's slower than simply appending to it. This
		// test is a heuristic that seems to strike a good balance in practice:
		fullUpdate = AlwaysCompactChangeLog ||
			(len(currentValue) > 20000 && (rand.Intn(100) < len(currentValue)/5000))
		removedCount = 0

		if len(currentValue) == 0 {
			channelLog := channels.ChangeLog{}
			channelLog.Add(entry)
			return encodeChannelLog(&channelLog), walrus.Raw, nil
		}

		if fullUpdate {
			fullUpdateAttempts++
			var newValue bytes.Buffer
			removedCount = channels.TruncateEncodedChangeLog(bytes.NewReader(currentValue),
				MaxChangeLogLength-1, &newValue)
			if removedCount > 0 {
				entry.Encode(&newValue, parentRevID)
				return newValue.Bytes(), walrus.Raw, nil
			}
		}

		w := bytes.NewBuffer(make([]byte, 0, 50000))
		entry.Encode(w, parentRevID)
		currentValue = append(currentValue, w.Bytes()...)
		return currentValue, walrus.Raw, nil
	})

	/*if fullUpdate {
		base.Log("Removed %d entries from %q", removedCount, channelName)
	} else if fullUpdateAttempts > 0 {
		base.Log("Attempted to remove entries %d times but failed", fullUpdateAttempts)
	}*/
	return err
}