CreateBucket creates a new bucket at the given key and returns the new bucket. Returns an error if the key already exists, if the bucket name is blank, or if the bucket name is too long. The bucket instance is only valid for the lifetime of the transaction.
(key []byte)
| 146 | // Returns an error if the key already exists, if the bucket name is blank, or if the bucket name is too long. |
| 147 | // The bucket instance is only valid for the lifetime of the transaction. |
| 148 | func (b *Bucket) CreateBucket(key []byte) (rb *Bucket, err error) { |
| 149 | if lg := b.tx.db.Logger(); lg != discardLogger { |
| 150 | lg.Debugf("Creating bucket %q", key) |
| 151 | defer func() { |
| 152 | if err != nil { |
| 153 | lg.Errorf("Creating bucket %q failed: %v", key, err) |
| 154 | } else { |
| 155 | lg.Debugf("Creating bucket %q successfully", key) |
| 156 | } |
| 157 | }() |
| 158 | } |
| 159 | if b.tx.db == nil { |
| 160 | return nil, errors.ErrTxClosed |
| 161 | } else if !b.tx.writable { |
| 162 | return nil, errors.ErrTxNotWritable |
| 163 | } else if len(key) == 0 { |
| 164 | return nil, errors.ErrBucketNameRequired |
| 165 | } |
| 166 | |
| 167 | // Insert into node. |
| 168 | // Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent |
| 169 | // it from being marked as leaking, and accordingly cannot be allocated on stack. |
| 170 | newKey := cloneBytes(key) |
| 171 | |
| 172 | // Move cursor to correct position. |
| 173 | c := b.Cursor() |
| 174 | k, _, flags := c.seek(newKey) |
| 175 | |
| 176 | // Return an error if there is an existing key. |
| 177 | if bytes.Equal(newKey, k) { |
| 178 | if (flags & common.BucketLeafFlag) != 0 { |
| 179 | return nil, errors.ErrBucketExists |
| 180 | } |
| 181 | return nil, errors.ErrIncompatibleValue |
| 182 | } |
| 183 | |
| 184 | // Create empty, inline bucket. |
| 185 | var bucket = Bucket{ |
| 186 | InBucket: &common.InBucket{}, |
| 187 | rootNode: &node{isLeaf: true}, |
| 188 | FillPercent: DefaultFillPercent, |
| 189 | } |
| 190 | var value = bucket.write() |
| 191 | |
| 192 | c.node().put(newKey, newKey, value, 0, common.BucketLeafFlag) |
| 193 | |
| 194 | // Since subbuckets are not allowed on inline buckets, we need to |
| 195 | // dereference the inline page, if it exists. This will cause the bucket |
| 196 | // to be treated as a regular, non-inline bucket for the rest of the tx. |
| 197 | b.page = nil |
| 198 | |
| 199 | return b.Bucket(newKey), nil |
| 200 | } |
| 201 | |
| 202 | // CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it. |
| 203 | // Returns an error if the bucket name is blank, or if the bucket name is too long. |