github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/meta/meta.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package meta 16 17 import ( 18 "sync" 19 20 "github.com/pingcap/errors" 21 "github.com/vescale/zgraph/internal/structure" 22 "github.com/vescale/zgraph/storage/kv" 23 ) 24 25 // The globalIDMutex is used to reduce the global id key conflicts. 26 var globalIDMutex sync.Mutex 27 28 var ( 29 mMetaKeyPrefix = []byte("m") 30 mNextGlobalIDKey = []byte("next_global_id") 31 mNextIDKey = []byte("next_id") 32 mGraphs = []byte("graphs") 33 mGraphPrefix = "graph" 34 mLabelPrefix = "label" 35 mPropertyPrefix = "property" 36 ) 37 38 const ( 39 // CurrentMagicByteVer is the current magic byte version, used for future meta compatibility. 40 CurrentMagicByteVer byte = 0x00 41 // PolicyMagicByte handler 42 // 0x00 - 0x3F: Json Handler 43 // 0x40 - 0x7F: Reserved 44 // 0x80 - 0xBF: Reserved 45 // 0xC0 - 0xFF: Reserved 46 47 // MaxInt48 is the max value of int48. 48 MaxInt48 = 0x0000FFFFFFFFFFFF 49 // MaxGlobalID reserves 1000 IDs. Use MaxInt48 to reserves the high 2 bytes to compatible with Multi-tenancy. 50 MaxGlobalID = MaxInt48 - 1000 51 ) 52 53 // Meta is for handling meta information in a transaction. 54 type Meta struct { 55 txn *structure.TxStructure 56 StartVer kv.Version 57 } 58 59 // New returns a new instance of meta API object. 60 func New(txn kv.Transaction) *Meta { 61 t := structure.NewStructure(txn, txn, mMetaKeyPrefix) 62 return &Meta{ 63 txn: t, 64 StartVer: txn.StartVer(), 65 } 66 } 67 68 // NewSnapshot returns a read-only new instance of meta API object. 69 func NewSnapshot(snap kv.Snapshot) *Meta { 70 t := structure.NewStructure(snap, nil, mMetaKeyPrefix) 71 return &Meta{ 72 txn: t, 73 StartVer: snap.StartVer(), 74 } 75 } 76 77 // NextGlobalID generates next id globally. 78 func (m *Meta) NextGlobalID() (int64, error) { 79 globalIDMutex.Lock() 80 defer globalIDMutex.Unlock() 81 82 newID, err := m.txn.Inc(mNextGlobalIDKey, 1) 83 if err != nil { 84 return 0, errors.Trace(err) 85 } 86 if newID > MaxGlobalID { 87 return 0, errors.Errorf("global id:%d exceeds the limit:%d", newID, MaxGlobalID) 88 } 89 return newID, err 90 } 91 92 // AdvanceGlobalID advances the global ID by n. 93 // return the old global ID. 94 func (m *Meta) AdvanceGlobalID(n int) (int64, error) { 95 globalIDMutex.Lock() 96 defer globalIDMutex.Unlock() 97 98 newID, err := m.txn.Inc(mNextGlobalIDKey, int64(n)) 99 if err != nil { 100 return 0, err 101 } 102 if newID > MaxGlobalID { 103 return 0, errors.Errorf("global id:%d exceeds the limit:%d", newID, MaxGlobalID) 104 } 105 origID := newID - int64(n) 106 return origID, nil 107 } 108 109 // GenGlobalIDs generates the next n global IDs. 110 func (m *Meta) GenGlobalIDs(n int) ([]int64, error) { 111 globalIDMutex.Lock() 112 defer globalIDMutex.Unlock() 113 114 newID, err := m.txn.Inc(mNextGlobalIDKey, int64(n)) 115 if err != nil { 116 return nil, err 117 } 118 if newID > MaxGlobalID { 119 return nil, errors.Errorf("global id:%d exceeds the limit:%d", newID, MaxGlobalID) 120 } 121 origID := newID - int64(n) 122 ids := make([]int64, 0, n) 123 for i := origID + 1; i <= newID; i++ { 124 ids = append(ids, i) 125 } 126 return ids, nil 127 } 128 129 // GlobalID gets current global id. 130 func (m *Meta) GlobalID() (int64, error) { 131 return m.txn.GetInt64(mNextGlobalIDKey) 132 }