1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 //
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 
10 #include "rocksdb/status.h"
11 #include <stdio.h>
12 #ifdef OS_WIN
13 #include <string.h>
14 #endif
15 #include <cstring>
16 #include "port/port.h"
17 
18 namespace ROCKSDB_NAMESPACE {
19 
CopyState(const char * state)20 const char* Status::CopyState(const char* state) {
21 #ifdef OS_WIN
22   const size_t cch = std::strlen(state) + 1;  // +1 for the null terminator
23   char* result = new char[cch];
24   errno_t ret
25 #if defined(_MSC_VER)
26     ;
27 #else
28     __attribute__((__unused__));
29 #endif
30   ret = strncpy_s(result, cch, state, cch - 1);
31   result[cch - 1] = '\0';
32   assert(ret == 0);
33   return result;
34 #else
35   const size_t cch = std::strlen(state) + 1;  // +1 for the null terminator
36   return std::strncpy(new char[cch], state, cch);
37 #endif
38 }
39 
40 static const char* msgs[static_cast<int>(Status::kMaxSubCode)] = {
41     "",                                                   // kNone
42     "Timeout Acquiring Mutex",                            // kMutexTimeout
43     "Timeout waiting to lock key",                        // kLockTimeout
44     "Failed to acquire lock due to max_num_locks limit",  // kLockLimit
45     "No space left on device",                            // kNoSpace
46     "Deadlock",                                           // kDeadlock
47     "Stale file handle",                                  // kStaleFile
48     "Memory limit reached",                               // kMemoryLimit
49     "Space limit reached",                                // kSpaceLimit
50     "No such file or directory",                          // kPathNotFound
51     // KMergeOperandsInsufficientCapacity
52     "Insufficient capacity for merge operands",
53     // kManualCompactionPaused
54     "Manual compaction paused",
55 };
56 
Status(Code _code,SubCode _subcode,const Slice & msg,const Slice & msg2)57 Status::Status(Code _code, SubCode _subcode, const Slice& msg,
58                const Slice& msg2)
59     : code_(_code), subcode_(_subcode), sev_(kNoError) {
60   assert(code_ != kOk);
61   assert(subcode_ != kMaxSubCode);
62   const size_t len1 = msg.size();
63   const size_t len2 = msg2.size();
64   const size_t size = len1 + (len2 ? (2 + len2) : 0);
65   char* const result = new char[size + 1];  // +1 for null terminator
66   memcpy(result, msg.data(), len1);
67   if (len2) {
68     result[len1] = ':';
69     result[len1 + 1] = ' ';
70     memcpy(result + len1 + 2, msg2.data(), len2);
71   }
72   result[size] = '\0';  // null terminator for C style string
73   state_ = result;
74 }
75 
ToString() const76 std::string Status::ToString() const {
77   char tmp[30];
78   const char* type;
79   switch (code_) {
80     case kOk:
81       return "OK";
82     case kNotFound:
83       type = "NotFound: ";
84       break;
85     case kCorruption:
86       type = "Corruption: ";
87       break;
88     case kNotSupported:
89       type = "Not implemented: ";
90       break;
91     case kInvalidArgument:
92       type = "Invalid argument: ";
93       break;
94     case kIOError:
95       type = "IO error: ";
96       break;
97     case kMergeInProgress:
98       type = "Merge in progress: ";
99       break;
100     case kIncomplete:
101       type = "Result incomplete: ";
102       break;
103     case kShutdownInProgress:
104       type = "Shutdown in progress: ";
105       break;
106     case kTimedOut:
107       type = "Operation timed out: ";
108       break;
109     case kAborted:
110       type = "Operation aborted: ";
111       break;
112     case kBusy:
113       type = "Resource busy: ";
114       break;
115     case kExpired:
116       type = "Operation expired: ";
117       break;
118     case kTryAgain:
119       type = "Operation failed. Try again.: ";
120       break;
121     case kColumnFamilyDropped:
122       type = "Column family dropped: ";
123       break;
124     default:
125       snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",
126                static_cast<int>(code()));
127       type = tmp;
128       break;
129   }
130   std::string result(type);
131   if (subcode_ != kNone) {
132     uint32_t index = static_cast<int32_t>(subcode_);
133     assert(sizeof(msgs) > index);
134     result.append(msgs[index]);
135   }
136 
137   if (state_ != nullptr) {
138     result.append(state_);
139   }
140   return result;
141 }
142 
143 }  // namespace ROCKSDB_NAMESPACE
144