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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
module Groonga
module CommandLine
class Grndb
def initialize(argv)
@command, *@arguments = argv
@succeeded = true
@executed = false
@database_path = nil
end
def run
slop = create_slop
rest = nil
begin
rest = slop.parse(@arguments)
rescue Slop::Error
$stderr.puts($!.message)
return false
end
if slop.help?
$stdout.puts(slop.help)
return true
end
unless @executed
if rest.empty?
$stderr.puts("No command is specified.")
else
$stderr.puts("Unknown command: <#{rest.first}>")
end
return false
end
@succeeded
end
private
def create_slop
slop = Slop.new
command_name = File.basename(@command)
slop.banner = "Usage: #{command_name} COMMAND [OPTIONS] DB_PATH"
slop_enable_help(slop)
slop.command "check" do |command|
command.description "Check database"
slop_enable_help(command)
command.run do |options, arguments|
run_command(options, arguments) do |database, new_arguments|
check(database, options, new_arguments)
end
end
end
slop.command "recover" do |command|
command.description "Recover database"
slop_enable_help(command)
command.run do |options, arguments|
run_command(options, arguments) do |database, new_arguments|
recover(database, options, new_arguments)
end
end
end
slop
end
def slop_enable_help(slop)
slop.on("-h", "--help", "Display this help message.", :tail => true)
end
def open_database(arguments)
if arguments.empty?
$stderr.puts("Database path is missing")
@succeesed = false
return
end
database = nil
@database_path, *rest_arguments = arguments
begin
database = Database.open(@database_path)
rescue Error => error
$stderr.puts("Failed to open database: <#{@database_path}>")
$stderr.puts(error.message)
@succeeded = false
return
end
begin
yield(database, rest_arguments)
ensure
database.close
end
end
def run_command(options, arguments)
@executed = true
if options.help?
$stdout.puts(options.help)
return
end
open_database(arguments) do |database|
yield(database)
end
end
def recover(database, options, arguments)
begin
database.recover
rescue Error => error
$stderr.puts("Failed to recover database: <#{@database_path}>")
$stderr.puts(error.message)
@succeeded = false
end
end
def check(database, options, arguments)
if database.locked?
message =
"Database is locked. " +
"It may be broken. " +
"Re-create the database."
$stdout.puts(message)
@succeeded = false
end
database.each do |object|
case object
when IndexColumn
next unless object.locked?
message =
"[#{object.name}] Index column is locked. " +
"It may be broken. " +
"Re-create index by '#{@command} recover #{@database_path}'."
$stdout.puts(message)
@succeeded = false
when Column
next unless object.locked?
name = object.name
message =
"[#{name}] Data column is locked. " +
"It may be broken. " +
"(1) Truncate the column (truncate #{name}) or " +
"clear lock of the column (lock_clear #{name}) " +
"and (2) load data again."
$stdout.puts(message)
@succeeded = false
when Table
next unless object.locked?
name = object.name
message =
"[#{name}] Table is locked. " +
"It may be broken. " +
"(1) Truncate the table (truncate #{name}) or " +
"clear lock of the table (lock_clear #{name}) " +
"and (2) load data again."
$stdout.puts(message)
@succeeded = false
end
end
end
end
end
end
|