/src/lib/log/conf/log_file_rotated.e

http://github.com/tybor/Liberty · Specman e · 219 lines · 178 code · 17 blank · 24 comment · 10 complexity · 1892664b906e1b4ad116bf9c87d0700f MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class LOG_FILE_ROTATED
  5. inherit
  6. LOG_FILE_OPTION
  7. create {LOG_FILE_OPTIONS}
  8. make
  9. feature {LOG_FILE_OPTIONS, LOG_FILE_OPTION}
  10. retrieve (stream: OUTPUT_STREAM): OUTPUT_STREAM
  11. local
  12. s: STREAM
  13. file: FILE_STREAM
  14. do
  15. Result := parent.retrieve(stream)
  16. s := Result
  17. if file ?:= s then -- TODO: BERK (inheritance branch skipped)
  18. file ::= s
  19. if condition.item([file]) then
  20. s := rotate(file)
  21. Result ::= s
  22. end
  23. end
  24. end
  25. feature {}
  26. make (a_parent: like parent; a_condition: like condition; a_retention: like retention)
  27. require
  28. a_parent /= Void
  29. a_condition /= Void
  30. do
  31. parent := a_parent
  32. condition := a_condition
  33. retention := a_retention
  34. ensure
  35. parent = a_parent
  36. condition = a_condition
  37. retention = a_retention
  38. end
  39. parent: LOG_FILE_OPTION
  40. condition: PREDICATE[TUPLE[FILE_STREAM]]
  41. retention: INTEGER_64
  42. file_pattern (base_name: STRING): REGULAR_EXPRESSION
  43. local
  44. file_name: STRING; i: INTEGER; c: CHARACTER
  45. regex: REGULAR_EXPRESSION_BUILDER
  46. do
  47. file_name := once ""
  48. file_name.with_capacity(base_name.count + 20)
  49. file_name.copy(once "^")
  50. from
  51. i := base_name.lower
  52. until
  53. i > base_name.upper
  54. loop
  55. c := base_name.item(i)
  56. inspect
  57. c
  58. when '.', '\', '*', '+', '?', '{', '}', '|', '^', '$', '(', ')' then
  59. file_name.extend('\')
  60. file_name.extend(c)
  61. else
  62. file_name.extend(c)
  63. end
  64. i := i + 1
  65. end
  66. file_name.append(once "\.([0-9]+)(\..*)?$")
  67. Result := regex.convert_posix_pattern(file_name)
  68. end
  69. rotate (file: FILE_STREAM): FILE_STREAM
  70. require
  71. file.is_connected
  72. local
  73. file_name_pattern: REGULAR_EXPRESSION
  74. file_path, dir_name, file_name, new_file_name: STRING
  75. i: INTEGER
  76. do
  77. file_path := file.path
  78. file.disconnect
  79. dir_name := once ""
  80. bd.compute_parent_directory_of(file_path)
  81. if bd.last_entry.is_empty then
  82. dir_name.make_from_string(bd.current_working_directory)
  83. else
  84. dir_name.copy(bd.last_entry)
  85. end
  86. file_name := once ""
  87. bd.compute_short_name_of(file_path)
  88. file_name.copy(bd.last_entry)
  89. if retention /= 0 then
  90. last_index := 0
  91. file_name_pattern := file_pattern(file_name)
  92. from
  93. map(dir_name, file_name_pattern, agent set_last_index(?))
  94. i := last_index
  95. until
  96. i = 0
  97. loop
  98. map(dir_name, file_name_pattern, agent rotate_file(dir_name, file_name_pattern, i, ?, ?))
  99. i := i - 1
  100. end
  101. new_file_name := once ""
  102. new_file_name.copy(file_name)
  103. new_file_name.append(once ".1")
  104. bd.compute_file_path_with(dir_name, new_file_name)
  105. ft.rename_to(file_path, bd.last_entry)
  106. end
  107. create {TEXT_FILE_WRITE} Result.connect_to(file_path)
  108. do_at_exit(agent (file_: FILE_STREAM) do if file_.is_connected then file_.disconnect end end (Result))
  109. ensure
  110. Result /= file
  111. Result.is_connected
  112. not file.is_connected
  113. end
  114. map (dir_name: STRING; file_name_pattern: REGULAR_EXPRESSION; action: PROCEDURE[TUPLE[INTEGER, STRING]])
  115. -- non-Void if the file exists; in that case the result contains the exact name of the log file.
  116. require
  117. dir_name /= Void
  118. file_name_pattern /= Void
  119. action /= Void
  120. local
  121. buf, file_name: STRING
  122. do
  123. buf := once ""
  124. bd.connect_to(dir_name)
  125. if bd.is_connected then
  126. from
  127. file_name := once ""
  128. bd.read_entry
  129. until
  130. bd.end_of_input
  131. loop
  132. file_name.copy(bd.last_entry)
  133. if file_name_pattern.match(file_name) then
  134. buf.clear_count
  135. file_name_pattern.append_ith_group(file_name, buf, 1)
  136. check
  137. buf.is_integer
  138. end
  139. action.call([buf.to_integer, file_name])
  140. end
  141. bd.read_entry
  142. end
  143. bd.disconnect
  144. end
  145. end
  146. last_index: INTEGER
  147. set_last_index (index: INTEGER)
  148. do
  149. if index > last_index then
  150. last_index := index
  151. end
  152. end
  153. rotate_file (dir_name: STRING; file_name_pattern: REGULAR_EXPRESSION; at_index, index: INTEGER; file_name: STRING)
  154. require
  155. last_index > 0
  156. local
  157. path, new_file_name, new_index: STRING
  158. do
  159. if retention /= -1 and then index > retention then
  160. bd.compute_file_path_with(dir_name, file_name)
  161. ft.delete(bd.last_entry)
  162. elseif index = at_index then
  163. path := once ""
  164. bd.compute_file_path_with(dir_name, file_name)
  165. path.copy(bd.last_entry)
  166. new_index := once ""
  167. new_index.clear_count
  168. ;(index + 1).append_in(new_index)
  169. new_file_name := once ""
  170. new_file_name.copy(file_name)
  171. if file_name_pattern.match(new_file_name) then
  172. new_file_name.replace_substring(new_index, file_name_pattern.ith_group_first_index(1), file_name_pattern.ith_group_last_index(1))
  173. bd.compute_file_path_with(dir_name, new_file_name)
  174. ft.rename_to(path, bd.last_entry)
  175. else
  176. check False end
  177. end
  178. end
  179. end
  180. bd: BASIC_DIRECTORY
  181. ft: FILE_TOOLS
  182. end -- class LOG_FILE_ROTATED
  183. --
  184. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  185. --
  186. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  187. -- of this software and associated documentation files (the "Software"), to deal
  188. -- in the Software without restriction, including without limitation the rights
  189. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  190. -- copies of the Software, and to permit persons to whom the Software is
  191. -- furnished to do so, subject to the following conditions:
  192. --
  193. -- The above copyright notice and this permission notice shall be included in
  194. -- all copies or substantial portions of the Software.
  195. --
  196. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  197. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  198. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  199. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  200. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  201. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  202. -- THE SOFTWARE.