You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.6 KiB
165 lines
4.6 KiB
//
|
|
// DISCLAIMER
|
|
//
|
|
// Copyright 2018-2021 ArangoDB GmbH, Cologne, Germany
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
//
|
|
// Author Ewout Prangsma
|
|
// Author Tomasz Mielech
|
|
//
|
|
|
|
package driver
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"path"
|
|
"strconv"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// Content of the create batch resp
|
|
type batchMetadata struct {
|
|
// ID of the batch
|
|
ID string `json:"id"`
|
|
// Last Tick reported by the server
|
|
LastTickInt Tick `json:"lastTick,omitempty"`
|
|
|
|
cl *client
|
|
serverID int64
|
|
database string
|
|
closed int32
|
|
}
|
|
|
|
// ErrBatchClosed occurs when there is an attempt closing or prolonging closed batch
|
|
var ErrBatchClosed = errors.New("Batch already closed")
|
|
|
|
// CreateBatch creates a "batch" to prevent WAL file removal and to take a snapshot
|
|
func (c *client) CreateBatch(ctx context.Context, db Database, serverID int64, ttl time.Duration) (Batch, error) {
|
|
req, err := c.conn.NewRequest("POST", path.Join("_db", db.Name(), "_api/replication/batch"))
|
|
if err != nil {
|
|
return nil, WithStack(err)
|
|
}
|
|
req = req.SetQuery("serverId", strconv.FormatInt(serverID, 10))
|
|
params := struct {
|
|
TTL float64 `json:"ttl"`
|
|
}{TTL: ttl.Seconds()} // just use a default ttl value
|
|
req, err = req.SetBody(params)
|
|
if err != nil {
|
|
return nil, WithStack(err)
|
|
}
|
|
resp, err := c.conn.Do(ctx, req)
|
|
if err != nil {
|
|
return nil, WithStack(err)
|
|
}
|
|
if err := resp.CheckStatus(200); err != nil {
|
|
return nil, WithStack(err)
|
|
}
|
|
var batch batchMetadata
|
|
if err := resp.ParseBody("", &batch); err != nil {
|
|
return nil, WithStack(err)
|
|
}
|
|
batch.cl = c
|
|
batch.serverID = serverID
|
|
batch.database = db.Name()
|
|
return &batch, nil
|
|
}
|
|
|
|
// Get the inventory of a server containing all collections (with entire details) of a database.
|
|
func (c *client) DatabaseInventory(ctx context.Context, db Database) (DatabaseInventory, error) {
|
|
req, err := c.conn.NewRequest("GET", path.Join("_db", db.Name(), "_api/replication/inventory"))
|
|
if err != nil {
|
|
return DatabaseInventory{}, WithStack(err)
|
|
}
|
|
applyContextSettings(ctx, req)
|
|
resp, err := c.conn.Do(ctx, req)
|
|
if err != nil {
|
|
return DatabaseInventory{}, WithStack(err)
|
|
}
|
|
if err := resp.CheckStatus(200); err != nil {
|
|
return DatabaseInventory{}, WithStack(err)
|
|
}
|
|
var result DatabaseInventory
|
|
if err := resp.ParseBody("", &result); err != nil {
|
|
return DatabaseInventory{}, WithStack(err)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// BatchID reported by the server
|
|
// The receiver is pointer because this struct contains the field `closed` and it can not be copied
|
|
// because race detector will complain.
|
|
func (b *batchMetadata) BatchID() string {
|
|
return b.ID
|
|
}
|
|
|
|
// LastTick reported by the server for this batch
|
|
// The receiver is pointer because this struct contains the field `closed` and it can not be copied
|
|
// because race detector will complain.
|
|
func (b *batchMetadata) LastTick() Tick {
|
|
return b.LastTickInt
|
|
}
|
|
|
|
// Extend the lifetime of an existing batch on the server
|
|
func (b *batchMetadata) Extend(ctx context.Context, ttl time.Duration) error {
|
|
if !atomic.CompareAndSwapInt32(&b.closed, 0, 0) {
|
|
return WithStack(ErrBatchClosed)
|
|
}
|
|
|
|
req, err := b.cl.conn.NewRequest("PUT", path.Join("_db", b.database, "_api/replication/batch", b.ID))
|
|
if err != nil {
|
|
return WithStack(err)
|
|
}
|
|
req = req.SetQuery("serverId", strconv.FormatInt(b.serverID, 10))
|
|
input := struct {
|
|
TTL int64 `json:"ttl"`
|
|
}{
|
|
TTL: int64(ttl.Seconds()),
|
|
}
|
|
req, err = req.SetBody(input)
|
|
if err != nil {
|
|
return WithStack(err)
|
|
}
|
|
resp, err := b.cl.conn.Do(ctx, req)
|
|
if err != nil {
|
|
return WithStack(err)
|
|
}
|
|
if err := resp.CheckStatus(204); err != nil {
|
|
return WithStack(err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Delete an existing dump batch
|
|
func (b *batchMetadata) Delete(ctx context.Context) error {
|
|
if !atomic.CompareAndSwapInt32(&b.closed, 0, 1) {
|
|
return WithStack(ErrBatchClosed)
|
|
}
|
|
|
|
req, err := b.cl.conn.NewRequest("DELETE", path.Join("_db", b.database, "_api/replication/batch", b.ID))
|
|
if err != nil {
|
|
return WithStack(err)
|
|
}
|
|
resp, err := b.cl.conn.Do(ctx, req)
|
|
if err != nil {
|
|
return WithStack(err)
|
|
}
|
|
if err := resp.CheckStatus(204); err != nil {
|
|
return WithStack(err)
|
|
}
|
|
return nil
|
|
}
|
|
|