github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/go-hbase/admin.go (about) 1 package hbase 2 3 import ( 4 "sort" 5 "strconv" 6 "strings" 7 "time" 8 9 "github.com/insionng/yougam/libraries/juju/errors" 10 "github.com/insionng/yougam/libraries/ngaut/log" 11 "github.com/insionng/yougam/libraries/pingcap/go-hbase/proto" 12 ) 13 14 const defaultNS = "default" 15 16 type TableName struct { 17 namespace string 18 name string 19 } 20 21 func newTableNameWithDefaultNS(tblName string) TableName { 22 return TableName{ 23 namespace: defaultNS, 24 name: tblName, 25 } 26 } 27 28 type TableDescriptor struct { 29 name TableName 30 attrs map[string][]byte 31 cfs []*ColumnFamilyDescriptor 32 } 33 34 func NewTableDesciptor(tblName string) *TableDescriptor { 35 ret := &TableDescriptor{ 36 name: newTableNameWithDefaultNS(tblName), 37 attrs: map[string][]byte{}, 38 } 39 ret.AddAddr("IS_META", "false") 40 return ret 41 } 42 43 func (c *TableDescriptor) AddAddr(attrName string, val string) { 44 c.attrs[attrName] = []byte(val) 45 } 46 47 func (t *TableDescriptor) AddColumnDesc(cf *ColumnFamilyDescriptor) { 48 for _, c := range t.cfs { 49 if c.name == cf.name { 50 return 51 } 52 } 53 t.cfs = append(t.cfs, cf) 54 } 55 56 type ColumnFamilyDescriptor struct { 57 name string 58 attrs map[string][]byte 59 } 60 61 func (c *ColumnFamilyDescriptor) AddAttr(attrName string, val string) { 62 c.attrs[attrName] = []byte(val) 63 } 64 65 // Themis will use VERSIONS=1 for some hook. 66 func NewColumnFamilyDescriptor(name string) *ColumnFamilyDescriptor { 67 return newColumnFamilyDescriptor(name, 1) 68 } 69 70 func newColumnFamilyDescriptor(name string, versionsNum int) *ColumnFamilyDescriptor { 71 versions := strconv.Itoa(versionsNum) 72 73 ret := &ColumnFamilyDescriptor{ 74 name: name, 75 attrs: make(map[string][]byte), 76 } 77 78 // add default attrs 79 ret.AddAttr("DATA_BLOCK_ENCODING", "NONE") 80 ret.AddAttr("BLOOMFILTER", "ROW") 81 ret.AddAttr("REPLICATION_SCOPE", "0") 82 ret.AddAttr("COMPRESSION", "NONE") 83 ret.AddAttr("VERSIONS", versions) 84 ret.AddAttr("TTL", "2147483647") // 1 << 31 85 ret.AddAttr("MIN_VERSIONS", "0") 86 ret.AddAttr("KEEP_DELETED_CELLS", "false") 87 ret.AddAttr("BLOCKSIZE", "65536") 88 ret.AddAttr("IN_MEMORY", "false") 89 ret.AddAttr("BLOCKCACHE", "true") 90 return ret 91 } 92 93 func getPauseTime(retry int) int64 { 94 if retry >= len(retryPauseTime) { 95 retry = len(retryPauseTime) - 1 96 } 97 if retry < 0 { 98 retry = 0 99 } 100 return retryPauseTime[retry] * defaultRetryWaitMs 101 } 102 103 func (c *client) CreateTable(t *TableDescriptor, splits [][]byte) error { 104 req := &proto.CreateTableRequest{} 105 schema := &proto.TableSchema{} 106 107 sort.Sort(BytesSlice(splits)) 108 109 schema.TableName = &proto.TableName{ 110 Qualifier: []byte(t.name.name), 111 Namespace: []byte(t.name.namespace), 112 } 113 114 for k, v := range t.attrs { 115 schema.Attributes = append(schema.Attributes, &proto.BytesBytesPair{ 116 First: []byte(k), 117 Second: []byte(v), 118 }) 119 } 120 121 for _, c := range t.cfs { 122 cf := &proto.ColumnFamilySchema{ 123 Name: []byte(c.name), 124 } 125 for k, v := range c.attrs { 126 cf.Attributes = append(cf.Attributes, &proto.BytesBytesPair{ 127 First: []byte(k), 128 Second: []byte(v), 129 }) 130 } 131 schema.ColumnFamilies = append(schema.ColumnFamilies, cf) 132 } 133 134 req.TableSchema = schema 135 req.SplitKeys = splits 136 137 ch, err := c.adminAction(req) 138 if err != nil { 139 return errors.Trace(err) 140 } 141 142 resp := <-ch 143 switch r := resp.(type) { 144 case *exception: 145 return errors.New(r.msg) 146 } 147 148 // wait and check 149 for retry := 0; retry < defaultMaxActionRetries*retryLongerMultiplier; retry++ { 150 regCnt := 0 151 numRegs := len(splits) + 1 152 err = c.metaScan(t.name.name, func(r *RegionInfo) (bool, error) { 153 if !(r.Offline || r.Split) && len(r.Server) > 0 && r.TableName == t.name.name { 154 regCnt++ 155 } 156 return true, nil 157 }) 158 if err != nil { 159 return errors.Trace(err) 160 } 161 162 if regCnt == numRegs { 163 return nil 164 } 165 log.Warnf("Retrying create table for the %d time(s)", retry+1) 166 time.Sleep(time.Duration(getPauseTime(retry)) * time.Millisecond) 167 } 168 return errors.New("create table timeout") 169 } 170 171 func (c *client) DisableTable(tblName string) error { 172 req := &proto.DisableTableRequest{ 173 TableName: &proto.TableName{ 174 Qualifier: []byte(tblName), 175 Namespace: []byte(defaultNS), 176 }, 177 } 178 179 ch, err := c.adminAction(req) 180 if err != nil { 181 return errors.Trace(err) 182 } 183 184 resp := <-ch 185 switch r := resp.(type) { 186 case *exception: 187 return errors.New(r.msg) 188 } 189 190 return nil 191 } 192 193 func (c *client) EnableTable(tblName string) error { 194 req := &proto.EnableTableRequest{ 195 TableName: &proto.TableName{ 196 Qualifier: []byte(tblName), 197 Namespace: []byte(defaultNS), 198 }, 199 } 200 201 ch, err := c.adminAction(req) 202 if err != nil { 203 return errors.Trace(err) 204 } 205 206 resp := <-ch 207 switch r := resp.(type) { 208 case *exception: 209 return errors.New(r.msg) 210 } 211 212 return nil 213 } 214 215 func (c *client) DropTable(tblName string) error { 216 req := &proto.DeleteTableRequest{ 217 TableName: &proto.TableName{ 218 Qualifier: []byte(tblName), 219 Namespace: []byte(defaultNS), 220 }, 221 } 222 223 ch, err := c.adminAction(req) 224 if err != nil { 225 return errors.Trace(err) 226 } 227 228 resp := <-ch 229 switch r := resp.(type) { 230 case *exception: 231 return errors.New(r.msg) 232 } 233 234 return nil 235 } 236 237 func (c *client) metaScan(tbl string, fn func(r *RegionInfo) (bool, error)) error { 238 scan := NewScan(metaTableName, 0, c) 239 defer scan.Close() 240 241 scan.StartRow = []byte(tbl) 242 scan.StopRow = nextKey([]byte(tbl)) 243 244 for { 245 r := scan.Next() 246 if r == nil || scan.Closed() { 247 break 248 } 249 250 region, err := c.parseRegion(r) 251 if err != nil { 252 return errors.Trace(err) 253 } 254 255 if more, err := fn(region); !more || err != nil { 256 return errors.Trace(err) 257 } 258 } 259 260 return nil 261 } 262 263 func (c *client) TableExists(tbl string) (bool, error) { 264 found := false 265 err := c.metaScan(tbl, func(region *RegionInfo) (bool, error) { 266 if region.TableName == tbl { 267 found = true 268 return false, nil 269 } 270 return true, nil 271 }) 272 if err != nil { 273 return false, errors.Trace(err) 274 } 275 276 return found, nil 277 } 278 279 // Split splits region. 280 // tblOrRegion table name or region(<tbl>,<endKey>,<timestamp>.<md5>). 281 // splitPoint which is a key, leave "" if want to split each region automatically. 282 func (c *client) Split(tblOrRegion, splitPoint string) error { 283 // Extract table name from supposing regionName. 284 tbls := strings.SplitN(tblOrRegion, ",", 2) 285 tbl := tbls[0] 286 found := false 287 var foundRegion *RegionInfo 288 err := c.metaScan(tbl, func(region *RegionInfo) (bool, error) { 289 if region != nil && region.Name == tblOrRegion { 290 found = true 291 foundRegion = region 292 return false, nil 293 } 294 return true, nil 295 }) 296 if err != nil { 297 return errors.Trace(err) 298 } 299 300 // This is a region name, split it directly. 301 if found { 302 return c.split(foundRegion, []byte(splitPoint)) 303 } 304 305 // This is a table name. 306 tbl = tblOrRegion 307 regions, err := c.GetRegions([]byte(tbl), false) 308 if err != nil { 309 return errors.Trace(err) 310 } 311 // Split each region. 312 for _, region := range regions { 313 err := c.split(region, []byte(splitPoint)) 314 if err != nil { 315 return errors.Trace(err) 316 } 317 } 318 return nil 319 } 320 321 func (c *client) split(region *RegionInfo, splitPoint []byte) error { 322 // Not in this region, skip it. 323 if len(splitPoint) > 0 && !findKey(region, splitPoint) { 324 return nil 325 } 326 c.CleanRegionCache([]byte(region.TableName)) 327 rs := NewRegionSpecifier(region.Name) 328 req := &proto.SplitRegionRequest{ 329 Region: rs, 330 } 331 if len(splitPoint) > 0 { 332 req.SplitPoint = splitPoint 333 } 334 // Empty response. 335 _, err := c.regionAction(region.Server, req) 336 if err != nil { 337 return errors.Trace(err) 338 } 339 return nil 340 }