1616import subprocess
1717import sys
1818import time
19+ # http lib for python2 or 3
20+ import json
21+ try :
22+ import httplib
23+ import urllib
24+ except ImportError :
25+ import http .client as httplib
26+ import urllib .parse as urllib
27+
1928# for Python 2, don't use f-string
2029log = logging .getLogger (__name__ )
2130logging .basicConfig (level = logging .INFO , format = '%(levelname)s: %(message)s' )
@@ -35,6 +44,9 @@ def GetMsg(self):
3544 def GetCode (self ):
3645 return self .code
3746
47+ def __str__ (self ):
48+ return "code: {code}, msg: {msg}" .format (code = self .code , msg = self .msg )
49+
3850class Partition :
3951 def __init__ (self , name , tid , pid , endpoint , is_leader , is_alive , offset ):
4052 self .name = name
@@ -202,17 +214,48 @@ def GetTableInfo(self, database, table_name = ''):
202214 continue
203215 result .append (record )
204216 return Status (), result
217+ def GetTableInfoHTTP (self , database , table_name = '' ):
218+ """http post ShowTable to ns leader, return one or all table info"""
219+ ns = self .endpoint_map [self .ns_leader ]
220+ conn = httplib .HTTPConnection (ns )
221+ param = {"db" : database , "name" : table_name }
222+ headers = {"Content-type" : "application/json" }
223+ conn .request ("POST" , "/NameServer/ShowTable" , json .dumps (param ), headers )
224+ response = conn .getresponse ()
225+ if response .status != 200 :
226+ return Status (response .status , response .reason ), None
227+ result = json .loads (response .read ())
228+ conn .close ()
229+ # check resp
230+ if result ["code" ] != 0 :
231+ return Status (result ["code" ], "get table info failed: {msg}" .format (msg = result ["msg" ]))
232+ return Status (), result ["table_info" ]
205233
206234 def ParseTableInfo (self , table_info ):
207235 result = {}
208236 for record in table_info :
209237 is_leader = True if record [4 ] == "leader" else False
210238 is_alive = True if record [5 ] == "yes" else False
211- partition = Partition (record [0 ], record [1 ], record [2 ], record [3 ], is_leader , is_alive , record [6 ]);
239+ partition = Partition (record [0 ], record [1 ], record [2 ], record [3 ], is_leader , is_alive , record [6 ])
212240 result .setdefault (record [2 ], [])
213241 result [record [2 ]].append (partition )
214242 return result
215243
244+ def ParseTableInfoJson (self , table_info ):
245+ """parse one table's partition info from json"""
246+ result = {}
247+ parts = table_info ["table_partition" ]
248+ for partition in parts :
249+ # one partition(one leader and others)
250+ for replica in partition ["partition_meta" ]:
251+ is_leader = replica ["is_leader" ]
252+ is_alive = True if "is_alive" not in replica else replica ["is_alive" ]
253+ # the classname should be replica, but use partition for compatible
254+ pinfo = Partition (table_info ["name" ], table_info ["tid" ], partition ["pid" ], replica ["endpoint" ], is_leader , is_alive , replica ["offset" ])
255+ result .setdefault (partition ["pid" ], [])
256+ result [partition ["pid" ]].append (pinfo )
257+ return result
258+
216259 def GetTablePartition (self , database , table_name ):
217260 status , result = self .GetTableInfo (database , table_name )
218261 if not status .OK :
@@ -274,30 +317,35 @@ def ShowTableStatus(self, pattern = '%'):
274317
275318 return Status (), output_processed
276319
277- def LoadTable (self , endpoint , name , tid , pid , sync = True ):
278- cmd = list (self .tablet_base_cmd )
279- cmd .append ("--endpoint=" + self .endpoint_map [endpoint ])
280- cmd .append ("--cmd=loadtable {} {} {} 0 8" .format (name , tid , pid ))
281- log .info ("run {cmd}" .format (cmd = cmd ))
282- status , output = self .RunWithRetuncode (cmd )
283- time .sleep (1 )
284- if status .OK () and output .find ("LoadTable ok" ) != - 1 :
285- if not sync :
286- return Status ()
287- while True :
288- status , result = self .GetTableStatus (endpoint , tid , pid )
289- key = "{}_{}" .format (tid , pid )
290- if status .OK () and key in result :
291- table_stat = result [key ][4 ]
292- if table_stat == "kTableNormal" :
293- return Status ()
294- elif table_stat == "kTableLoading" or table_stat == "kTableUndefined" :
295- log .info ("table is loading... tid {tid} pid {pid}" .format (tid = tid , pid = pid ))
296- else :
297- return Status (- 1 , "table stat is {table_stat}" .format (table_stat = table_stat ))
298- time .sleep (2 )
299-
300- return Status (- 1 , "execute load table failed, status {msg}, output {output}" .format (msg = status .GetMsg (), output = output ))
320+ def LoadTableHTTP (self , endpoint , name , tid , pid , storage ):
321+ """http post LoadTable to tablet, support all storage mode"""
322+ conn = httplib .HTTPConnection (endpoint )
323+ # ttl won't effect, set to 0, and seg cnt is always 8
324+ # and no matter if leader
325+ param = {"table_meta" : {"name" : name , "tid" : tid , "pid" : pid , "ttl" :0 , "seg_cnt" :8 , "storage_mode" : storage }}
326+ headers = {"Content-type" : "application/json" }
327+ conn .request ("POST" , "/TabletServer/LoadTable" , json .dumps (param ), headers )
328+ response = conn .getresponse ()
329+ if response .status != 200 :
330+ return Status (response .status , response .reason )
331+ result = response .read ()
332+ conn .close ()
333+ resp = json .loads (result )
334+ if resp ["code" ] != 0 :
335+ return Status (resp ["code" ], resp ["msg" ])
336+ # wait for success TODO(hw): refactor
337+ while True :
338+ status , result = self .GetTableStatus (endpoint , str (tid ), str (pid ))
339+ key = "{}_{}" .format (tid , pid )
340+ if status .OK () and key in result :
341+ table_stat = result [key ][4 ]
342+ if table_stat == "kTableNormal" :
343+ return Status ()
344+ elif table_stat == "kTableLoading" or table_stat == "kTableUndefined" :
345+ log .info ("table is loading... tid {tid} pid {pid}" .format (tid = tid , pid = pid ))
346+ else :
347+ return Status (- 1 , "table stat is {table_stat}" .format (table_stat = table_stat ))
348+ time .sleep (2 )
301349
302350 def GetLeaderFollowerOffset (self , endpoint , tid , pid ):
303351 cmd = list (self .tablet_base_cmd )
0 commit comments