github.com/polarismesh/polaris@v1.17.8/store/mysql/namespace.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package sqldb
    19  
    20  import (
    21  	"database/sql"
    22  	"errors"
    23  	"fmt"
    24  	"time"
    25  
    26  	"github.com/polarismesh/polaris/common/model"
    27  	"github.com/polarismesh/polaris/store"
    28  )
    29  
    30  // namespaceStore 实现了NamespaceStore
    31  type namespaceStore struct {
    32  	master *BaseDB // 大部分操作都用主数据库
    33  	slave  *BaseDB // 缓存相关的读取,请求到slave
    34  }
    35  
    36  // AddNamespace 添加命名空间
    37  func (ns *namespaceStore) AddNamespace(namespace *model.Namespace) error {
    38  	if namespace.Name == "" {
    39  		return errors.New("store add namespace name is empty")
    40  	}
    41  	return RetryTransaction("addNamespace", func() error {
    42  		return ns.master.processWithTransaction("addNamespace", func(tx *BaseTx) error {
    43  			// 先删除无效数据,再添加新数据
    44  			if err := cleanNamespace(tx, namespace.Name); err != nil {
    45  				return err
    46  			}
    47  
    48  			str := "insert into namespace(name, comment, token, owner, ctime, mtime) values(?,?,?,?,sysdate(),sysdate())"
    49  			if _, err := tx.Exec(str, namespace.Name, namespace.Comment, namespace.Token, namespace.Owner); err != nil {
    50  				return store.Error(err)
    51  			}
    52  
    53  			if err := tx.Commit(); err != nil {
    54  				log.Errorf("[Store][database] batch delete instance commit tx err: %s", err.Error())
    55  				return err
    56  			}
    57  
    58  			return nil
    59  		})
    60  	})
    61  }
    62  
    63  // UpdateNamespace 更新命名空间,目前只更新owner
    64  func (ns *namespaceStore) UpdateNamespace(namespace *model.Namespace) error {
    65  	if namespace.Name == "" {
    66  		return errors.New("store update namespace name is empty")
    67  	}
    68  	return RetryTransaction("updateNamespace", func() error {
    69  		return ns.master.processWithTransaction("updateNamespace", func(tx *BaseTx) error {
    70  			str := "update namespace set owner = ?, comment = ?,mtime = sysdate() where name = ?"
    71  			if _, err := tx.Exec(str, namespace.Owner, namespace.Comment, namespace.Name); err != nil {
    72  				return store.Error(err)
    73  			}
    74  
    75  			if err := tx.Commit(); err != nil {
    76  				log.Errorf("[Store][database] batch delete instance commit tx err: %s", err.Error())
    77  				return err
    78  			}
    79  
    80  			return nil
    81  		})
    82  	})
    83  }
    84  
    85  // UpdateNamespaceToken 更新命名空间token
    86  func (ns *namespaceStore) UpdateNamespaceToken(name string, token string) error {
    87  	if name == "" || token == "" {
    88  		return fmt.Errorf(
    89  			"store update namespace token some param are empty, name is %s, token is %s", name, token)
    90  	}
    91  	return RetryTransaction("updateNamespaceToken", func() error {
    92  		return ns.master.processWithTransaction("updateNamespaceToken", func(tx *BaseTx) error {
    93  			str := "update namespace set token = ?, mtime = sysdate() where name = ?"
    94  			if _, err := tx.Exec(str, token, name); err != nil {
    95  				return store.Error(err)
    96  			}
    97  
    98  			if err := tx.Commit(); err != nil {
    99  				log.Errorf("[Store][database] batch delete instance commit tx err: %s", err.Error())
   100  				return err
   101  			}
   102  
   103  			return nil
   104  		})
   105  	})
   106  }
   107  
   108  // GetNamespace 根据名字获取命名空间详情,只返回有效的
   109  func (ns *namespaceStore) GetNamespace(name string) (*model.Namespace, error) {
   110  	namespace, err := ns.getNamespace(name)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	if namespace != nil && !namespace.Valid {
   116  		return nil, nil
   117  	}
   118  
   119  	return namespace, nil
   120  }
   121  
   122  // GetNamespaces 根据过滤条件查询命名空间及数目
   123  func (ns *namespaceStore) GetNamespaces(filter map[string][]string, offset, limit int) (
   124  	[]*model.Namespace, uint32, error) {
   125  	// 只查询有效数据
   126  	filter["flag"] = []string{"0"}
   127  
   128  	num, err := ns.getNamespacesCount(filter)
   129  	if err != nil {
   130  		return nil, 0, err
   131  	}
   132  
   133  	out, err := ns.getNamespaces(filter, offset, limit)
   134  	if err != nil {
   135  		return nil, 0, err
   136  	}
   137  
   138  	return out, num, nil
   139  }
   140  
   141  // GetMoreNamespaces 根据mtime获取命名空间
   142  func (ns *namespaceStore) GetMoreNamespaces(mtime time.Time) ([]*model.Namespace, error) {
   143  	str := genNamespaceSelectSQL() + " where mtime >= FROM_UNIXTIME(?)"
   144  	rows, err := ns.slave.Query(str, timeToTimestamp(mtime))
   145  	if err != nil {
   146  		log.Errorf("[Store][database] get more namespace query err: %s", err.Error())
   147  		return nil, err
   148  	}
   149  
   150  	return namespaceFetchRows(rows)
   151  }
   152  
   153  // getNamespacesCount根据相关条件查询对应命名空间数目
   154  func (ns *namespaceStore) getNamespacesCount(filter map[string][]string) (uint32, error) {
   155  	str := `select count(*) from namespace `
   156  	str, args := genNamespaceWhereSQLAndArgs(str, filter, nil, 0, 1)
   157  
   158  	var count uint32
   159  	err := ns.master.QueryRow(str, args...).Scan(&count)
   160  	switch {
   161  	case err == sql.ErrNoRows:
   162  		log.Errorf("[Store][database] no row with this namespace filter")
   163  		return count, err
   164  	case err != nil:
   165  		log.Errorf("[Store][database] get namespace count by filter err: %s", err.Error())
   166  		return count, err
   167  	default:
   168  		return count, err
   169  	}
   170  }
   171  
   172  // getNamespaces 根据相关条件查询对应命名空间
   173  func (ns *namespaceStore) getNamespaces(filter map[string][]string, offset, limit int) ([]*model.Namespace, error) {
   174  	str := genNamespaceSelectSQL()
   175  	order := &Order{"mtime", "desc"}
   176  	str, args := genNamespaceWhereSQLAndArgs(str, filter, order, offset, limit)
   177  
   178  	rows, err := ns.master.Query(str, args...)
   179  	if err != nil {
   180  		log.Errorf("[Store][database] get namespaces by filter query err: %s", err.Error())
   181  		return nil, err
   182  	}
   183  
   184  	return namespaceFetchRows(rows)
   185  }
   186  
   187  // getNamespace 获取namespace的内部函数,从数据库中拉取数据
   188  func (ns *namespaceStore) getNamespace(name string) (*model.Namespace, error) {
   189  	if name == "" {
   190  		return nil, errors.New("store get namespace name is empty")
   191  	}
   192  
   193  	str := genNamespaceSelectSQL() + " where name = ?"
   194  	rows, err := ns.master.Query(str, name)
   195  	if err != nil {
   196  		log.Errorf("[Store][database] get namespace query err: %s", err.Error())
   197  		return nil, err
   198  	}
   199  
   200  	out, err := namespaceFetchRows(rows)
   201  	if err != nil {
   202  		return nil, err
   203  	}
   204  
   205  	if len(out) == 0 {
   206  		return nil, nil
   207  	}
   208  	return out[0], nil
   209  }
   210  
   211  // clean真实的数据,只有flag=1的数据才可以清除
   212  func cleanNamespace(tx *BaseTx, name string) error {
   213  	str := "delete from namespace where name = ? and flag = 1"
   214  	// 必须打印日志说明
   215  	log.Infof("[Store][database] clean namespace(%s)", name)
   216  	if _, err := tx.Exec(str, name); err != nil {
   217  		log.Infof("[Store][database] clean namespace(%s) err: %s", name, err.Error())
   218  		return err
   219  	}
   220  
   221  	return nil
   222  }
   223  
   224  // rlockNamespace rlock namespace
   225  func rlockNamespace(queryRow func(query string, args ...interface{}) *sql.Row, namespace string) (
   226  	string, error) {
   227  	str := "select name from namespace where name = ? and flag != 1 lock in share mode"
   228  
   229  	var name string
   230  	err := queryRow(str, namespace).Scan(&name)
   231  	switch {
   232  	case err == sql.ErrNoRows:
   233  		return "", nil
   234  	case err != nil:
   235  		return "", err
   236  	default:
   237  		return name, nil
   238  	}
   239  }
   240  
   241  // genNamespaceSelectSQL 生成namespace的查询语句
   242  func genNamespaceSelectSQL() string {
   243  	str := `select name, IFNULL(comment, ""), token, owner, flag, UNIX_TIMESTAMP(ctime), UNIX_TIMESTAMP(mtime)
   244  			from namespace `
   245  	return str
   246  }
   247  
   248  // namespaceFetchRows 取出rows的数据
   249  func namespaceFetchRows(rows *sql.Rows) ([]*model.Namespace, error) {
   250  	if rows == nil {
   251  		return nil, nil
   252  	}
   253  	defer rows.Close()
   254  
   255  	var out []*model.Namespace
   256  	var ctime, mtime int64
   257  	var flag int
   258  
   259  	for rows.Next() {
   260  		space := &model.Namespace{}
   261  		err := rows.Scan(
   262  			&space.Name,
   263  			&space.Comment,
   264  			&space.Token,
   265  			&space.Owner,
   266  			&flag,
   267  			&ctime,
   268  			&mtime)
   269  		if err != nil {
   270  			log.Errorf("[Store][database] fetch namespace rows scan err: %s", err.Error())
   271  			return nil, err
   272  		}
   273  
   274  		space.CreateTime = time.Unix(ctime, 0)
   275  		space.ModifyTime = time.Unix(mtime, 0)
   276  		space.Valid = true
   277  		if flag == 1 {
   278  			space.Valid = false
   279  		}
   280  
   281  		out = append(out, space)
   282  	}
   283  	if err := rows.Err(); err != nil {
   284  		log.Errorf("[Store][database] fetch namespace rows next err: %s", err.Error())
   285  		return nil, err
   286  	}
   287  
   288  	return out, nil
   289  }