1 /* Copyright (c) 2003-2007 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include <ndb_global.h>
22 void desc_AutoGrowSpecification(struct NdbDictionary::AutoGrowSpecification ags
);
23 int desc_logfilegroup(Ndb
*myndb
, char* name
);
24 int desc_undofile(Ndb_cluster_connection
&con
, Ndb
*myndb
, char* name
);
25 int desc_datafile(Ndb_cluster_connection
&con
, Ndb
*myndb
, char* name
);
26 int desc_tablespace(Ndb
*myndb
,char* name
);
27 int desc_table(Ndb
*myndb
,char* name
);
31 static const char* _dbname
= "TEST_DB";
32 static int _unqualified
= 0;
33 static int _partinfo
= 0;
35 const char *load_default_groups
[]= { "mysql_cluster",0 };
37 static int _retries
= 0;
38 static struct my_option my_long_options
[] =
40 NDB_STD_OPTS("ndb_desc"),
41 { "database", 'd', "Name of database table is in",
42 (uchar
**) &_dbname
, (uchar
**) &_dbname
, 0,
43 GET_STR
, REQUIRED_ARG
, 0, 0, 0, 0, 0, 0 },
44 { "unqualified", 'u', "Use unqualified table names",
45 (uchar
**) &_unqualified
, (uchar
**) &_unqualified
, 0,
46 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
47 { "extra-partition-info", 'p', "Print more info per partition",
48 (uchar
**) &_partinfo
, (uchar
**) &_partinfo
, 0,
49 GET_BOOL
, NO_ARG
, 0, 0, 0, 0, 0, 0 },
50 { "retries", 'r', "Retry every second for # retries",
51 (uchar
**) &_retries
, (uchar
**) &_retries
, 0,
52 GET_INT
, REQUIRED_ARG
, 0, 0, 0, 0, 0, 0 },
53 { 0, 0, 0, 0, 0, 0, GET_NO_ARG
, NO_ARG
, 0, 0, 0, 0, 0, 0}
60 "This program list all properties of table(s) in NDB Cluster.\n"\
61 " ex: desc T1 T2 T4\n";
63 ndb_std_print_version();
64 print_defaults(MYSQL_CONFIG_NAME
,load_default_groups
);
66 my_print_help(my_long_options
);
67 my_print_variables(my_long_options
);
70 static void print_part_info(Ndb
* pNdb
, NDBT_Table
* pTab
);
72 int main(int argc
, char** argv
){
74 load_defaults("my",load_default_groups
,&argc
,&argv
);
77 opt_debug
= "d:t:O,/tmp/ndb_desc.trace";
79 if ((ho_error
=handle_options(&argc
, &argv
, my_long_options
,
80 ndb_std_get_one_option
)))
81 return NDBT_ProgramExit(NDBT_WRONGARGS
);
83 Ndb_cluster_connection
con(opt_connect_str
);
84 con
.set_name("ndb_desc");
85 if(con
.connect(12, 5, 1) != 0)
87 ndbout
<< "Unable to connect to management server." << endl
;
88 return NDBT_ProgramExit(NDBT_FAILED
);
90 if (con
.wait_until_ready(30,0) < 0)
92 ndbout
<< "Cluster nodes not ready in 30 seconds." << endl
;
93 return NDBT_ProgramExit(NDBT_FAILED
);
96 Ndb
MyNdb(&con
, _dbname
);
97 if(MyNdb
.init() != 0){
98 ERR(MyNdb
.getNdbError());
99 return NDBT_ProgramExit(NDBT_FAILED
);
102 for(int i
= 0; i
<argc
;i
++)
104 if(desc_table(&MyNdb
,argv
[i
]))
106 else if(desc_tablespace(&MyNdb
,argv
[i
]))
108 else if(desc_logfilegroup(&MyNdb
,argv
[i
]))
110 else if(desc_datafile(con
, &MyNdb
, argv
[i
]))
112 else if(desc_undofile(con
, &MyNdb
, argv
[i
]))
115 ndbout
<< "No such object: " << argv
[i
] << endl
<< endl
;
118 return NDBT_ProgramExit(NDBT_OK
);
121 void desc_AutoGrowSpecification(struct NdbDictionary::AutoGrowSpecification ags
)
123 ndbout
<< "AutoGrow.min_free: " << ags
.min_free
<< endl
;
124 ndbout
<< "AutoGrow.max_size: " << ags
.max_size
<< endl
;
125 ndbout
<< "AutoGrow.file_size: " << ags
.file_size
<< endl
;
126 ndbout
<< "AutoGrow.filename_pattern: " << ags
.filename_pattern
<< endl
;
129 int desc_logfilegroup(Ndb
*myndb
, char* name
)
131 NdbDictionary::Dictionary
*dict
= myndb
->getDictionary();
133 NdbDictionary::LogfileGroup lfg
= dict
->getLogfileGroup(name
);
134 NdbError err
= dict
->getNdbError();
135 if( (int) err
.classification
!= (int) ndberror_cl_none
)
138 ndbout
<< "Type: LogfileGroup" << endl
;
139 ndbout
<< "Name: " << lfg
.getName() << endl
;
140 ndbout
<< "UndoBuffer size: " << lfg
.getUndoBufferSize() << endl
;
141 ndbout
<< "Version: " << lfg
.getObjectVersion() << endl
;
142 ndbout
<< "Free Words: " << lfg
.getUndoFreeWords() << endl
;
144 desc_AutoGrowSpecification(lfg
.getAutoGrowSpecification());
151 int desc_tablespace(Ndb
*myndb
, char* name
)
153 NdbDictionary::Dictionary
*dict
= myndb
->getDictionary();
155 NdbDictionary::Tablespace ts
= dict
->getTablespace(name
);
156 NdbError err
= dict
->getNdbError();
157 if ((int) err
.classification
!= (int) ndberror_cl_none
)
160 ndbout
<< "Type: Tablespace" << endl
;
161 ndbout
<< "Name: " << ts
.getName() << endl
;
162 ndbout
<< "Object Version: " << ts
.getObjectVersion() << endl
;
163 ndbout
<< "Extent Size: " << ts
.getExtentSize() << endl
;
164 ndbout
<< "Default Logfile Group: " << ts
.getDefaultLogfileGroup() << endl
;
169 int desc_undofile(Ndb_cluster_connection
&con
, Ndb
*myndb
, char* name
)
172 NdbDictionary::Dictionary
*dict
= myndb
->getDictionary();
173 Ndb_cluster_connection_node_iter iter
;
177 con
.init_get_next_node(iter
);
179 while ((id
= con
.get_next_node(iter
)))
181 NdbDictionary::Undofile uf
= dict
->getUndofile(0, name
);
182 NdbError err
= dict
->getNdbError();
183 if ((int) err
.classification
!= (int) ndberror_cl_none
)
186 ndbout
<< "Type: Undofile" << endl
;
187 ndbout
<< "Name: " << name
<< endl
;
188 ndbout
<< "Node: " << id
<< endl
;
189 ndbout
<< "Path: " << uf
.getPath() << endl
;
190 ndbout
<< "Size: " << uf
.getSize() << endl
;
192 ndbout
<< "Logfile Group: " << uf
.getLogfileGroup() << endl
;
194 /** FIXME: are these needed, the functions aren't there
195 but the prototypes are...
197 ndbout << "Number: " << uf.getFileNo() << endl;
206 int desc_datafile(Ndb_cluster_connection
&con
, Ndb
*myndb
, char* name
)
209 NdbDictionary::Dictionary
*dict
= myndb
->getDictionary();
211 Ndb_cluster_connection_node_iter iter
;
213 con
.init_get_next_node(iter
);
215 while ((id
= con
.get_next_node(iter
)))
217 NdbDictionary::Datafile df
= dict
->getDatafile(id
, name
);
218 NdbError err
= dict
->getNdbError();
219 if ((int) err
.classification
!= (int) ndberror_cl_none
)
222 ndbout
<< "Type: Datafile" << endl
;
223 ndbout
<< "Name: " << name
<< endl
;
224 ndbout
<< "Node: " << id
<< endl
;
225 ndbout
<< "Path: " << df
.getPath() << endl
;
226 ndbout
<< "Size: " << df
.getSize() << endl
;
227 ndbout
<< "Free: " << df
.getFree() << endl
;
229 ndbout
<< "Tablespace: " << df
.getTablespace() << endl
;
231 /** We probably don't need to display this ever...
232 ndbout << "Number: " << uf.getFileNo() << endl;
241 int desc_table(Ndb
*myndb
, char* name
)
243 NdbDictionary::Dictionary
* dict
= myndb
->getDictionary();
245 while ((pTab
= (NDBT_Table
*)dict
->getTable(name
)) == NULL
&& --_retries
>= 0) NdbSleep_SecSleep(1);
249 ndbout
<< (* pTab
) << endl
;
251 NdbDictionary::Dictionary::List list
;
252 if (dict
->listIndexes(list
, name
) != 0){
253 ndbout
<< name
<< ": " << dict
->getNdbError() << endl
;
254 return NDBT_ProgramExit(NDBT_FAILED
);
257 ndbout
<< "-- Indexes -- " << endl
;
258 ndbout
<< "PRIMARY KEY(";
260 for (j
= 0; (int)j
< pTab
->getNoOfPrimaryKeys(); j
++)
262 const NdbDictionary::Column
* col
= pTab
->getColumn(pTab
->getPrimaryKey(j
));
263 ndbout
<< col
->getName();
264 if ((int)j
< pTab
->getNoOfPrimaryKeys()-1)
267 ndbout
<< ") - UniqueHashIndex" << endl
;
268 for (j
= 0; j
< list
.count
; j
++) {
269 NdbDictionary::Dictionary::List::Element
& elt
= list
.elements
[j
];
270 const NdbDictionary::Index
*pIdx
= dict
->getIndex(elt
.name
, name
);
272 ndbout
<< name
<< ": " << dict
->getNdbError() << endl
;
273 return NDBT_ProgramExit(NDBT_FAILED
);
276 ndbout
<< (*pIdx
) << endl
;
281 print_part_info(myndb
, pTab
);
288 const char * m_title
;
289 NdbRecAttr
* m_rec_attr
;
290 const NdbDictionary::Column
* m_column
;
295 void print_part_info(Ndb
* pNdb
, NDBT_Table
* pTab
)
297 InfoInfo g_part_info
[] = {
298 { "Partition", 0, NdbDictionary::Column::FRAGMENT
},
299 { "Row count", 0, NdbDictionary::Column::ROW_COUNT
},
300 { "Commit count", 0, NdbDictionary::Column::COMMIT_COUNT
},
301 { "Frag fixed memory", 0, NdbDictionary::Column::FRAGMENT_FIXED_MEMORY
},
302 { "Frag varsized memory", 0, NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY
},
306 ndbout
<< "-- Per partition info -- " << endl
;
308 NdbConnection
* pTrans
= pNdb
->startTransaction();
314 NdbScanOperation
* pOp
= pTrans
->getNdbScanOperation(pTab
->getName());
318 int rs
= pOp
->readTuples(NdbOperation::LM_CommittedRead
);
322 if (pOp
->interpret_exit_last_row() != 0)
326 for(i
= 0; g_part_info
[i
].m_title
!= 0; i
++)
328 if ((g_part_info
[i
].m_rec_attr
= pOp
->getValue(g_part_info
[i
].m_column
)) == 0)
332 if (g_part_info
[i
].m_title
!= 0)
335 if (pTrans
->execute(NoCommit
) != 0)
338 for (i
= 0; g_part_info
[i
].m_title
!= 0; i
++)
339 ndbout
<< g_part_info
[i
].m_title
<< "\t";
342 while(pOp
->nextResult() == 0)
344 for(i
= 0; g_part_info
[i
].m_title
!= 0; i
++)
346 ndbout
<< *g_part_info
[i
].m_rec_attr
<< "\t";