2 /**************************************************************************
3 ** (c) Copyright 2007, Andromeda Technology & Automation
4 ** This is free software; you can redistribute it and/or modify it under the
5 ** terms of the GNU General Public License, see the file COPYING.
6 ***************************************************************************
7 ** MODULE INFORMATION *
8 ***********************
9 ** FILE NAME : df_filter.cpp
11 ** VERSION NUMBER : $Revision: 1.1 $
13 ** DESCRIPTION : Transform output of 'df' into a Gnucomo XML document
18 ***************************************************************************
19 ** ADMINISTRATIVE INFORMATION *
20 ********************************
21 ** ORIGINAL AUTHOR : Arjen Baart - arjen@andromeda.nl
22 ** CREATION DATE : Oct 30, 2007
23 ** LAST UPDATE : Nov 02, 2007
25 **************************************************************************/
27 /*****************************
28 $Log: df_filter.cpp,v $
29 Revision 1.1 2007-11-03 10:26:13 arjen
30 Added a new filter which can directly read the output
31 of the UNIX df command. A brief description is added in
34 *****************************/
36 /* static const char *RCSID = "$Id: df_filter.cpp,v 1.1 2007-11-03 10:26:13 arjen Exp $"; */
41 #include "df_filter.h"
44 std::vector<String> tokenize(String line)
46 std::vector<String> words;
47 int l; // letter index in line
54 while (l < ~line && isspace(line[l]))
61 while (l < ~line && !isspace(line[l]))
66 String w = line(start, length);
72 // Find a regular expression in a vector of Strings
74 int findword(const std::vector<String> &tokens, const regex &pattern)
79 while (i < tokens.size() && !(tokens[i] == pattern))
84 if (i == tokens.size())
86 std::cerr << "Token not found.\n";
92 /*=========================================================================
93 ** NAME : constructXML
94 ** SYNOPSIS : int constructXML(message_buffer &in, strstream &xml)
96 ** RETURN VALUE : Create an XML document from output of 'df -k'
104 ** LAST MODIFIED : Nov 02, 2007
105 **=========================================================================
108 static const regex re_df_header("^Filesystem.+[Uu]se.+[Aa]vail.+Mounted");
109 static const regex re_df_i_header("^Filesystem +Inodes.+IUse.+Mounted");
110 static const regex re_df_data(".+ [0-9]+ +[0-9]+ +[0-9]+");
112 void df_filter::construct_XML(message_buffer &in, std::strstream &xml)
115 enum df_report_detection { NONE, BLOCKS, INODES };
117 df_report_detection report_type = NONE;
119 int field_position[4]; // Mountpoint, blocks, used, available
121 std::vector<String> tokens;
123 scan_email_header(in);
124 construct_header(xml);
126 xml << " <gcmt:data>\n";
127 xml << " <gcmt:parameters class='filesystem'>\n";
140 case NONE: // Header.
141 if (line == re_df_header)
143 report_type = BLOCKS;
144 tokens = tokenize(line);
145 // Make a map to find the fields we're interested in
146 field_position[0] = findword(tokens, regex("Mounted"));
147 field_position[1] = findword(tokens, regex("kbytes|-blocks"));
148 field_position[2] = findword(tokens, regex("[uU]se"));
149 field_position[3] = findword(tokens, regex("[aA]vail"));
151 if (line == re_df_i_header)
153 report_type = INODES;
154 tokens = tokenize(line);
155 // Make a map to find the fields we're interested in
156 field_position[0] = findword(tokens, regex("Mounted"));
157 field_position[1] = findword(tokens, regex("Inodes"));
158 field_position[2] = findword(tokens, regex("IUsed"));
159 field_position[3] = findword(tokens, regex("IFree"));
163 case BLOCKS: // df output lines.
164 tokens = tokenize(line);
165 if (tokens.size() > 4)
167 mountpoint = tokens[field_position[0]];
168 blocks = tokens[field_position[1]];
169 used = tokens[field_position[2]];
170 available = tokens[field_position[3]];
172 if (mountpoint[0] == '/')
175 // Create the XML element.
177 xml << " <gcmt:parameter name='" << mountpoint << "'>\n";
178 xml << " <gcmt:property name='device'>" << device << "</gcmt:property>\n";
179 xml << " <gcmt:property name='size'>" << blocks << "</gcmt:property>\n";
180 xml << " <gcmt:property name='used'>" << used << "</gcmt:property>\n";
181 xml << " <gcmt:property name='available'>" << available << "</gcmt:property>\n";
182 xml << " </gcmt:parameter>\n";
187 //cerr << "Mismatch on " << line << "\n";
191 case INODES: // df output lines.
192 tokens = tokenize(line);
193 if (tokens.size() > 4)
195 mountpoint = tokens[field_position[0]];
196 inodes = tokens[field_position[1]];
197 used = tokens[field_position[2]];
198 available = tokens[field_position[3]];
200 if (mountpoint[0] == '/')
203 // Create the XML element.
205 xml << " <gcmt:parameter name='" << mountpoint << "'>\n";
206 xml << " <gcmt:property name='device'>" << device << "</gcmt:property>\n";
207 xml << " <gcmt:property name='Inodes'>" << inodes << "</gcmt:property>\n";
208 xml << " <gcmt:property name='Iused'>" << used << "</gcmt:property>\n";
209 xml << " <gcmt:property name='Ifree'>" << available << "</gcmt:property>\n";
210 xml << " </gcmt:parameter>\n";
215 //cerr << "Mismatch on " << line << "\n";
220 xml << " </gcmt:parameters>\n";
221 xml << " </gcmt:data>\n";
222 xml << "</gcmt:message>\n";
225 bool df_cooker::check_pattern(String logline)
229 df_detected = (logline == re_df_data);
233 df_detected = (logline == re_df_header || logline == re_df_i_header);
239 bool df_cooker::cook_this(String logline, UTC arrival)