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 *****************************/
39 #include "df_filter.h"
42 std::vector<String> tokenize(String line)
44 std::vector<String> words;
45 int l; // letter index in line
52 while (l < ~line && isspace(line[l]))
59 while (l < ~line && !isspace(line[l]))
64 String w = line(start, length);
70 // Find a regular expression in a vector of Strings
72 int findword(const std::vector<String> &tokens, const regex &pattern)
77 while (i < tokens.size() && !(tokens[i] == pattern))
82 if (i == tokens.size())
84 std::cerr << "Token not found.\n";
90 /*=========================================================================
91 ** NAME : constructXML
92 ** SYNOPSIS : int constructXML(message_buffer &in, strstream &xml)
94 ** RETURN VALUE : Create an XML document from output of 'df -k'
102 ** LAST MODIFIED : Nov 02, 2007
103 **=========================================================================
106 static const regex re_df_header("^Filesystem.+[Uu]se.+[Aa]vail.+Mounted");
107 static const regex re_df_i_header("^Filesystem +Inodes.+IUse.+Mounted");
108 static const regex re_df_data(".+ [0-9]+ +[0-9]+ +[0-9]+");
110 void df_filter::construct_XML(message_buffer &in, std::strstream &xml)
113 enum df_report_detection { NONE, BLOCKS, INODES };
115 df_report_detection report_type = NONE;
117 int field_position[4]; // Mountpoint, blocks, used, available
119 std::vector<String> tokens;
121 scan_email_header(in);
122 construct_header(xml);
124 xml << " <gcmt:data>\n";
125 xml << " <gcmt:parameters class='filesystem'>\n";
138 case NONE: // Header.
139 if (line == re_df_header)
141 report_type = BLOCKS;
142 tokens = tokenize(line);
143 // Make a map to find the fields we're interested in
144 field_position[0] = findword(tokens, regex("Mounted"));
145 field_position[1] = findword(tokens, regex("kbytes|-blocks"));
146 field_position[2] = findword(tokens, regex("[uU]se"));
147 field_position[3] = findword(tokens, regex("[aA]vail"));
149 if (line == re_df_i_header)
151 report_type = INODES;
152 tokens = tokenize(line);
153 // Make a map to find the fields we're interested in
154 field_position[0] = findword(tokens, regex("Mounted"));
155 field_position[1] = findword(tokens, regex("Inodes"));
156 field_position[2] = findword(tokens, regex("IUsed"));
157 field_position[3] = findword(tokens, regex("IFree"));
161 case BLOCKS: // df output lines.
162 tokens = tokenize(line);
163 if (tokens.size() > 4)
165 mountpoint = tokens[field_position[0]];
166 blocks = tokens[field_position[1]];
167 used = tokens[field_position[2]];
168 available = tokens[field_position[3]];
170 if (mountpoint[0] == '/')
173 // Create the XML element.
175 xml << " <gcmt:parameter name='" << mountpoint << "'>\n";
176 xml << " <gcmt:property name='device'>" << device << "</gcmt:property>\n";
177 xml << " <gcmt:property name='size'>" << blocks << "</gcmt:property>\n";
178 xml << " <gcmt:property name='used'>" << used << "</gcmt:property>\n";
179 xml << " <gcmt:property name='available'>" << available << "</gcmt:property>\n";
180 xml << " </gcmt:parameter>\n";
185 //cerr << "Mismatch on " << line << "\n";
189 case INODES: // df output lines.
190 tokens = tokenize(line);
191 if (tokens.size() > 4)
193 mountpoint = tokens[field_position[0]];
194 inodes = tokens[field_position[1]];
195 used = tokens[field_position[2]];
196 available = tokens[field_position[3]];
198 if (mountpoint[0] == '/')
201 // Create the XML element.
203 xml << " <gcmt:parameter name='" << mountpoint << "'>\n";
204 xml << " <gcmt:property name='device'>" << device << "</gcmt:property>\n";
205 xml << " <gcmt:property name='Inodes'>" << inodes << "</gcmt:property>\n";
206 xml << " <gcmt:property name='Iused'>" << used << "</gcmt:property>\n";
207 xml << " <gcmt:property name='Ifree'>" << available << "</gcmt:property>\n";
208 xml << " </gcmt:parameter>\n";
213 //cerr << "Mismatch on " << line << "\n";
218 xml << " </gcmt:parameters>\n";
219 xml << " </gcmt:data>\n";
220 xml << "</gcmt:message>\n";
224 bool df_cooker::check_pattern(String logline)
228 df_detected = (logline == re_df_data);
232 df_detected = (logline == re_df_header || logline == re_df_i_header);
238 bool df_cooker::cook_this(String logline, UTC arrival)