rb.rotate 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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