/*
 *  Start from existing snapshot if possible
 *  If an existing snapshot does not exist, use the apid scope to fetch
 *  all data scopes, then get a snapshot for those data scopes
 *
 *  Then, poll for changes
 */
769133
func (l *listenerManager) bootstrap(lastSnap string) {
	if l.isOfflineMode && lastSnap == "" {
		log.Panic("Diagnostic mode requires existent snapshot info in default DB.")
	}

	if lastSnap != "" {
		if err := l.snapMan.startOnDataSnapshot(lastSnap); err == nil {
			log.Infof("Started on local snapshot: %s", lastSnap)
			l.changeMan.pollChangeWithBackoff()
			return
		} else {
			log.Errorf("Failed to bootstrap on local snapshot: %v", err)
			log.Warn("Will get new snapshots.")
		}
	}

	l.snapMan.downloadBootSnapshot()
	if err := l.snapMan.downloadDataSnapshot(); err != nil {
		log.Panicf("Error downloading data snapshot: %v", err)
	}
	l.changeMan.pollChangeWithBackoff()
}
824417
func (tr *Repo) InitSnapshot() error {
	if tr.Root == nil {
		return ErrNotLoaded{Role: data.CanonicalRootRole}
	}
	root, err := tr.Root.ToSigned()
	if err != nil {
		return err
	}

	if _, ok := tr.Targets[data.CanonicalTargetsRole]; !ok {
		return ErrNotLoaded{Role: data.CanonicalTargetsRole}
	}
	targets, err := tr.Targets[data.CanonicalTargetsRole].ToSigned()
	if err != nil {
		return err
	}
	snapshot, err := data.NewSnapshot(root, targets)
	if err != nil {
		return err
	}
	tr.Snapshot = snapshot
	return nil
}
739906
func (s *InjectedStore) GetSnapshot(ver Version) (Snapshot, error) {
	snapshot, err := s.Storage.GetSnapshot(ver)
	return &InjectedSnapshot{
		Snapshot: snapshot,
		cfg:      s.cfg,
	}, err
}
341751
func (v *volumeClient) Snapshot(volumeID string,
	readonly bool,
	locator *api.VolumeLocator,
	noRetry bool,
) (string, error) {
	response := &api.SnapCreateResponse{}
	request := &api.SnapCreateRequest{
		Id:       volumeID,
		Readonly: readonly,
		Locator:  locator,
		NoRetry:  noRetry,
	}
	if err := v.c.Post().Resource(snapPath).Body(request).Do().Unmarshal(response); err != nil {
		return "", err
	}

	// TODO(pedge): this probably should not be embedded in this way
	if response.VolumeCreateResponse != nil &&
		response.VolumeCreateResponse.VolumeResponse != nil &&
		response.VolumeCreateResponse.VolumeResponse.Error != "" {
		return "", errors.New(
			response.VolumeCreateResponse.VolumeResponse.Error)
	}
	if response.VolumeCreateResponse != nil {
		return response.VolumeCreateResponse.Id, nil
	}
	return "", nil
}
386881
func (m *collection) snapshot(skip uint32, cb func(*segmentStack),
	gotLock bool) (*segmentStack, int, int, int, int) {
	atomic.AddUint64(&m.stats.TotSnapshotInternalBeg, 1)

	rv := &segmentStack{options: m.options, refs: 1, stats: m.stats}

	heightDirtyTop := 0
	heightDirtyMid := 0
	heightDirtyBase := 0
	heightClean := 0

	if !gotLock {
		m.m.Lock()
	}

	rv.lowerLevelSnapshot = m.lowerLevelSnapshot.addRef()
	if rv.lowerLevelSnapshot != nil {
		rv = m.appendChildLLSnapshot(rv, rv.lowerLevelSnapshot.ss)
	}

	if m.stackDirtyTop != nil && (skip&snapshotSkipDirtyTop == 0) {
		heightDirtyTop = len(m.stackDirtyTop.a)
	}

	if m.stackDirtyMid != nil && (skip&snapshotSkipDirtyMid == 0) {
		heightDirtyMid = len(m.stackDirtyMid.a)
	}

	if m.stackDirtyBase != nil && (skip&snapshotSkipDirtyBase == 0) {
		heightDirtyBase = len(m.stackDirtyBase.a)
	}

	if m.stackClean != nil && (skip&snapshotSkipClean == 0) {
		heightClean = len(m.stackClean.a)
	}

	rv.a = make([]Segment, 0,
		heightDirtyTop+heightDirtyMid+heightDirtyBase+heightClean)

	if m.stackClean != nil && (skip&snapshotSkipClean == 0) {
		rv = m.appendChildStacks(rv, m.stackClean)
	}

	if m.stackDirtyBase != nil && (skip&snapshotSkipDirtyBase == 0) {
		rv = m.appendChildStacks(rv, m.stackDirtyBase)
	}

	if m.stackDirtyMid != nil && (skip&snapshotSkipDirtyMid == 0) {
		rv = m.appendChildStacks(rv, m.stackDirtyMid)
	}

	if m.stackDirtyTop != nil && (skip&snapshotSkipDirtyTop == 0) {
		rv = m.appendChildStacks(rv, m.stackDirtyTop)
	}

	if cb != nil {
		cb(rv)
	}

	if !gotLock {
		m.m.Unlock()
	}

	atomic.AddUint64(&m.stats.TotSnapshotInternalEnd, 1)

	return rv, heightClean, heightDirtyBase, heightDirtyMid, heightDirtyTop
}
1189072
func (client *Client) WaitForSnapShotReady(regionId common.Region, snapshotId string, timeout int) error {
	if timeout <= 0 {
		timeout = SnapshotDefaultTimeout
	}
	for {
		args := DescribeSnapshotsArgs{
			RegionId:    regionId,
			SnapshotIds: []string{snapshotId},
		}

		snapshots, _, err := client.DescribeSnapshots(&args)
		if err != nil {
			return err
		}
		if snapshots == nil || len(snapshots) == 0 {
			return common.GetClientErrorFromString("Not found")
		}
		if snapshots[0].Progress == "100%" {
			break
		}
		timeout = timeout - DefaultWaitForInterval
		if timeout <= 0 {
			return common.GetClientErrorFromString("Timeout")
		}
		time.Sleep(DefaultWaitForInterval * time.Second)
	}
	return nil
}
1317203
func (f *Facade) Snapshot(ctx datastore.Context, serviceID, message string, tags []string, snapshotSpacePercent int) (string, error) {
	defer ctx.Metrics().Stop(ctx.Metrics().Start("Facade.Snapshot"))
	// Do not DFSLock here, ControlPlaneDao does that

	logger := plog.WithFields(logrus.Fields{
		"serviceid": serviceID,
	})

	tenantID, err := f.GetTenantID(ctx, serviceID)
	if err != nil {
		logger.WithError(err).Debug("Could not get tenant id of service")
		return "", err
	}
	logger = logger.WithField("tenantid", tenantID)
	if err := f.lockTenant(ctx, tenantID); err != nil {
		logger.WithError(err).Debug("Could not lock tenant")
		return "", err
	}
	defer f.retryUnlockTenant(ctx, tenantID, nil, time.Second)
	logger.Info("Got tenant lock")
	svcs, err := f.GetServices(ctx, dao.ServiceRequest{TenantID: tenantID})
	if err != nil {
		logger.WithError(err).Debug("Could not get services under tenant")
		return "", err
	}
	imagesMap := make(map[string]struct{})
	images := make([]string, 0)
	serviceids := []string{}
	servicesToPause := []*service.Service{}
	poolmap := make(map[string]bool)
	var pausedServiceIds []string
	for i, _ := range svcs {
		svc := &svcs[i]

		// only pause services that have access to the dfs
		hasDFS, ok := poolmap[svc.PoolID]
		if !ok {
			p := &pool.ResourcePool{}
			err := f.poolStore.Get(ctx, pool.Key(svc.PoolID), p)
			if err != nil {
				logger.WithField("poolid", svc.PoolID).WithError(err).Error("Could not get resource pool")
				return "", err
			}
			hasDFS = p.HasDfsAccess()
			poolmap[svc.PoolID] = hasDFS
		}

		if hasDFS {
			if svc.DesiredState == int(service.SVCRun) {
				servicesToPause = append(servicesToPause, svc)
				pausedServiceIds = append(pausedServiceIds, svc.ID)
			}
			serviceids = append(serviceids, svc.ID)
		}

		if svc.ImageID != "" {
			if _, ok := imagesMap[svc.ImageID]; !ok {
				imagesMap[svc.ImageID] = struct{}{}
				images = append(images, svc.ImageID)
			}
		}
	}
	// Pause the services that need pausing in a batch
	if _, err := scheduleServices(f, servicesToPause, ctx, tenantID, service.SVCPause, false); err != nil {
		logger.WithError(err).Debug("Could not pause services for snapshot")
		return "", err
	}

	defer func() {
		// Refresh service objects in case something has changed (like current state)
		servicesToPause = f.GetServicesForScheduling(ctx, pausedServiceIds)
		scheduleServices(f, servicesToPause, ctx, tenantID, service.SVCRun, false)
	}()

	// Wait for the paused services to reach the paused state (and other services to reach stopped)
	if err := f.WaitService(ctx, service.SVCPause, f.dfs.Timeout(), false, serviceids...); err != nil {
		logger.WithError(err).Debug("Could not wait for services to pause during snapshot")
		return "", err
	}
	logger.Infof("Services are now paused for snapshot")
	data := dfs.SnapshotInfo{
		SnapshotInfo: &volume.SnapshotInfo{
			TenantID: tenantID,
			Message:  message,
			Tags:     tags,
		},
		Services: svcs,
		Images:   images,
	}
	snapshotID, err := f.dfs.Snapshot(data, snapshotSpacePercent)
	if err != nil {
		logger.WithError(err).Debug("Could not snapshot disk and images for tenant")
		return "", err
	}
	logger.WithField("snapshotid", snapshotID).Info("Successfully captured application data and created snapshot")
	return snapshotID, nil
}
1049389
func (dsw *desiredStateOfWorld) SnapshotExists(snapshotName string) bool {
	dsw.RLock()
	defer dsw.RUnlock()
	_, snapshotExists := dsw.snapshots[snapshotName]

	return snapshotExists
}
1168931
func (a *LBClient) AckProxySnapshotQuiece(snapshotId string, unused *interface{}) error {
	glog.V(4).Infof("ControlCenterAgent.AckProxySnapshotQuiece()")
	return a.rpcClient.Call("ControlCenterAgent.AckProxySnapshotQuiece", snapshotId, unused, 0)
}
265936
func (db *memDB) Snapshot() View {
	return &memdbView{
		txn: db.store.Txn(false),
	}
}
1305134
func (s *UniformSample) Snapshot() Sample {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	values := make([]int64, len(s.values))
	copy(values, s.values)
	return &SampleSnapshot{
		count:  s.count,
		values: values,
	}
}
612522
func (f *fragment) Snapshot() error {
	f.mu.Lock()
	defer f.mu.Unlock()
	return f.snapshot()
}
734983
func (s *Store) Snapshot() (snapshot *Store) {
	coll := copyColl(*(*map[string]*Collection)(atomic.LoadPointer(&s.coll)))
	res := &Store{
		coll:      unsafe.Pointer(&coll),
		file:      s.file,
		size:      atomic.LoadInt64(&s.size),
		readOnly:  true,
		callbacks: s.callbacks,
	}
	for _, name := range collNames(coll) {
		collOrig := coll[name]
		coll[name] = &Collection{
			store:    res,
			compare:  collOrig.compare,
			rootLock: collOrig.rootLock,
			root:     collOrig.rootAddRef(),
		}
	}
	return res
}
1113724
func (s *Store) Snapshot() *Store {
	if s.IsReadOnly() {
		return s
	}

	s.collLock.RLock()
	defer s.collLock.RUnlock()

	// Return a read-only Store with the new Collection set.
	snap := &Store{
		collLock:  nil,
		colls:     make(map[string]*Collection, len(s.colls)),
		collNames: s.collNames,
	}

	// Create a read-only Collection for each coll.
	for k, coll := range s.colls {
		newColl := &Collection{
			name: coll.name,
		}
		newColl.setRoot(coll.currentRoot())
		snap.colls[k] = newColl
	}
	return snap
}
232612
func (c *Client) LoadSnapshot(snap *Snapshot) error {
	return c.Post("/snapshot", snap, nil)
}
974491
func (r *PortAllocator) Snapshot(dst *api.RangeAllocation) error {
	snapshottable, ok := r.alloc.(allocator.Snapshottable)
	if !ok {
		return fmt.Errorf("not a snapshottable allocator")
	}
	rangeString, data := snapshottable.Snapshot()
	dst.Range = rangeString
	dst.Data = data
	return nil
}
295357
func (_m *API) GetSnapshots() ([]dao.SnapshotInfo, error) {
	ret := _m.Called()

	var r0 []dao.SnapshotInfo
	if rf, ok := ret.Get(0).(func() []dao.SnapshotInfo); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]dao.SnapshotInfo)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func() error); ok {
		r1 = rf()
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}