rb.rotate 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,201 @@
1
+ # encoding: utf-8
2
+
3
+ require "rb.rotate/configuration"
4
+ require "rb.rotate/file"
5
+ require "rb.rotate/reader"
6
+ require "rb.rotate/storage"
7
+
8
+ module RbRotate
9
+
10
+ ##
11
+ # Represents one log directory.
12
+ #
13
+
14
+ class Directory
15
+
16
+ ##
17
+ # Internal cache of the configuration.
18
+ #
19
+
20
+ @configuration
21
+
22
+ ##
23
+ # Parent configuration object.
24
+ #
25
+
26
+ @parent
27
+
28
+ ##
29
+ # Indicates, it isn't child directory of configured directory,
30
+ # but directly the configured directory.
31
+ #
32
+
33
+ @configured
34
+
35
+ ##
36
+ # Holds directory identifier.
37
+ #
38
+
39
+ @identifier
40
+ attr_reader :identifier
41
+
42
+ ##
43
+ # Holds directory path.
44
+ #
45
+
46
+ @path
47
+ attr_reader :path
48
+
49
+ ##
50
+ # Constructor.
51
+ #
52
+ # Identifier is symbol so identifier in configuration file or
53
+ # string, so directory path.
54
+ #
55
+
56
+ def initialize(identifier, parent = nil)
57
+ @parent = parent
58
+ if identifier.kind_of? Symbol
59
+ @identifier = identifier
60
+ else
61
+ @path = identifier
62
+ end
63
+ end
64
+
65
+ ##
66
+ # Returns the configuration instance.
67
+ #
68
+
69
+ def configuration
70
+ if @configuration.nil?
71
+ # If no identifier set, looks for the dir
72
+ # in configuration.
73
+ if @identifier.nil?
74
+ directory = Configuration::find_path(@path)
75
+
76
+ if not directory.nil?
77
+ @identifier = directory.identifier
78
+ @configured = true
79
+ elsif not @parent.nil?
80
+ @identifier = @parent.identifier
81
+ @configured = false
82
+ else
83
+ @identifier = :default
84
+ @configured = false
85
+ end
86
+ else
87
+ @configured = true
88
+ end
89
+
90
+ @configuration = DirectoryConfiguration::new(@identifier)
91
+ end
92
+
93
+ return @configuration
94
+ end
95
+
96
+ ##
97
+ # Indicates, it isn't child directory of configured directory,
98
+ # but directly the configured directory.
99
+ #
100
+
101
+ def configured?
102
+ self.configuration
103
+ @configured
104
+ end
105
+
106
+ ##
107
+ # Returns path to directory.
108
+ #
109
+ # So it get @path or directory from configuration if hasn't
110
+ # been sete.
111
+ #
112
+
113
+ def path
114
+ if not @path.nil?
115
+ @path
116
+ else
117
+ self.configuration.directory
118
+ end
119
+ end
120
+
121
+ ##
122
+ # Returns relative path to parent (configured) directory.
123
+ #
124
+
125
+ def relative_path
126
+ if self.configured?
127
+ "."
128
+ else
129
+ self.path[(self.configured_ancestor.path.length + 1)..-1]
130
+ end
131
+ end
132
+
133
+ ##
134
+ # Returns the "nearest" configured ancestor.
135
+ #
136
+
137
+ def configured_ancestor
138
+ if self.configured?
139
+ self
140
+ elsif not @parent.nil?
141
+ @parent.configured_ancestor
142
+ else
143
+ nil
144
+ end
145
+ end
146
+
147
+ ##
148
+ # Traverses through all files in directory.
149
+ #
150
+
151
+ def each_file(&block)
152
+ Reader::read(self, :filter => :files, &block)
153
+ end
154
+
155
+ ##
156
+ # Traverses through all directories in directory.
157
+ #
158
+
159
+ def each_directory(&block)
160
+ Reader::read(self, :filter => :dirs, &block)
161
+ end
162
+
163
+ ##
164
+ # Rotates.
165
+ #
166
+
167
+ def rotate!
168
+ # Cleans old or expired items
169
+ # self.storage.cleanup! (cleaned up globally by dispatcher call)
170
+
171
+ # Rotates
172
+ if self.configuration[:recursive]
173
+ self.each_directory do |directory|
174
+ directory.rotate!
175
+ end
176
+ end
177
+ self.each_file do |file|
178
+ file.rotate!
179
+ end
180
+ end
181
+
182
+ ##
183
+ # Indicates, directory entries should be compressed
184
+ # in archive.
185
+ #
186
+
187
+ def compressable?
188
+ not self.configuration[:compress].nil?
189
+ end
190
+
191
+ ##
192
+ # Returns storage appropriate to directory.
193
+ #
194
+
195
+ def storage
196
+ Storage::get(self)
197
+ end
198
+
199
+ end
200
+
201
+ end
@@ -0,0 +1,112 @@
1
+ # encoding: utf-8
2
+
3
+ module RbRotate
4
+
5
+ ##
6
+ # Dispatches all operations.
7
+ #
8
+
9
+ class Dispatcher
10
+
11
+ ##
12
+ # Runs the rotate session.
13
+ #
14
+
15
+ def run!
16
+ require "rb.rotate/configuration"
17
+ require "rb.rotate/state"
18
+ require "rb.rotate/storage"
19
+ require "rb.rotate/log"
20
+
21
+ # Reads configuration file
22
+ locator = ::File.dirname(::File.dirname(__FILE__)).dup << "/paths.conf"
23
+ if not ::File.exists? locator
24
+ STDERR.write("FATAL: rb.rotate unconfigured. Please, run 'rb.rotate install' or eventually create the " << locator << " file with path to configuration file. Aborted.\n")
25
+ exit
26
+ end
27
+
28
+ path = ::File.read(locator)
29
+ path.strip!
30
+
31
+ Configuration::read(path)
32
+ log "Configuration file loaded."
33
+
34
+ # Process
35
+ log "Start of processing."
36
+ Configuration::each_directory do |directory|
37
+ begin
38
+ directory.rotate!
39
+ rescue Exception => e
40
+ log "Exception: " << e.to_s
41
+ end
42
+ end
43
+
44
+ # Removes orhpans
45
+ log "Start of orphans removing."
46
+ Storage::remove_orphans!
47
+
48
+ # Saves state file
49
+ State::save!
50
+ log "New state saved."
51
+ end
52
+
53
+ ##
54
+ # Installs the application configuration files.
55
+ #
56
+
57
+ def install!
58
+ require "sys/uname"
59
+ require "fileutils"
60
+
61
+ basedir = ::File.dirname(__FILE__)
62
+
63
+ # Loads and creates the configuration dir
64
+ case Sys::Uname.sysname.downcase.to_sym
65
+ when :freebsd
66
+ etc = "/usr/local/etc"
67
+ when :linux
68
+ etc = "/etc"
69
+ else
70
+ raise Exception::new("You are running on an unknown platform. It cannot be problem, but it's necessary define path to configuration file and define paths in configuration file.")
71
+ end
72
+
73
+ etc << "/rb.rotate"
74
+ FileUtils.mkdir_p(etc)
75
+
76
+ # Creates other important directories
77
+ FileUtils.mkdir_p("/var/log")
78
+ FileUtils.mkdir_p("/var/lib")
79
+
80
+ # Puts configuration files to configuration directory
81
+ source = basedir.dup << "/install"
82
+ replacements = { "%%configuration" => etc }
83
+ files = ["rotate.yaml", "defaults.yaml"]
84
+
85
+ files.each do |file|
86
+ body = ::File.read(source.dup << "/" << file << ".initial")
87
+ replacements.each_pair do |key, value|
88
+ body.gsub! key, value
89
+ end
90
+ ::File.open(etc.dup << "/" << file, "w") do |io|
91
+ io.write(body)
92
+ end
93
+ end
94
+
95
+ # Puts to library root path path to configuration directory
96
+ ::File.open(basedir.dup << "/../paths.conf", "w") do |io|
97
+ io.write(etc.dup << "/rotate.yaml")
98
+ end
99
+ end
100
+
101
+ ##
102
+ # Prints out system name.
103
+ #
104
+
105
+ def sysname!
106
+ require "sys/uname"
107
+ puts Sys::Uname.sysname.downcase
108
+ end
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,174 @@
1
+ # encoding: utf-8
2
+
3
+ require "fileutils"
4
+ require "rb.rotate/storage"
5
+ require "rb.rotate/directory"
6
+ require "rb.rotate/configuration"
7
+
8
+ module RbRotate
9
+
10
+ ##
11
+ # Represents one log file.
12
+ #
13
+
14
+ class File
15
+
16
+ ##
17
+ # Holds parent file directory.
18
+ #
19
+
20
+ @directory
21
+
22
+ ##
23
+ # Indicates file path.
24
+ #
25
+
26
+ @path
27
+ attr_reader :path
28
+
29
+ ##
30
+ # Holds state for the file.
31
+ #
32
+
33
+ @state
34
+
35
+ ##
36
+ # Holds stat informations about the (original) file.
37
+ #
38
+
39
+ @stat
40
+
41
+ ##
42
+ # Constructor.
43
+ #
44
+
45
+ def initialize(path, directory = nil)
46
+ @directory = directory
47
+ @path = path
48
+ @stat = ::File.stat(@path.to_s)
49
+ end
50
+
51
+ ##
52
+ # Returns the file parent directory object.
53
+ #
54
+
55
+ def directory
56
+ if @directory.nil?
57
+ if not self.state.directory.nil?
58
+ @directory = Directory::new(self.state.directory)
59
+ else
60
+ @directory = Configuration::find_path(::File.dirname(@path.to_s))
61
+ end
62
+
63
+ if @directory.nil?
64
+ raise Exception::new("File from directory which isn't covered by rb.rotate found: " << @path.to_s << ".")
65
+ end
66
+ end
67
+
68
+ return @directory
69
+ end
70
+
71
+ ##
72
+ # Removes the file from medium.
73
+ #
74
+
75
+ def remove!
76
+ FileUtils.remove_file(@path)
77
+ return @path
78
+ end
79
+
80
+ ##
81
+ # Creates new file.
82
+ #
83
+
84
+ def create!
85
+ ::File.open(@path, "w").close()
86
+
87
+ # Sets access rights and ownership according to
88
+ # stat information
89
+ if not @stat.nil?
90
+ ::FileUtils.chmod(@stat.mode, @path)
91
+ ::FileUtils.chown(@stat.uid, @stat.gid, @path)
92
+ end
93
+
94
+ return @path
95
+ end
96
+
97
+ ##
98
+ # Truncates file.
99
+ #
100
+
101
+ alias :"truncate!" :"create!"
102
+
103
+ ##
104
+ # Rotates the file.
105
+ #
106
+
107
+ def rotate!
108
+ if self.archivable?
109
+ self.archive!
110
+ end
111
+ end
112
+
113
+ ##
114
+ # Archives file.
115
+ #
116
+
117
+ def archive!
118
+ Storage::put(self)
119
+ end
120
+
121
+ ##
122
+ # Indicates, file is suitable for immediate archiving.
123
+ #
124
+
125
+ def archivable?
126
+ self.too_big? or self.too_old?
127
+ end
128
+
129
+ ##
130
+ # Indicates, file is bigger than is allowed.
131
+ #
132
+
133
+ def too_big?
134
+ ::File.size(@path) > @directory.configuration[:"max size"].to_bytes
135
+ end
136
+
137
+ ##
138
+ # Indicates, file is too old.
139
+ #
140
+
141
+ def too_old?
142
+ if self.state.exists?
143
+ period = @directory.configuration[:period].to_seconds
144
+ result = Time::at(self.state.date + period) < Time::now
145
+ else
146
+ result = false
147
+ end
148
+
149
+ return result
150
+ end
151
+
152
+ ##
153
+ # Returns state.
154
+ #
155
+
156
+ def state
157
+ if @state.nil?
158
+ @state = State::get.file(@path)
159
+ end
160
+
161
+ return @state
162
+ end
163
+
164
+ ##
165
+ # Indicates file exists.
166
+ #
167
+
168
+ def exists?
169
+ ::File.exists? @path.to_s
170
+ end
171
+
172
+ end
173
+
174
+ end