package clientv3

import (
    "io"

    pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

type (
    DefragmentResponse pb.DefragmentResponse
    AlarmResponse      pb.AlarmResponse
    AlarmMember        pb.AlarmMember
    StatusResponse     pb.StatusResponse
)

type Maintenance interface {
    // AlarmList gets all active alarms.
    AlarmList(ctx context.Context) (*AlarmResponse, error)

    // AlarmDisarm disarms a given alarm.
    AlarmDisarm(ctx context.Context, m *AlarmMember) (*AlarmResponse, error)

    // Defragment defragments storage backend of the etcd member with given endpoint.
    // Defragment is only needed when deleting a large number of keys and want to reclaim
    // the resources.
    // Defragment is an expensive operation. User should avoid defragmenting multiple members
    // at the same time.
    // To defragment multiple members in the cluster, user need to call defragment multiple
    // times with different endpoints.
    Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error)

    // Status gets the status of the endpoint.
    Status(ctx context.Context, endpoint string) (*StatusResponse, error)

    // Snapshot provides a reader for a snapshot of a backend.
    Snapshot(ctx context.Context) (io.ReadCloser, error)
}

type maintenance struct {
    c      *Client
    remote pb.MaintenanceClient
}

func NewMaintenance(c *Client) Maintenance {
    return &maintenance{c: c, remote: pb.NewMaintenanceClient(c.conn)}
}

func (m *maintenance) AlarmList(ctx context.Context) (*AlarmResponse, error) {
    req := &pb.AlarmRequest{
        Action:   pb.AlarmRequest_GET,
        MemberID: 0,                 // all
        Alarm:    pb.AlarmType_NONE, // all
    }
    for {
        resp, err := m.remote.Alarm(ctx, req, grpc.FailFast(false))
        if err == nil {
            return (*AlarmResponse)(resp), nil
        }
        if isHaltErr(ctx, err) {
            return nil, toErr(ctx, err)
        }
    }
}

func (m *maintenance) AlarmDisarm(ctx context.Context, am *AlarmMember) (*AlarmResponse, error) {
    req := &pb.AlarmRequest{
        Action:   pb.AlarmRequest_DEACTIVATE,
        MemberID: am.MemberID,
        Alarm:    am.Alarm,
    }

    if req.MemberID == 0 && req.Alarm == pb.AlarmType_NONE {
        ar, err := m.AlarmList(ctx)
        if err != nil {
            return nil, toErr(ctx, err)
        }
        ret := AlarmResponse{}
        for _, am := range ar.Alarms {
            dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am))
            if derr != nil {
                return nil, toErr(ctx, derr)
            }
            ret.Alarms = append(ret.Alarms, dresp.Alarms...)
        }
        return &ret, nil
    }

    resp, err := m.remote.Alarm(ctx, req, grpc.FailFast(false))
    if err == nil {
        return (*AlarmResponse)(resp), nil
    }
    return nil, toErr(ctx, err)
}

func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error) {
    conn, err := m.c.Dial(endpoint)
    if err != nil {
        return nil, toErr(ctx, err)
    }
    defer conn.Close()
    remote := pb.NewMaintenanceClient(conn)
    resp, err := remote.Defragment(ctx, &pb.DefragmentRequest{}, grpc.FailFast(false))
    if err != nil {
        return nil, toErr(ctx, err)
    }
    return (*DefragmentResponse)(resp), nil
}

func (m *maintenance) Status(ctx context.Context, endpoint string) (*StatusResponse, error) {
    conn, err := m.c.Dial(endpoint)
    if err != nil {
        return nil, toErr(ctx, err)
    }
    defer conn.Close()
    remote := pb.NewMaintenanceClient(conn)
    resp, err := remote.Status(ctx, &pb.StatusRequest{}, grpc.FailFast(false))
    if err != nil {
        return nil, toErr(ctx, err)
    }
    return (*StatusResponse)(resp), nil
}

func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) {
    ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{}, grpc.FailFast(false))
    if err != nil {
        return nil, toErr(ctx, err)
    }

    pr, pw := io.Pipe()
    go func() {
        for {
            resp, err := ss.Recv()
            if err != nil {
                pw.CloseWithError(err)
                return
            }
            if resp == nil && err == nil {
                break
            }
            if _, werr := pw.Write(resp.Blob); werr != nil {
                pw.CloseWithError(werr)
                return
            }
        }
        pw.Close()
    }()
    return pr, nil
}

maintenance.go的更多相关文章

  1. 第24/24周 数据库维护(Database Maintenance)

    哇哦,光阴似箭!欢迎回到性能调优培训的最后一期.今天我会详细讲下SQL Server里的数据库维护,尤其是索引维护操作,还有如何进行数据库维护. 索引维护 作为一个DBA,数据库维护是你工作中非常重要 ...

  2. 玩转PowerShell第三节——【SCOM Maintenance Mode】-技术&分享

    概述 Microsoft System Center Operations Manager 2007 sp1(SCOM)是微软推出的专业系统监控软件,可以监控部署在网络中的服务器.应用系统和客户端,提 ...

  3. cloud maintenance of OpenNebula

    OpenNebula 4.4.1 maintenance release,官方建议当前的生产环境使用3.x or 4.x的其它版本; php调用curl工具伪造ip Upgrading from Op ...

  4. gdb在运行maintenance info program-spaces命令时coredump

    coredump时的信息: (gdb) maintenance info program-spaces *** Error in `gdb': free(): invalid pointer: 0x0 ...

  5. Setup SQL Server 2008 Maintenance Plan Email Notifications

    一条龙作完,如何设置EXCHANGE的操作员邮件通知.. ~~~~ http://808techblog.com/2009/07/setup-sql-server-2008-maintena.html ...

  6. The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.

    The server is temporarily unable to service your request due to maintenance downtime or capacity pro ...

  7. 产品 线上 保持 和 支持 服务 (Support and maintenance solutions)

    Maintenance and support are the key factors for the smooth functioning of ERP solutions. ERP mainten ...

  8. 一个"Median Maintenance"问题

    题目要求: Download the text file here. The goal of this problem is to implement the "Median Mainten ...

  9. Maste Note for OCR / Vote disk Maintenance Operations (ADD/REMOVE/REPLACE/MOVE)

    Doc ID 428681.1 Applies to: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 11.2.0.1.0 [R ...

  10. Oracle E-Business Suite Maintenance Guide Release 12.2(Patching Procedures)

    更多内容参考: http://docs.oracle.com/cd/E51111_01/current/acrobat/122ebsmt.zip Preparing for Patching For ...

随机推荐

  1. spring boot + jersey工程由jar包转为war包在tomcat中启动报错问题

    第一步: 在maven下,将Spring Boot工程由jar转换为war包启动,很简单,将pom.xml文件中的packaging改为war <packaging>war</pac ...

  2. json.parseArray源码解析

    json.parseArray源码解析 public static <T> List<T> parseArray(String text, Class<T> cla ...

  3. com.android.dex.DexException: Multiple dex files define Lcom/sina/sso/RemoteSSO;

    错误原因:ShareSDK的包里面也包含微博SDK的代码,两个Jar包含重复. 解决方法:用Winrar到ShareSDK的Jar里面把sso目录删掉,编译即可成功

  4. The note of Developing Innovative Ideas for New Companies Course

    This course is free on the Coursera Site,But it only has English version Threee pieces of the course ...

  5. ruby1.9.2 +windowxp

    ruby1.9.2 install on the window xp 1:在公司上網是有windows代理的(ntlm),而rails又都是gem安裝,對于接觸rails不多的人來時真是一場災難,我是 ...

  6. var $this = $(this)是什么意思?

    var $this = $(this) 声明一个变量,$this 是变量名,加$说明是jquery对象. 给声明的变量赋值,赋的值是将this元素转换为jQuery对象.

  7. Java的精确整数计算-Bigdecimal学习总结和工具类

    随笔:随着最近工作需要,回首需要涉及到一些精确的数据计算,就需要用到Bigdecimal,索性就趁着闲暇之余整理收集一下关于Bigdecimal的使用方法,由于时间的原因,整理的并不是特别详细,但相信 ...

  8. kaggle入门项目:Titanic存亡预测(四)模型拟合

    原kaggle比赛地址:https://www.kaggle.com/c/titanic 原kernel地址:A Data Science Framework: To Achieve 99% Accu ...

  9. 洛谷 P1057 解题报告

    P1057 传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹 ...

  10. 关于html以及js相关格式验证的记录

    关于html中禁止输入的一些写法主要是实现实时监听值:      下面的例子实现的事只运行输入数字切小数位数不能超过两位的示例.      1. onkeyup事件是在输的时候在键盘松开的时候进行触发 ...