Motr  M0
s3_req.py
Go to the documentation of this file.
1 #
2 # Copyright (c) 2020 Seagate Technology LLC and/or its Affiliates
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # For any questions about this software or licensing,
17 # please email opensource@seagate.com or cortx-questions@seagate.com.
18 #
19 
20 import io_req as ior
21 import md_req as mdr
22 from addb2db import *
23 from graphviz import Digraph
24 from req_utils import *
25 
26 
27 def graph_prepare(graph: Digraph, relations):
28  # relation | from | to | table or direct | flags
29  # |table/mapping|table/mapping| mapping |
30  schema = [("s3_request_id", "s3_request_id", "client_id", "s3_request_to_client", "C")]
31  # flags: '1' - one to one mapping, 's' - stash samples, 'l' - leaf element
32 
33  graph_add_relations(graph, relations, schema)
34 
35 def get_timelines_ioo(client_id: str, grange: int, client_pid: int, create_attr_graph: bool,
36  export_only: bool, ext_graph: Digraph):
37  return ior.get_timelines(client_id, grange, client_pid, create_attr_graph,
38  export_only, ext_graph, False)
39 
40 def get_timelines_cob(client_id: str, grange: int, client_pid: int, create_attr_graph: bool,
41  export_only: bool, ext_graph: Digraph):
42  return ior.get_timelines(client_id, grange, client_pid, create_attr_graph,
43  export_only, ext_graph, True)
44 
45 def get_timelines(s3reqs: List[str], pid: str, create_attr_graph: bool = False, verbose: bool = False):
46  get_timelines_fns = [mdr.get_timelines, get_timelines_ioo, get_timelines_cob]
47  time_table = []
48  attr_graph = None
49 
50  for s3id in s3reqs:
51  if "-" in s3id:
52  s3_req_rel_d = s3_request_uid.select().where(s3_request_uid.uuid == s3id)
53  else:
54  s3_req_rel_d = s3_request_uid.select().where(s3_request_uid.id == s3id)
55 
56  if pid is not None:
57  s3_req_rel_d = filter(lambda x: x.pid == pid, s3_req_rel_d)
58 
59  for s3_req_rel in s3_req_rel_d:
60  s3_req_d = query2dlist(s3_request_state.select().where(
61  (s3_request_state.id == s3_req_rel.id) &
62  (s3_request_state.pid == s3_req_rel.pid)))
63  for r in s3_req_d:
64  r['op'] = s3_req_rel.uuid
65 
66  time_table.append(s3_req_d)
67 
68  s3_to_client_d = query2dlist(s3_request_to_client.select().where(
69  (s3_request_to_client.s3_request_id == s3_req_rel.id) &
70  (s3_request_to_client.pid == s3_req_rel.pid)))
71 
72  s3_to_client_d.sort(key=lambda s3rc: s3rc['client_id'])
73 
74  print("Processing S3 request {} (id {}, pid {}), client requests: "
75  .format(s3_req_rel.uuid, s3_req_rel.id, s3_req_rel.pid), end='')
76  cids_str = ""
77  for s3c in s3_to_client_d:
78  cids_str += "{}, ".format(s3c['client_id'])
79  print(cids_str[0:-2])
80 
81  if not verbose:
82  sql_tmpl = """
83 select client_req.*, 'client[' || ifnull(cob.op, '') || ifnull(dix.op, '') || ifnull(ioo.op, '') || '] ' || client_req.id as 'op' from
84 client_req LEFT JOIN (select 'cob' as 'op', client_id, pid from client_to_cob) as cob ON cob.client_id = client_req.id AND cob.pid = client_req.pid
85 LEFT JOIN (select 'dix' as 'op', client_id, pid from client_to_dix) as dix ON dix.client_id = client_req.id AND dix.pid = client_req.pid
86 LEFT JOIN (select 'ioo' as 'op', client_id, pid from client_to_ioo) as ioo ON ioo.client_id = client_req.id AND ioo.pid = client_req.pid
87 WHERE client_req.id = {clvid} and client_req.pid = {clvpid};
88 """
89  for s3c in s3_to_client_d:
90  clvreq = sql_tmpl.format(clvid=s3c['client_id'], clvpid=s3c['pid'])
91  lbls = ["time", "pid", "id", "state", "op"]
92  clov_req_d = list(map(lambda tpl: dict(zip(lbls, tpl)),
93  DB.execute_sql(clvreq).fetchall()))
94  time_table.append(clov_req_d)
95  continue
96 
97  if create_attr_graph:
98  attr_graph = Digraph(strict=True, format='png', node_attr = {'shape': 'plaintext'})
99  relations = [dict(s3_request_id = s3_req_rel.id, cli_pid = s3_req_rel.pid, srv_pid = None)]
100  graph_prepare(attr_graph, relations)
101 
102  for s3c in s3_to_client_d:
103  found = False
104  i = 0
105  ext_tml = []
106 
107  print("Processing client request {} (pid {})...".format(s3c['client_id'], s3c['pid']))
108 
109  while not found and i < len(get_timelines_fns):
110  try:
111  ext_tml, _, _, _, _ = get_timelines_fns[i](s3c['client_id'], [0, 0], s3c['pid'],
112  create_attr_graph, True, attr_graph)
113  found = True
114  except Exception:
115  pass
116  i = i + 1
117 
118  if found:
119  time_table += ext_tml
120  print("Done")
121  else:
122  print("Failed")
123  print("Could not build timelines for client request {} (pid: {})".format(s3c['client_id'], s3c['pid']))
124 
125  if create_attr_graph:
126  attr_graph.render(filename='s3_graph_{}'.format(s3_req_rel.uuid))
127 
128  return time_table
129 
131  parser = argparse.ArgumentParser(description="draws s3 request timeline")
132  parser.add_argument('--s3reqs', nargs='+', type=str, required=True,
133  help="requests ids to draw")
134  parser.add_argument("-p", "--pid", type=int, required=False, default=None,
135  help="Client pid to get requests for")
136  parser.add_argument('--db', type=str, required=False, default="m0play.db",
137  help="input database file")
138  parser.add_argument("-a", "--attr", action='store_true', help="Create attributes graph")
139  parser.add_argument("-m", "--maximize", action='store_true', help="Display in maximised window")
140  parser.add_argument("-u", "--time-unit", choices=['ms','us'], default='us',
141  help="Default time unit")
142  parser.add_argument("-v", "--verbose", action='store_true',
143  help="Display detailed request structure")
144  parser.add_argument("-i", "--index", action='store_true',
145  help="Create indexes before processing")
146 
147  return parser.parse_args()
148 
149 def create_table_index(tbl_model):
150  index_query = "CREATE INDEX {} ON {} ({});"
151  tbl_name = tbl_model.__name__
152  tbl_fields = filter(lambda nm: (("id" in nm) or ("time" in nm)) and "__" not in nm,
153  tbl_model.__dict__.keys())
154  for f in tbl_fields:
155  iq = index_query.format(f"idx_{tbl_name}_{f}", tbl_name, f)
156  try:
157  DB.execute_sql(iq)
158  except:
159  pass
160 
162  for tbl in db_create_delete_tables:
163  create_table_index(tbl)
164 
165 if __name__ == '__main__':
166  args=parse_args()
167 
168  db_init(args.db)
169  db_connect()
170 
171  if args.index:
173 
174  time_table = get_timelines(args.s3reqs, args.pid, args.attr, args.verbose)
175  prepare_time_table(time_table)
176 
177  db_close()
178 
179  print("Plotting timelines...")
180 
181  draw_timelines(time_table, None, 0, None, args.time_unit, False, args.maximize)
static struct m0_list list
Definition: list.c:144
def prepare_time_table(time_table)
Definition: req_utils.py:51
def query2dlist(model)
Definition: req_utils.py:68
def db_init(path)
Definition: addb2db.py:314
def db_connect()
Definition: addb2db.py:321
Definition: filter.py:1
static M0_UNUSED void print(struct m0_be_list *list)
Definition: list.c:186
def graph_prepare
Definition: s3_req.py:27
def create_table_index(tbl_model)
Definition: s3_req.py:149
def get_timelines_ioo
Definition: s3_req.py:35
def get_timelines
Definition: s3_req.py:45
def create_indexes()
Definition: s3_req.py:161
format
Definition: hist.py:128
def db_close()
Definition: addb2db.py:324
def graph_add_relations
Definition: req_utils.py:227
def parse_args()
Definition: s3_req.py:130
def draw_timelines
Definition: req_utils.py:105
def get_timelines_cob
Definition: s3_req.py:40