1 /* Copyright (C) 2014 InfiniDB, Inc.
2 
3    This program is free software; you can redistribute it and/or
4    modify it under the terms of the GNU General Public License
5    as published by the Free Software Foundation; version 2 of
6    the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16    MA 02110-1301, USA. */
17 
18 /*
19 * $Id: editem.cpp 2336 2013-06-25 19:11:36Z rdempsey $
20 */
21 
22 
23 #include <iostream>
24 #include <vector>
25 #include <algorithm>
26 #include <cassert>
27 #include <stdexcept>
28 #include <sstream>
29 #include <string>
30 #include <unistd.h>
31 using namespace std;
32 
33 #include "blocksize.h"
34 #include "calpontsystemcatalog.h"
35 #include "objectidmanager.h"
36 using namespace execplan;
37 
38 #include "dbrm.h"
39 using namespace BRM;
40 
41 #include "configcpp.h"
42 using namespace config;
43 
44 #include "dataconvert.h"
45 using namespace dataconvert;
46 
47 #include "liboamcpp.h"
48 
49 #undef REALLY_DANGEROUS
50 
51 #define CHECK(cmd) { int rc = (cmd);\
52 if ((rc) != 0)\
53 { cerr << "Error in DBRM call " #cmd "; returnCode: " << rc << endl;\
54 return 1; } }
55 
56 namespace
57 {
58 
59 OID_t MaxOID;
60 
61 DBRM* emp = 0;
62 
63 string pname;
64 
65 bool tflg = false;
66 bool sflg = false;
67 bool aflg = false;
68 bool fflg = false;
69 bool vflg = false;
70 bool mflg = false;
71 bool uflg = false;
72 
73 struct SortExtentsByPartitionFirst
74 {
operator ()__anona7a1cb0e0111::SortExtentsByPartitionFirst75     bool operator() (const EMEntry& entry1, const EMEntry& entry2)
76     {
77         if ( (entry1.partitionNum <  entry2.partitionNum) ||
78                 ((entry1.partitionNum == entry2.partitionNum) &&
79                  (entry1.dbRoot       <  entry2.dbRoot))      ||
80                 ((entry1.partitionNum == entry2.partitionNum) &&
81                  (entry1.dbRoot       == entry2.dbRoot)       &&
82                  (entry1.segmentNum   <  entry2.segmentNum))  ||
83                 ((entry1.partitionNum == entry2.partitionNum) &&
84                  (entry1.dbRoot       == entry2.dbRoot)       &&
85                  (entry1.segmentNum   == entry2.segmentNum)   &&
86                  (entry1.blockOffset  <  entry2.blockOffset)) )
87             return true;
88         else
89             return false;
90     }
91 };
92 
93 struct SortExtentsByDBRootFirst
94 {
operator ()__anona7a1cb0e0111::SortExtentsByDBRootFirst95     bool operator() (const EMEntry& entry1, const EMEntry& entry2)
96     {
97         if ( (entry1.dbRoot       <  entry2.dbRoot)       ||
98                 ((entry1.dbRoot       == entry2.dbRoot)       &&
99                  (entry1.partitionNum <  entry2.partitionNum)) ||
100                 ((entry1.dbRoot       == entry2.dbRoot)       &&
101                  (entry1.partitionNum == entry2.partitionNum) &&
102                  (entry1.segmentNum   <  entry2.segmentNum))  ||
103                 ((entry1.dbRoot       == entry2.dbRoot)       &&
104                  (entry1.partitionNum == entry2.partitionNum) &&
105                  (entry1.segmentNum   == entry2.segmentNum)   &&
106                  (entry1.blockOffset  <  entry2.blockOffset)) )
107             return true;
108         else
109             return false;
110     }
111 };
112 
113 //------------------------------------------------------------------------------
114 // Describes program usage to the user
115 //------------------------------------------------------------------------------
usage(const string & pname)116 void usage(const string& pname)
117 {
118     cout << "usage: " << pname <<
119          " [-tsahvm] [-di]|[-o oid -S opt]|[-c oid]|[-x]|[-e oid]|[-r oid]|"
120          "[-w oid]|[-l]|[-b lbid][-C][-p dbr]" << endl <<
121          "   examins/modifies the extent map." << endl <<
122          "   -h     \tdisplay this help text" << endl <<
123          "   -o oid \tdisplay extent map for oid" << endl <<
124          "   -S opt \tSort order for -o (1-partition, dbroot, seg#, fbo;" << endl <<
125          "          \t                   2-dbroot, partition, seg#, fbo;" << endl <<
126          "          \t                   default is unsorted)"  << endl <<
127          "   -d     \tdump the entire extent map" << endl <<
128          "   -c oid \tclear the min/max vals for oid" << endl <<
129          "   -C     \tclear all min/max vals" << endl <<
130          "   -t     \tdisplay min/max values as dates" << endl <<
131          "   -s     \tdisplay min/max values as timestamps" << endl <<
132          "   -a     \tdisplay min/max values as char strings" << endl <<
133          "   -u     \tdisplay min/max values as unsigned integers" << endl <<
134          "   -x     \tcreate/extend one or more oids" << endl <<
135          "   -e oid \tdelete oid" << endl <<
136          "   -r oid \trollback or delete extents" << endl <<
137          "   -v     \tdisplay verbose output" << endl <<
138          "   -w oid \tedit HWM for an oid" << endl <<
139          "   -l     \tdump the free list" << endl <<
140          "   -b lbid\tdisplay info about lbid" << endl <<
141          "   -i     \tformat the output for import (implies -dm)" << endl <<
142          "   -m     \tdisplay actual min/max values" << endl <<
143          "   -p dbr \tdelete all extents on dbroot dbr" << endl;
144 }
145 
146 //------------------------------------------------------------------------------
147 // Converts a non-dictionary char column to a string
148 //------------------------------------------------------------------------------
charcolToString(int64_t v)149 const string charcolToString(int64_t v)
150 {
151     ostringstream oss;
152     char c;
153 
154     for (int i = 0; i < 8; i++)
155     {
156         c = v & 0xff;
157         oss << c;
158         v >>= 8;
159     }
160 
161     return oss.str();
162 }
163 
164 //------------------------------------------------------------------------------
165 // Formats an integer to it's date, datetime, or char equivalent
166 //------------------------------------------------------------------------------
fmt(int64_t v)167 const string fmt(int64_t v)
168 {
169     ostringstream oss;
170 
171     if (tflg)
172     {
173         oss << DataConvert::dateToString(v);
174     }
175     else if (sflg)
176     {
177         oss << DataConvert::datetimeToString(v);
178     }
179     else if (aflg)
180     {
181         oss << charcolToString(v);
182     }
183     else if (mflg)
184     {
185         oss << v;
186     }
187     else if (uflg)
188     {
189         if (static_cast<uint64_t>(v) > numeric_limits<uint64_t>::max() - 2)
190             oss << "notset";
191         else
192             oss << static_cast<uint64_t>(v);
193     }
194     else
195     {
196         if (v == numeric_limits<int64_t>::max() ||
197                 v <= (numeric_limits<int64_t>::min() + 2))
198             oss << "notset";
199         else
200             oss << v;
201     }
202 
203     return oss.str();
204 }
205 
206 //------------------------------------------------------------------------------
207 // Check to see if the latest read operation from stdin was successful.
208 // Primarily used to validate the case where we have prompted the user for
209 // more than 1 parameter.  Ex: we are validating that the user correctly
210 // formatted the input to enter 3 values separated by spaces (1 2 3) in-
211 // stead of accidentally separating with commas (1,2,3).
212 //------------------------------------------------------------------------------
213 //@bug 4914: Validate that correct number of input parameters is given
isInputValid()214 bool isInputValid()
215 {
216     if (cin.good())
217         return true;
218 
219     cin.clear();
220     cin.ignore( numeric_limits<std::streamsize>::max(), '\n');
221     cout << endl << "Invalid input; try again, be sure to enter spaces "
222          "between input parameters." << endl << endl;
223 
224     return false;
225 }
226 
227 //------------------------------------------------------------------------------
228 // Dump all the extents for the specified OID
229 //------------------------------------------------------------------------------
dumpone(OID_t oid,unsigned int sortOrder)230 int dumpone(OID_t oid, unsigned int sortOrder)
231 {
232     std::vector<struct EMEntry> entries;
233     std::vector<struct EMEntry>::iterator iter;
234     std::vector<struct EMEntry>::iterator end;
235     int64_t max;
236     int64_t min;
237     int32_t seqNum;
238     bool header;
239     bool needtrailer = false;
240     unsigned extentRows = emp->getExtentRows();
241     unsigned colWidth = 0;
242 
243     CHECK(emp->getExtents(oid, entries, false, false, true));
244 
245     if (entries.size() > 0)
246     {
247         if (sortOrder == 1)
248         {
249             SortExtentsByPartitionFirst sorter;
250             std::sort( entries.begin(), entries.end(), sorter );
251         }
252         else if (sortOrder == 2)
253         {
254             SortExtentsByDBRootFirst sorter;
255             std::sort( entries.begin(), entries.end(), sorter );
256         }
257 
258         header = false;
259         iter = entries.begin();
260         end = entries.end();
261 
262         while (iter != end)
263         {
264             uint32_t lbidRangeSize = iter->range.size * 1024;
265             max       = iter->partition.cprange.hi_val;
266             min       = iter->partition.cprange.lo_val;
267             seqNum    = iter->partition.cprange.sequenceNum;
268             int state = iter->partition.cprange.isValid;
269 
270             if (!header)
271             {
272                 if ( iter->colWid > 0 )
273                 {
274                     cout << "Col OID = " << oid << ", NumExtents = " <<
275                          entries.size() << ", width = " << iter->colWid << endl;
276                     colWidth = iter->colWid;
277                 }
278                 else
279                 {
280                     cout << "Dct OID = " << oid << endl;
281                     colWidth = DICT_COL_WIDTH;
282                 }
283 
284                 header = true;
285             }
286 
287             if (vflg)
288                 cout << oid << ' ';
289 
290             cout << iter->range.start << " - " <<
291                  (iter->range.start + lbidRangeSize - 1) <<
292                  " (" << lbidRangeSize << ") min: " << fmt(min) <<
293                  ", max: " << fmt(max) << ", seqNum: " << seqNum << ", state: ";
294 
295             switch (state)
296             {
297                 case 0:
298                     cout << "invalid";
299                     break;
300 
301                 case 1:
302                     cout << "updating";
303                     break;
304 
305                 case 2:
306                     cout << "valid";
307                     break;
308 
309                 default:
310                     cout << "unknown";
311                     break;
312             }
313 
314             cout << ", fbo: "   << iter->blockOffset;
315             cout << ", DBRoot: " << iter->dbRoot <<
316                  ", part#: " << iter->partitionNum <<
317                  ", seg#: " << iter->segmentNum;
318             cout << ", HWM: "   << iter->HWM;
319 
320             switch (iter->status)
321             {
322                 case EXTENTAVAILABLE:
323                     cout << "; status: avail";
324                     break;
325 
326                 case EXTENTUNAVAILABLE:
327                     cout << "; status: unavail";
328                     break;
329 
330                 case EXTENTOUTOFSERVICE:
331                     cout << "; status: outOfSrv";
332                     break;
333 
334                 default:
335                     cout << "; status: unknown";
336                     break;
337             }
338 
339             cout << endl;
340 
341             //Complain loudly if there's a mis-match
342             if (lbidRangeSize != (extentRows * colWidth / BLOCK_SIZE))
343             {
344                 cout << endl;
345                 throw logic_error(
346                     "Extent Map entries do match config file setting!");
347             }
348 
349             needtrailer = true;
350             ++iter;
351         }
352 
353         if (needtrailer) cout << endl;
354     }
355 
356     return 0;
357 }
358 
359 //------------------------------------------------------------------------------
360 // Dumps all the extents in the extent map
361 //------------------------------------------------------------------------------
dumpall()362 int dumpall()
363 {
364     for (OID_t oid = 0; oid <= MaxOID; oid++)
365     {
366         dumpone(oid, 0 /* no sorting */);
367     }
368 
369     return 0;
370 }
371 
372 //------------------------------------------------------------------------------
373 // Deletes all the extents in the extent map
374 //------------------------------------------------------------------------------
zapit()375 int zapit()
376 {
377 #ifdef REALLY_DANGEROUS
378     LBIDRange_v range;
379 
380     for (OID_t oid = 0; oid <= MaxOID; oid++)
381     {
382         CHECK(emp->lookup(oid, range));
383 
384         if (range.size() > 0)
385         {
386             CHECK(emp->deleteOID(oid));
387             CHECK(emp->confirmChanges());
388         }
389     }
390 
391 #else
392     cerr << "Sorry, I'm not going to do that." << endl;
393 #endif
394     return 0;
395 }
396 
397 //------------------------------------------------------------------------------
398 // Clears Casual Partition min/max for all the extents in the extent map
399 //------------------------------------------------------------------------------
clearAllCPData()400 int clearAllCPData()
401 {
402     BRM::LBIDRange_v ranges;
403     int oid, err;
404 
405     for (oid = 0; oid < MaxOID; oid++)
406     {
407         err = emp->lookup(oid, ranges);
408 
409         if (err == 0 && ranges.size() > 0)
410         {
411             BRM::CPInfo cpInfo;
412             BRM::CPInfoList_t vCpInfo;
413             cpInfo.max = numeric_limits<int64_t>::min();
414             cpInfo.min = numeric_limits<int64_t>::max();
415             cpInfo.seqNum = -1;
416 
417             for (uint32_t i = 0; i < ranges.size(); i++)
418             {
419                 BRM::LBIDRange r = ranges.at(i);
420                 cpInfo.firstLbid = r.start;
421                 vCpInfo.push_back(cpInfo);
422             }
423 
424             CHECK(emp->setExtentsMaxMin(vCpInfo));
425         }
426     }
427 
428     return 0;
429 }
430 
431 //------------------------------------------------------------------------------
432 // Clears Casual Partition min/max for the specified OID
433 //------------------------------------------------------------------------------
clearmm(OID_t oid)434 int clearmm(OID_t oid)
435 {
436 
437     BRM::LBIDRange_v ranges;
438     CHECK(emp->lookup(oid, ranges));
439     BRM::LBIDRange_v::size_type rcount = ranges.size();
440 
441     // @bug 2280.  Changed to use the batch interface to clear the CP info to make the clear option faster.
442     BRM::CPInfo cpInfo;
443     BRM::CPInfoList_t vCpInfo;
444     cpInfo.max = numeric_limits<int64_t>::min();
445     cpInfo.min = numeric_limits<int64_t>::max();
446     cpInfo.seqNum = -1;
447 
448     for (unsigned i = 0; i < rcount; i++)
449     {
450         BRM::LBIDRange r = ranges.at(i);
451         cpInfo.firstLbid = r.start;
452         vCpInfo.push_back(cpInfo);
453     }
454 
455     CHECK(emp->setExtentsMaxMin(vCpInfo));
456 
457     return 0;
458 }
459 
460 //------------------------------------------------------------------------------
461 // Create/add extents to dictionary OID, or a list of column OIDs.
462 //------------------------------------------------------------------------------
extendOids()463 int extendOids( )
464 {
465     uint16_t  dbRoot;
466     uint32_t  partNum;
467     uint16_t  segNum;
468     OID_t     oid;
469     uint32_t colWidth;
470     char      DictStoreOIDFlag;
471 
472     vector<CreateStripeColumnExtentsArgIn> cols;
473 
474     cout << "Are you extending a dictionary store oid (y/n)? ";
475     cin >> DictStoreOIDFlag;
476 
477     if ((DictStoreOIDFlag == 'y') || (DictStoreOIDFlag == 'Y'))
478     {
479         LBID_t lbid;
480         int    allocd;
481 
482         cout << "Enter OID, DBRoot, and Partition#, and Segment# "
483              "(separated by spaces): ";
484 
485         while (1)
486         {
487             cin >> oid >> dbRoot >> partNum >> segNum;
488 
489             if (isInputValid())
490                 break;
491         }
492 
493         CHECK(emp->createDictStoreExtent ( oid, dbRoot, partNum, segNum,
494                                            lbid, allocd));
495 
496         if (vflg)
497         {
498             cout << oid << " created/extended w/ " << allocd << " blocks; "
499                  "beginning LBID: " << lbid <<
500                  "; DBRoot: " << dbRoot <<
501                  "; Part#: "  << partNum <<
502                  "; Seg#: "   << segNum << endl;
503         }
504     }
505     else
506     {
507         while (1)
508         {
509             bool bFinished = false;
510 
511             while (1)
512             {
513                 cout << "Enter OID and column width (separated by spaces); "
514                      "0 OID represents end of list: ";
515                 cin >> oid >> colWidth;
516 
517                 if (oid == 0)
518                 {
519                     bFinished = true;
520                     break;
521                 }
522 
523                 if (isInputValid())
524                     break;
525             }
526 
527             if (bFinished)
528                 break;
529 
530             CreateStripeColumnExtentsArgIn colArg;
531             colArg.oid   = oid;
532             colArg.width = colWidth;
533 
534             if (uflg)
535             {
536                 colArg.colDataType = execplan::CalpontSystemCatalog::UBIGINT;
537             }
538             else
539             {
540                 colArg.colDataType = execplan::CalpontSystemCatalog::BIGINT;
541             }
542 
543             cols.push_back( colArg );
544         }
545 
546         vector<CreateStripeColumnExtentsArgOut> newExtents;
547 
548         while (1)
549         {
550             cout << "Enter DBRoot and partition# (partition "
551                  "only used for empty DBRoot): ";
552             cin  >> dbRoot >> partNum;
553 
554             if (isInputValid())
555                 break;
556         }
557 
558         CHECK(emp->createStripeColumnExtents(cols, dbRoot, partNum,
559                                              segNum, newExtents));
560 
561         cout << "Extents created in partition " << partNum <<
562              ", segment " << segNum << endl;
563 
564         if (vflg)
565         {
566             for (unsigned k = 0; k < newExtents.size(); k++)
567             {
568                 cout << "Column OID-" << cols[k].oid <<
569                      "; LBID-"  << newExtents[k].startLbid <<
570                      "; nblks-" << newExtents[k].allocSize <<
571                      "; fbo-"   << newExtents[k].startBlkOffset << endl;
572             }
573         }
574     }
575 
576     return 0;
577 }
578 
579 //------------------------------------------------------------------------------
580 // Rollback (delete) all extents for the specified OID, that follow the
581 // designated extent
582 //------------------------------------------------------------------------------
rollbackExtents(OID_t oid)583 int rollbackExtents(OID_t oid)
584 {
585     char      DictStoreOIDFlag;
586     uint32_t  partNum;
587     uint16_t  dbRoot;
588     uint16_t  segNum;
589     HWM_t     hwm;
590 
591     cout << "Are you rolling back extents for a dictionary store oid (y/n)? ";
592     cin >> DictStoreOIDFlag;
593 
594     if ((DictStoreOIDFlag == 'y') || (DictStoreOIDFlag == 'Y'))
595     {
596         unsigned int     hwmCount = 0;
597         vector<uint16_t> segNums;
598         vector<HWM_t>    hwms;
599 
600         while (1)
601         {
602             cout << "Enter DBRoot#, part#, and the number of HWMs to be entered "
603                  "(separated by spaces): ";
604             cin >> dbRoot >> partNum >> hwmCount;
605 
606             if (isInputValid())
607                 break;
608         }
609 
610         for (unsigned int k = 0; k < hwmCount; k++)
611         {
612             while (1)
613             {
614                 cout << "Enter seg# and HWM for that segment file " <<
615                      "(separated by spaces): ";
616                 cin >> segNum >> hwm;
617 
618                 if (isInputValid())
619                     break;
620             }
621 
622             hwms.push_back(hwm);
623             segNums.push_back(segNum);
624         }
625 
626         CHECK(emp->rollbackDictStoreExtents_DBroot( oid, dbRoot, partNum,
627                 segNums, hwms ));
628     }
629     else
630     {
631         while (1)
632         {
633             cout << "Enter DBRoot#, part#, seg#, and HWM for the last extent "
634                  "on that DBRoot (separated by spaces): ";
635             cin >> dbRoot >> partNum >> segNum >> hwm;
636 
637             if (isInputValid())
638                 break;
639         }
640 
641         CHECK(emp->rollbackColumnExtents_DBroot( oid, false,
642                 dbRoot, partNum, segNum, hwm ));
643     }
644 
645     return 0;
646 }
647 
648 //------------------------------------------------------------------------------
649 // Delete the specified OID from the extent map
650 //------------------------------------------------------------------------------
deleteOid(OID_t oid)651 int deleteOid(OID_t oid)
652 {
653     if (!fflg)
654     {
655         cout << "WARNING! This operation cannot be undone. Enter 'yes' to continue: ";
656         string resp;
657         cin >> resp;
658 
659         if (resp.empty())
660             return 1;
661 
662         string::const_iterator p = resp.begin();
663 
664         if (*p != 'y' && *p != 'Y')
665             return 1;
666     }
667 
668     cout << "Deleting extent map info for " << oid << endl;
669 
670     CHECK(emp->deleteOID(oid));
671 
672     return 0;
673 }
674 
675 //------------------------------------------------------------------------------
676 // Update the local HWM for the specified OID and segment file
677 //------------------------------------------------------------------------------
editHWM(OID_t oid)678 int editHWM(OID_t oid)
679 {
680     HWM_t    oldHWM;
681     HWM_t    newHWM;
682     uint32_t partNum   = 0;
683     uint16_t segNum    = 0;
684 
685     while (1)
686     {
687         cout << "Enter Partition#, and Segment# (separated by spaces): ";
688         cin >> partNum >> segNum;
689 
690         if (isInputValid())
691             break;
692     }
693 
694     int extState;
695     CHECK(emp->getLocalHWM(oid, partNum, segNum, oldHWM, extState));
696 
697     cout << "HWM for partition " << partNum << " and segment " << segNum <<
698          " is currently " << oldHWM <<
699          ".  Enter new value: ";
700     cin >> newHWM;
701 
702     CHECK(emp->setLocalHWM(oid, partNum, segNum, newHWM));
703 
704     return 0;
705 }
706 
707 //------------------------------------------------------------------------------
708 // Dump the free list information
709 //------------------------------------------------------------------------------
dumpFL()710 int dumpFL()
711 {
712     vector<InlineLBIDRange> v = emp->getEMFreeListEntries();
713 
714     vector<InlineLBIDRange>::iterator iter = v.begin();
715     vector<InlineLBIDRange>::iterator end = v.end();
716 
717     while (iter != end)
718     {
719         if (iter->size || vflg)
720             cout << iter->start << '\t' << iter->size << endl;
721 
722         ++iter;
723     }
724 
725     return 0;
726 }
727 
728 //------------------------------------------------------------------------------
729 // Dump information about the specified LBID
730 //------------------------------------------------------------------------------
dumpLBID(LBID_t lbid)731 int dumpLBID(LBID_t lbid)
732 {
733     uint16_t ver = 0;
734     BRM::OID_t oid;
735     uint16_t dbroot;
736     uint32_t partNum;
737     uint16_t segNum;
738     uint32_t fbo;
739     int rc;
740     rc = emp->lookupLocal(lbid, ver, false, oid, dbroot, partNum, segNum, fbo);
741     idbassert(rc == 0);
742     cout << "LBID " << lbid << " is part of OID " << oid <<
743          "; DbRoot "     << dbroot  <<
744          "; partition# " << partNum <<
745          "; segment# "   << segNum  <<
746          "; at FBO "     << fbo     << endl;
747     return 0;
748 }
749 
750 //------------------------------------------------------------------------------
751 // Delete all the extents for the specified DBRoot
752 //------------------------------------------------------------------------------
deleteAllOnDBRoot(uint16_t dbroot)753 int deleteAllOnDBRoot(uint16_t dbroot)
754 {
755     int rc;
756     rc = emp->deleteDBRoot(dbroot);
757     idbassert(rc == 0);
758     return 0;
759 }
760 
761 }
762 
763 //------------------------------------------------------------------------------
764 // main entry point into this program
765 //------------------------------------------------------------------------------
main(int argc,char ** argv)766 int main(int argc, char** argv)
767 {
768     int c;
769     pname = argv[0];
770     bool dflg = false;
771     int zflg = 0;
772     bool cflg = false;
773     bool Cflg = false;
774     OID_t oid = 0;
775     bool oflg = false;
776     bool xflg = false;
777     bool eflg = false;
778     bool rflg = false;
779     bool wflg = false;
780     bool lflg = false;
781     bool bflg = false;
782     bool iflg = false;
783     LBID_t lbid = 0;
784     bool pflg = false;
785     uint16_t dbroot = 0;
786     unsigned int sortOrder = 0; // value of 0 means no sorting
787 
788     opterr = 0;
789 
790     while ((c = getopt(argc, argv, "dzCc:o:tsxue:r:fvhw:lb:aimp:S:")) != EOF)
791         switch (c)
792         {
793             case 'd':
794                 dflg = true;
795                 break;
796 
797             case 'z':
798                 zflg++;
799                 break;
800 
801             case 'C':
802                 Cflg = true;
803                 break;
804 
805             case 'c':
806                 cflg = true;
807                 oid = (OID_t)strtoul(optarg, 0, 0);
808                 break;
809 
810             case 'o':
811                 oflg = true;
812                 oid = (OID_t)strtoul(optarg, 0, 0);
813                 break;
814 
815             case 't':
816                 tflg = true;
817                 break;
818 
819             case 'u':
820                 uflg = true;
821                 break;
822 
823             case 's':
824                 sflg = true;
825                 break;
826 
827             case 'x':
828                 xflg = true;
829                 break;
830 
831             case 'e':
832                 eflg = true;
833                 oid = (OID_t)strtoul(optarg, 0, 0);
834                 break;
835 
836             case 'r':
837                 rflg = true;
838                 oid = (OID_t)strtoul(optarg, 0, 0);
839                 break;
840 
841             case 'f':
842                 fflg = true;
843                 break;
844 
845             case 'v':
846                 vflg = true;
847                 break;
848 
849             case 'w':
850                 wflg = true;
851                 oid = (OID_t)strtoul(optarg, 0, 0);
852                 break;
853 
854             case 'l':
855                 lflg = true;
856                 break;
857 
858             case 'b':
859                 bflg = true;
860                 lbid = (LBID_t)strtoull(optarg, 0, 0);
861                 break;
862 
863             case 'a':
864                 aflg = true;
865                 break;
866 
867             case 'i':
868                 iflg = true;
869                 break;
870 
871             case 'm':
872                 mflg = true;
873                 break;
874 
875             case 'p':
876                 pflg = true;
877                 dbroot = (uint16_t)strtoul(optarg, 0, 0);
878                 break;
879 
880             case 'S':
881                 sortOrder = strtoul(optarg, 0, 0);
882                 break;
883 
884             case 'h':
885             case '?':
886             default:
887                 usage(pname);
888                 return (c == 'h' ? 0 : 1);
889                 break;
890         }
891 
892     (void)Config::makeConfig();
893 
894     //IF this is UM in a multi-node system, there may not (won't) be an OID bitmap file, so move on...
895     oam::oamModuleInfo_t modInfo;
896     oam::Oam oam;
897     string localModuleType("pm");
898 
899     try
900     {
901         modInfo = oam.getModuleInfo();
902         localModuleType = modInfo.get<1>();
903     }
904     catch (...)
905     {
906     }
907 
908     emp = new DBRM();
909 
910     if (!emp->isDBRMReady())
911     {
912         cerr << endl << "Error! The DBRM is currently not responding!" << endl
913              << "editem can't continue" << endl << endl;
914         return 1;
915     }
916 
917     MaxOID = -1;
918 
919     if (localModuleType != "um")
920     {
921         ObjectIDManager oidm;
922         MaxOID = oidm.size();
923     }
924 
925     if (emp->isReadWrite() != ERR_OK)
926     {
927         cerr << endl << "Warning! The DBRM is currently in Read-Only mode!" << endl
928              << "Updates will not propagate!" << endl << endl;
929     }
930 
931     if (iflg)
932     {
933         dflg = mflg = true;
934         ExtentMap em;
935         cout << em;
936         return 0;
937     }
938 
939     if ((int)dflg + (int)cflg + (int)oflg + (int)xflg + (int)eflg + (int)wflg +
940             (int)lflg + (int)bflg + (int)Cflg + (int)rflg + (int)pflg > 1)
941     {
942         cerr << "Only one of d/c/o/x/e/w/l/b/r/C/p can be specified." << endl;
943         usage(pname);
944         return 1;
945     }
946 
947     if ((int)sflg + (int)tflg + (int)aflg + (int)uflg > 1)
948     {
949         cerr << "Only one of s/t/a/u can be specified." << endl;
950         usage(pname);
951         return 1;
952     }
953 
954     if (MaxOID < 0 && ((int)dflg + (int)Cflg + zflg) > 0)
955     {
956         cerr << "Can't use d/C flag on module type " << localModuleType << endl;
957         usage(pname);
958         return 1;
959     }
960 
961     if (pflg)
962         return deleteAllOnDBRoot(dbroot);
963 
964     if (oflg)
965         return dumpone(oid, sortOrder);
966 
967     if (dflg)
968         return dumpall();
969 
970     if (zflg >= 2)
971         return zapit();
972     else if (zflg)
973     {
974         cerr << "Not enough z's to zap extent map." << endl;
975         return 1;
976     }
977 
978     if (Cflg)
979         return clearAllCPData();
980 
981     if (cflg)
982         return clearmm(oid);
983 
984     if (xflg)
985         return extendOids();
986 
987     if (eflg)
988         return deleteOid(oid);
989 
990     if (wflg)
991         return editHWM(oid);
992 
993     if (rflg)
994         return rollbackExtents(oid);
995 
996     if (lflg)
997         return dumpFL();
998 
999     if (bflg)
1000         return dumpLBID(lbid);
1001 
1002     usage(pname);
1003 
1004     return 0;
1005 }
1006 // vim:ts=4 sw=4:
1007 
1008