host/common/win32/diskslayoutupdaterimp.cpp (392 lines of code) (raw):
#include <string>
#include <iostream>
#include <algorithm>
#include <boost/spirit/include/classic.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/phoenix1_primitives.hpp>
#include <boost/spirit/include/phoenix1_functions.hpp>
#include "diskslayoutupdaterimp.h"
#include "configurevxagent.h"
#include "configurecxagent.h"
#include "disklabeldefines.h"
#include "devicestream.h"
#include "filterdrvifmajor.h"
#include "devicefilter.h"
#include "logger.h"
#include "portablehelpers.h"
#include "portablehelpersmajor.h"
#include "dlmapi.h"
#include "volumegroupsettings.h"
#include "genericstream.h"
#include "transportstream.h"
#include "compressmode.h"
#include "FileConfigurator.h"
#include "localconfigurator.h"
#include "HttpFileTransfer.h"
#include "configwrapper.h"
#include "inmalertdefs.h"
#include "setpermissions.h"
using namespace BOOST_SPIRIT_CLASSIC_NS;
void CreateTransportStream(boost::shared_ptr<TransportStream> &ts, const TRANSPORT_PROTOCOL &tp,
const TRANSPORT_CONNECTION_SETTINGS &tss, const VOLUME_SETTINGS::SECURE_MODE &securemode);
DisksLayoutUpdaterImp::DisksLayoutUpdaterImp(Configurator* configurator)
: m_Configurator(configurator),
m_IsUploading(m_Configurator->getVxAgent().getSerializerType() != Xmlize)
{
}
DisksLayoutUpdaterImp::~DisksLayoutUpdaterImp()
{
}
void DisksLayoutUpdaterImp::Update(const std::string &diskslayoutoption, Options_t & statusmap)
{
UpdateDiskLabels_t udls[] = {&DisksLayoutUpdaterImp::DummyUpdateDiskLabels, &DisksLayoutUpdaterImp::UpdateDiskLabels};
UpdateDiskLabels_t uld = udls[m_Configurator->getVxAgent().registerLabelOnDisks()];
(this->*uld)(diskslayoutoption, statusmap);
}
void DisksLayoutUpdaterImp::Clear(const Options_t & statusmap)
{
Clear_t clearFunctions[] = {&DisksLayoutUpdaterImp::ClearInNoUpload, &DisksLayoutUpdaterImp::ClearInUpload};
Clear_t clearFunction = clearFunctions[m_IsUploading];
(this->*clearFunction)(statusmap);
}
void DisksLayoutUpdaterImp::DummyUpdateDiskLabels(const std::string &diskslayoutoption, Options_t & statusmap)
{
DebugPrintf( SV_LOG_DEBUG, "%s called\n", FUNCTION_NAME);
}
void DisksLayoutUpdaterImp::UpdateDiskLabels(const std::string &diskslayoutoption, Options_t & statusmap)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
std::stringstream labelFileNamePath;
std::string labelInfoDirName, labelFileName;
GetDiskLayoutFilePath_t pathFunctions[] = {&DisksLayoutUpdaterImp::GetDiskLayoutFilePathInNoUpload, &DisksLayoutUpdaterImp::GetDiskLayoutFilePathInUpload};
GetDiskLayoutFilePath_t pathFunction = pathFunctions[m_IsUploading];
DeleteOldDisksLayoutFiles_t delFunctions[] = {&DisksLayoutUpdaterImp::DeleteOldDisksLayoutFilesInNoUpload, &DisksLayoutUpdaterImp::DeleteOldDisksLayoutFilesInUpload};
DeleteOldDisksLayoutFiles_t delFunction = delFunctions[m_IsUploading];
ProcessDisksLayoutFiles_t createdFunctions[] = {&DisksLayoutUpdaterImp::ProcessCreatedFilesInNoUpload, &DisksLayoutUpdaterImp::ProcessCreatedFilesInUpload};
ProcessDisksLayoutFiles_t createdFunction = createdFunctions[m_IsUploading];
ProcessDisksLayoutFiles_t notCreatedFunctions[] = {&DisksLayoutUpdaterImp::ProcessNotCreatedFilesInNoUpload, &DisksLayoutUpdaterImp::ProcessNotCreatedFilesInUpload};
ProcessDisksLayoutFiles_t notCreatedFunction = notCreatedFunctions[m_IsUploading];
(this->*pathFunction)(labelFileNamePath);
securitylib::setPermissions(labelFileNamePath.str(), securitylib::SET_PERMISSIONS_NAME_IS_DIR);
labelInfoDirName = labelFileNamePath.str();
DebugPrintf(SV_LOG_DEBUG, "disks label file directory is %s\n", labelInfoDirName.c_str());
labelFileName = getDiskLayoutFileNameWOPath();
DebugPrintf(SV_LOG_DEBUG, "disks label base file name is %s\n", labelFileName.c_str());
labelFileNamePath << char(ACE_DIRECTORY_SEPARATOR_CHAR) << labelFileName;
DebugPrintf(SV_LOG_DEBUG, "disks layout file name formed is %s, diskslayoutoption is %s\n", labelFileNamePath.str().c_str(),
diskslayoutoption.c_str());
std::list<std::string> erraticVolumeGuids ;
std::list<std::string> outFileNames ;
DLM_ERROR_CODE ec = StoreDisksInfo(labelFileNamePath.str(), outFileNames, erraticVolumeGuids, diskslayoutoption);
DebugPrintf(SV_LOG_DEBUG, "StoreDisksInfo returned %d for disks layout file %s\n", ec, labelFileNamePath.str().c_str());
DebugPrintf(SV_LOG_DEBUG, "erraticVolumeGuids:\n");
for_each(erraticVolumeGuids.begin(), erraticVolumeGuids.end(), PrintString);
DebugPrintf(SV_LOG_DEBUG, "outFileNames:\n");
for_each(outFileNames.begin(), outFileNames.end(), PrintString);
/* TODO: handle labelandcreatefiles being of size zero ?
* Currently trust the api for this */
if(DLM_FILE_CREATED == ec) {
DebugPrintf(SV_LOG_DEBUG, "New disk layout file(s) have been created by disk layout manager\n");
AlertCxToErraticVolumes(erraticVolumeGuids);
(this->*delFunction)(outFileNames, labelInfoDirName);
(this->*createdFunction)(labelFileName, outFileNames, statusmap);
} else if (DLM_FILE_NOT_CREATED == ec) {
DebugPrintf(SV_LOG_DEBUG, "New disk layout file(s) are not created by disk layout manager\n");
AlertCxToErraticVolumes(erraticVolumeGuids);
(this->*notCreatedFunction)(labelFileName, outFileNames, statusmap);
} else {
DebugPrintf(SV_LOG_ERROR, "Getting %s from disk layout manager failed with DLM_ERROR_CODE: %d."
" Setting the status as failure to CS\n", labelFileNamePath.str().c_str(), ec);
statusmap.insert(std::make_pair(NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_KEY, labelFileName+std::string(1, NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_SEP)+NSRegisterHostStaticInfo::FAILURE));
}
DebugPrintf( SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}
void DisksLayoutUpdaterImp::GetDiskLayoutFilePathInNoUpload(std::stringstream & labelFileNamePath)
{
FileConfigurator lc ;
labelFileNamePath << lc.getRepositoryLocation() ;
if( labelFileNamePath.str().length() == 1 )
{
labelFileNamePath << ":" ;
}
labelFileNamePath << ACE_DIRECTORY_SEPARATOR_CHAR_A ;
labelFileNamePath << LABELFILESDIR;
labelFileNamePath << ACE_DIRECTORY_SEPARATOR_CHAR_A ;
labelFileNamePath << m_Configurator->getVxAgent().getHostId();
}
void DisksLayoutUpdaterImp::GetDiskLayoutFilePathInUpload(std::stringstream & labelFileNamePath)
{
labelFileNamePath << m_Configurator->getVxAgent().getCacheDirectory() << char(ACE_DIRECTORY_SEPARATOR_CHAR)
<< LABELFILESDIR << char(ACE_DIRECTORY_SEPARATOR_CHAR) << m_Configurator->getVxAgent().getHostId();
}
std::string DisksLayoutUpdaterImp::getDiskLayoutFileNameWOPath(void)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
int iStatus = SV_SUCCESS;
std::string strDriverTime;
std::stringstream diskLayoutFile;
do
{
diskLayoutFile << LABELFILENAMEPREFIX;
//Look for disk filter and then volume filter
DeviceStream *p = 0;
DeviceStream volumeFilterStream(Device(INMAGE_FILTER_DEVICE_NAME));
DeviceStream diskFilterStream(Device(INMAGE_DISK_FILTER_DOS_DEVICE_NAME));
//If disk filter driver opens, get time stamp from it; else use volume filter driver
if (SV_SUCCESS == diskFilterStream.Open(DeviceStream::Mode_Open | DeviceStream::Mode_RW | DeviceStream::Mode_ShareRW)) {
DebugPrintf(SV_LOG_INFO, "Opened disk filter driver.\n");
p = &diskFilterStream;
}
else if (SV_SUCCESS == volumeFilterStream.Open(DeviceStream::Mode_Open | DeviceStream::Mode_RW | DeviceStream::Mode_ShareRW)) {
DebugPrintf(SV_LOG_INFO, "Opened volume filter driver.\n");
p = &volumeFilterStream;
}
else {
//Use system time if drivers are not present.
DebugPrintf(SV_LOG_ERROR, "Failed to open disk filter driver %s with error %d and failed to open volume filter %s driver with error %d. Hence using system time.\n",
diskFilterStream.GetName().c_str(), diskFilterStream.GetErrorCode(), volumeFilterStream.GetName().c_str(), volumeFilterStream.GetErrorCode());
diskLayoutFile << getSystemTimeInUtc();
break;
}
DRIVER_GLOBAL_TIMESTAMP driverTime;
FilterDrvIfMajor drvif;
iStatus = drvif.getDriverTime(*p, &driverTime);
if ( SV_SUCCESS == iStatus)
{
//DebugPrintf( SV_LOG_DEBUG, "DriverTime %llu SeqNo %llu\n", driverTime.TimeInHundNanoSecondsFromJan1601, driverTime.ullSequenceNumber);
ConvertTimeToString(driverTime.TimeInHundNanoSecondsFromJan1601, strDriverTime);
diskLayoutFile << strDriverTime;
diskLayoutFile << "_" << driverTime.ullSequenceNumber;
break;
}
else if ( ERR_INVALID_FUNCTION == iStatus)
{
DebugPrintf(SV_LOG_ERROR,"IOCTL_INMAGE_GET_GLOBAL_TIMESTAMP not supported, using system time\n");
diskLayoutFile << getSystemTimeInUtc();
break;
}
DebugPrintf( SV_LOG_DEBUG, "IOCTL_INMAGE_GET_GLOBAL_TIMESTAMP failed: %d\n", iStatus);
// else don't use any time string
} while (FALSE);
DebugPrintf( SV_LOG_DEBUG, "diskLayoutFile %s\n", diskLayoutFile.str().c_str());
DebugPrintf( SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
return diskLayoutFile.str();
}
void DisksLayoutUpdaterImp::AlertCxToErraticVolumes(const std::list<std::string> & erraticVolumeGuids)
{
std::list<std::string>::const_iterator erraticVolGuidIter ;
erraticVolGuidIter = erraticVolumeGuids.begin() ;
std::string guids;
const char SEP = ',';
while( erraticVolGuidIter != erraticVolumeGuids.end() ) {
guids += *erraticVolGuidIter;
guids += SEP;
erraticVolGuidIter++ ;
}
if (!erraticVolumeGuids.empty()) {
guids.erase(guids.end()-1);
ErraticVolumesGUIDAlert a(guids);
SendAlertToCx(SV_ALERT_ERROR, SV_ALERT_MODULE_HOST_REGISTRATION, a);
}
}
void DisksLayoutUpdaterImp::DeleteOldDisksLayoutFilesInNoUpload(const std::list<std::string> &latestfiles, const std::string &directory)
{
return;
}
void DisksLayoutUpdaterImp::DeleteOldDisksLayoutFilesInUpload(const std::list<std::string> &latestfiles, const std::string &directory)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
std::string errmsg;
std::string fileindirectory, readdirentry;
ACE_DIR * ace_dir = NULL ;
ACE_DIRENT * dirent = NULL ;
ace_dir = sv_opendir(directory.c_str()) ;
if( ace_dir ) {
for(dirent = ACE_OS::readdir(ace_dir); dirent != NULL; dirent = ACE_OS::readdir(ace_dir)) {
readdirentry = ACE_TEXT_ALWAYS_CHAR(dirent->d_name);
if ((readdirentry == ".") || (readdirentry == ".."))
continue;
fileindirectory = directory + ACE_DIRECTORY_SEPARATOR_CHAR_A + readdirentry;
/* TODO: write a generic operation on file function with respect to containers */
if (latestfiles.end() == std::find(latestfiles.begin(), latestfiles.end(), fileindirectory)) {
if (InmRemoveFile(fileindirectory, errmsg))
DebugPrintf(SV_LOG_DEBUG, "Removed older disks layout file %s successfully\n", fileindirectory.c_str());
else
DebugPrintf(SV_LOG_ERROR, "Removing old disks layout file file %s failed with error: %s\n", fileindirectory.c_str(), errmsg.c_str());
}
}
ACE_OS::closedir( ace_dir ) ;
} else
DebugPrintf(SV_LOG_ERROR, "opening directory %s failed with error number %d\n", directory.c_str(), ACE_OS::last_error());
DebugPrintf( SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}
void DisksLayoutUpdaterImp::ProcessCreatedFilesInNoUpload(const std::string &labelfile,
const std::list<std::string> &labelfileandrelatedfiles, Options_t &statusmap)
{
return;
}
void DisksLayoutUpdaterImp::ProcessCreatedFilesInUpload(const std::string &labelfile,
const std::list<std::string> &labelfileandrelatedfiles, Options_t &statusmap)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
SetExistingFiles(labelfileandrelatedfiles);
std::vector<std::string>::size_type nfilesexisting = m_ExistingFiles.size();
if (nfilesexisting == 0) {
DebugPrintf(SV_LOG_ERROR, "Disk layout manager has not created any label file, out of the said \"created\", for file %s."
" Setting the status as failure to CS\n", labelfile.c_str());
statusmap.insert(std::make_pair(NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_KEY, labelfile+std::string(1, NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_SEP)+NSRegisterHostStaticInfo::FAILURE));
} else if (nfilesexisting < labelfileandrelatedfiles.size()) {
DebugPrintf(SV_LOG_DEBUG, "Disk layout manager has created less number of files, out of the said \"created\", for file %s."
" Considering this as case where label file has reference to already sent file(s). Uploading the existing ones.\n", labelfile.c_str());
UploadExistingFiles(labelfile, statusmap);
} else
UploadExistingFiles(labelfile, statusmap);
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}
void DisksLayoutUpdaterImp::ProcessNotCreatedFilesInNoUpload(const std::string &labelfile, const std::list<std::string> &labelfileandrelatedfiles, Options_t &statusmap)
{
return;
}
void DisksLayoutUpdaterImp::ProcessNotCreatedFilesInUpload(const std::string &labelfile, const std::list<std::string> &labelfileandrelatedfiles, Options_t &statusmap)
{
DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
SetExistingFiles(labelfileandrelatedfiles);
std::vector<std::string>::size_type nfilesexisting = m_ExistingFiles.size();
if (nfilesexisting == 0) {
DebugPrintf(SV_LOG_DEBUG, "Disk layout manager has not created new label files for file %s. "
"Considering these as already uploaded earlier.\n", labelfile.c_str());
} else {
DebugPrintf(SV_LOG_DEBUG, "Although disks layout manager said, \"no files created\", "
"for disks layout file %s, all or some previous files are present. "
"Hence uploading these, considering that these were not, or partially, uploaded (or) "
"local deletion failed earlier after upload(NOTE: In this case, this is overwrite).\n", labelfile.c_str());
UploadExistingFiles(labelfile, statusmap);
}
DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}
void DisksLayoutUpdaterImp::SetExistingFiles(const std::list<std::string> &labelfileandrelatedfiles)
{
m_ExistingFiles = for_each(labelfileandrelatedfiles.begin(), labelfileandrelatedfiles.end(), CollectExistingFiles());
std::vector<std::string>::size_type nfilesexisting = m_ExistingFiles.size();
DebugPrintf(SV_LOG_DEBUG, "Below are the existing files out of the outFileNames:\n");
for (std::vector<std::string>::size_type i = 0; i < nfilesexisting; i++) {
DebugPrintf(SV_LOG_DEBUG, "%s\n", m_ExistingFiles[i].c_str());
const std::string &baseexistingname = basename_r(m_ExistingFiles[i].c_str());
if (IsLabelFileForStatus(baseexistingname)) {
m_LabelFileForStatus = baseexistingname;
DebugPrintf(SV_LOG_DEBUG, "Label file to send status is %s\n", m_LabelFileForStatus.c_str());
}
}
}
void DisksLayoutUpdaterImp::DeleteExistingFiles(const SV_LOG_LEVEL &loglevel)
{
std::string errmsg;
std::vector<std::string>::size_type nfilesexisting = m_ExistingFiles.size();
for (std::vector<std::string>::size_type i = 0; i < nfilesexisting; i++) {
const std::string &existingfile = m_ExistingFiles[i];
if (InmRemoveFile(existingfile, errmsg))
DebugPrintf(loglevel, "Deleted %s successfully, as this was an uploaded disks layout file.\n", existingfile.c_str());
else
DebugPrintf(SV_LOG_ERROR, "Failed to delete an uploaded disks layout file %s with error %s\n", existingfile.c_str(), errmsg.c_str());
}
}
void DisksLayoutUpdaterImp::UploadExistingFiles(const std::string &labelfile, Options_t &statusmap)
{
FileUpload(labelfile, statusmap);
}
void DisksLayoutUpdaterImp::FileUpload(const std::string &labelfile, Options_t &statusmap)
{
DebugPrintf(SV_LOG_DEBUG,"Entered %s\n",__FUNCTION__);
bool res = true ;
std::string labelremotedir;
const char *status = NSRegisterHostStaticInfo::SUCCESS;
LocalConfigurator lc ;
bool bHttps = lc.IsHttps();
//Find CX Ip from Local Configurtaor
HTTP_CONNECTION_SETTINGS s = m_Configurator->getHttpSettings();
std::string strCxIpAddress(s.ipAddress) ;
//Find CX port number
std::string httpPortNumber = boost::lexical_cast<std::string>(s.port) ;
boost::shared_ptr<FileTransfer> ftPtr(new HttpFileTransfer(bHttps,strCxIpAddress,httpPortNumber));
if(ftPtr->Init())
{
labelremotedir = LABELFILESREMOTEDIR + LABELFILESDIR + '/' + m_Configurator->getVxAgent().getHostId() ;
std::vector<std::string>::size_type nfilesexisting = m_ExistingFiles.size();
for (std::vector<std::string>::size_type i = 0; i < nfilesexisting; i++)
{
const std::string ¤tPath = m_ExistingFiles[i];
DebugPrintf(SV_LOG_DEBUG, "sending label file %s, in remote directory %s\n",
currentPath.c_str(), labelremotedir.c_str());
if ( !ftPtr->Upload( labelremotedir,currentPath ) )
{
res = false ;
DlmFileUploadFailedAlert a(currentPath, labelremotedir, strCxIpAddress, s.port, bHttps);
DebugPrintf(SV_LOG_ERROR, "%s\n", a.GetMessage().c_str());
SendAlertToCx(SV_ALERT_CRITICAL, SV_ALERT_MODULE_HOST_REGISTRATION, a);
break ;
}
else
{
DebugPrintf(SV_LOG_DEBUG, "successfully sent label file %s, in remote directory %s\n",
currentPath.c_str(), labelremotedir.c_str());
}
}
}
if(!res)
{
status = NSRegisterHostStaticInfo::FAILURE;
}
if (m_LabelFileForStatus.empty())
DebugPrintf(SV_LOG_ERROR, "Could not find label file to send status to CS for label file %s\n", labelfile.c_str());
else
statusmap.insert(std::make_pair(NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_KEY, m_LabelFileForStatus+std::string(1, NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_SEP)+status));
DebugPrintf(SV_LOG_DEBUG,"Exiting %s\n",__FUNCTION__);
}
void DisksLayoutUpdaterImp::ClearInNoUpload(const Options_t & statusmap)
{
return;
}
void DisksLayoutUpdaterImp::ClearInUpload(const Options_t & statusmap)
{
DebugPrintf( SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME);
Options_t::const_iterator it = statusmap.find(NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_KEY);
if (it != statusmap.end()) {
const std::string &value = it->second;
DebugPrintf(SV_LOG_DEBUG, "While clearing disks layout files, found disks layout status key %s with value %s\n",
NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_KEY, value.c_str());
ClearIfFilesWereUploaded(value);
} else {
DebugPrintf(SV_LOG_DEBUG, "While clearing disks layout files, did not find disks layout status key %s."
" There were no uploads.\n", NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_KEY);
}
DebugPrintf( SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME);
}
void DisksLayoutUpdaterImp::ClearIfFilesWereUploaded(const std::string &filewithstatus)
{
char sep;
std::string revfilename, revstatus;
const std::string s(NSRegisterHostStaticInfo::SUCCESS);
const std::string f(NSRegisterHostStaticInfo::FAILURE);
strlit<std::string::const_reverse_iterator> revsuccess(s.rbegin(), s.rend());
strlit<std::string::const_reverse_iterator> revfailure(f.rbegin(), f.rend());
bool parsed = parse(filewithstatus.rbegin(), filewithstatus.rend(),
lexeme_d
[
(revsuccess | revfailure) [phoenix::var(revstatus) = phoenix::construct_<std::string>(phoenix::arg1,phoenix::arg2)]
>> ch_p(NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_SEP) [phoenix::var(sep) = phoenix::arg1]
>> (+anychar_p) [phoenix::var(revfilename) = phoenix::construct_<std::string>(phoenix::arg1,phoenix::arg2)]
] >> end_p,
space_p).full;
if (parsed) {
std::string filename(revfilename.rbegin(), revfilename.rend());
std::string status(revstatus.rbegin(), revstatus.rend());
DebugPrintf(SV_LOG_DEBUG, "for cleanup, disks label file name is %s, upload status %s\n", filename.c_str(), status.c_str());
if (s == status) {
DebugPrintf(SV_LOG_DEBUG, "Deleting label files as these were uploaded successfully\n");
DeleteExistingFiles(SV_LOG_DEBUG);
} else
DebugPrintf(SV_LOG_DEBUG, "Not deleting label files as these were not uploaded successfully\n");
} else
DebugPrintf(SV_LOG_ERROR, "The status value %s for key %s is invalid\n", filewithstatus.c_str(), NSRegisterHostStaticInfo::DISKS_LAYOUT_STATUS_KEY);
}
bool DisksLayoutUpdaterImp::IsLabelFileForStatus(const std::string &file)
{
strlit<std::string::const_iterator> prefixrule(LABELFILENAMEPREFIX.begin(), LABELFILENAMEPREFIX.end());
/* older driver does not support ioctl to give time
* and sequence number. Hence the disks layout file
* name in this case will contain system time and not
* sequence number */
return parse(file.begin(), file.end(),
lexeme_d [
prefixrule
>> +digit_p
>> !(ch_p('_') >> +digit_p)
] >> end_p,
space_p).full;
}