Example #1
0
// GetOrCreateShard will return the shard object, or create one if it doesn't
// already exist. Note the shard creation is protected by a keyspace Lock.
func GetOrCreateShard(ctx context.Context, ts topo.Server, keyspace, shard string) (*topo.ShardInfo, error) {
	si, finalErr := ts.GetShard(ctx, keyspace, shard)
	if finalErr == topo.ErrNoNode {
		// create the keyspace, maybe it already exists
		if err := ts.CreateKeyspace(ctx, keyspace, &pb.Keyspace{}); err != nil && err != topo.ErrNodeExists {
			return nil, fmt.Errorf("CreateKeyspace(%v) failed: %v", keyspace, err)
		}

		// now we can lock the keyspace
		node := actionnode.KeyspaceCreateShard()
		lockPath, err := node.LockKeyspace(ctx, ts, keyspace)
		if err != nil {
			return nil, fmt.Errorf("LockKeyspace failed: %v", err)
		}

		// now try to create within the lock, may already exist
		if err := ts.CreateShard(ctx, keyspace, shard); err != nil && err != topo.ErrNodeExists {
			return nil, node.UnlockKeyspace(ctx, ts, keyspace, lockPath, fmt.Errorf("CreateShard(%v/%v) failed: %v", keyspace, shard, err))
		}

		// try to read the shard again, maybe someone created it
		// in between the original GetShard and the LockKeyspace
		si, finalErr = ts.GetShard(ctx, keyspace, shard)

		// and unlock
		if err := node.UnlockKeyspace(ctx, ts, keyspace, lockPath, finalErr); err != nil {
			return nil, fmt.Errorf("UnlockKeyspace failed: %v", err)
		}
	}
	return si, finalErr
}
Example #2
0
// CreateShard will create the shard, while holding the keyspace lock
func CreateShard(ctx context.Context, ts topo.Server, keyspace, shard string) error {
	// Lock the keyspace
	node := actionnode.KeyspaceCreateShard()
	lockPath, err := node.LockKeyspace(ctx, ts, keyspace)
	if err != nil {
		return fmt.Errorf("LockKeyspace failed: %v", err)
	}

	// now try to create within the lock, may already exist
	err = ts.CreateShard(ctx, keyspace, shard)

	// and unlock and return
	return node.UnlockKeyspace(ctx, ts, keyspace, lockPath, err)
}
Example #3
0
// CopyShards will create the keyspaces in the destination topo
func CopyShards(fromTS, toTS topo.Server, deleteKeyspaceShards bool) {
	keyspaces, err := fromTS.GetKeyspaces()
	if err != nil {
		relog.Fatal("fromTS.GetKeyspaces failed: %v", err)
	}

	wg := sync.WaitGroup{}
	rec := concurrency.AllErrorRecorder{}
	for _, keyspace := range keyspaces {
		wg.Add(1)
		go func(keyspace string) {
			defer wg.Done()
			shards, err := fromTS.GetShardNames(keyspace)
			if err != nil {
				rec.RecordError(err)
				return
			}

			if deleteKeyspaceShards {
				if err := toTS.DeleteKeyspaceShards(keyspace); err != nil {
					rec.RecordError(err)
					return
				}
			}

			for _, shard := range shards {
				wg.Add(1)
				go func(keyspace, shard string) {
					defer wg.Done()
					if err := toTS.CreateShard(keyspace, shard); err != nil {
						if err == topo.ErrNodeExists {
							relog.Warning("shard %v/%v already exists", keyspace, shard)
						} else {
							rec.RecordError(err)
						}
					}
				}(keyspace, shard)
			}
		}(keyspace)
	}
	wg.Wait()
	if rec.HasErrors() {
		relog.Fatal("copyShards failed: %v", rec.Error())
	}
}