File: skipdbm_ex2.cc

package info (click to toggle)
tkrzw 1.0.32-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,820 kB
  • sloc: cpp: 64,785; ansic: 2,079; makefile: 1,125
file content (135 lines) | stat: -rw-r--r-- 4,839 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*************************************************************************************************
 * Example for serious use cases of the skip database
 *
 * Copyright 2020 Google LLC
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a copy of the License at
 *     https://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied.  See the License for the specific language governing permissions
 * and limitations under the License.
 *************************************************************************************************/

#include "tkrzw_cmd_util.h"
#include "tkrzw_dbm_skip.h"

// Main routine.
int main(int argc, char** argv) {
  // All symbols of Tkrzw are under the namespace "tkrzw".
  using namespace tkrzw;

  // Creates the database manager.
  SkipDBM dbm;

  // Tuning parameters.
  // Using a 4-byte integer for addressing.
  // Setting 1 in 3 records to have skip links.
  // Setting 8 as the maximum level of the skip list.
  // Assuming the input records are in ascending order.
  SkipDBM::TuningParameters tuning_params;
  tuning_params.offset_width = 4;
  tuning_params.step_unit = 3;
  tuning_params.max_level = 8;
  tuning_params.insert_in_order = true;
  
  // Opens a new database, OPEN_TRUNCATE means to clear the file content.
  // The result is returned as a Status object.
  Status status = dbm.OpenAdvanced(
      "casket.tks", true, File::OPEN_TRUNCATE, tuning_params);
  if (status != Status::SUCCESS) {
    // Failure of the Open operation is critical so we stop.
    Die("Open failed: ", status);
  }
  
  // Prepares records in ascending order of the key.
  // The in-order mode requires sorted records.
  std::map<std::string, std::string> input_records;
  input_records["foo"] = "hop";
  input_records["bar"] = "step";
  input_records["baz"] = "jump";

  // Stores records.
  for (const auto& input_record : input_records) {
    status = dbm.Set(input_record.first, input_record.second);
    if (status != Status::SUCCESS) {
      // The Set operation shouldn't fail.  So we stop if it happens.
      Die("Set failed: ", status);
    }
  }

  // Closes the database.
  status = dbm.Close();
  if (status != Status::SUCCESS) {
    // The Close operation shouldn't fail.  So we stop if it happens.
    Die("Close failed: ", status);
  }

  // Opens the existing database as a reader mode.
  status = dbm.Open("casket.tks", false);
  if (status != Status::SUCCESS) {
    // Failure of the Open operation is critical so we stop.
    Die("Open failed: ", status);
  }

  // Retrieves records.
  // If there was no record, NOT_FOUND_ERROR would be returned.
  std::string value;
  status = dbm.Get("foo", &value);
  if (status == Status::SUCCESS) {
    std::cout << value << std::endl;
  } else {
    std::cerr << "missing: " << status << std::endl;
  }

  // Traverses records with forward matching with "ba"
  std::unique_ptr<DBM::Iterator> iter = dbm.MakeIterator();
  status = iter->Jump("ba");
  if (status == Status::NOT_FOUND_ERROR) {
    // This could happen if there are no records equal to or greater than it.
    std::cerr << "missing: " << status << std::endl;
  } else if (status != Status::SUCCESS) {
    // Other errors are critical so we stop.
    Die("Jump failed: ", status);
  }
  while (true) {
    // Retrieves the current record data.
    std::string iter_key, iter_value;
    status = iter->Get(&iter_key, &iter_value);
    if (status == Status::SUCCESS) {
      if (!StrBeginsWith(iter_key, "ba")) break;
      std::cout << iter_key << ":" << iter_value << std::endl;
    } else {
      // This happens at the end of iteration.
      if (status != Status::NOT_FOUND_ERROR) {
        // Error types other than NOT_FOUND_ERROR are critical.
        Die("Iterator::Get failed: ", status);
      }
      break;
    }
    // Moves the iterator to the next record.
    status = iter->Next();
    if (status != Status::SUCCESS) {
      // This could happen if another thread cleared the database.
      if (status != Status::NOT_FOUND_ERROR) {
        // Error types other than NOT_FOUND_ERROR are critical.
        Die("Iterator::Get failed: ", status);
      }
      std::cerr << "missing: " << status << std::endl;
      break;
    }
  }

  // Closes the database.
  // Even if you forgot to close it, the destructor would close it.
  // However, checking the status is a good manner.
  status = dbm.Close();
  if (status != Status::SUCCESS) {
    // The Close operation shouldn't fail.  So we stop if it happens.
    Die("Close failed: ", status);
  }

  return 0;
}

// END OF FILE