On Tue, Nov 20, 2012 at 11:26 AM, Iustin Pop <ius...@google.com> wrote:

> On Mon, Nov 19, 2012 at 03:19:51PM +0100, Michele Tartara wrote:
> > A new directory for haskell modules about block devices has been created
> > The parser is divided in two modules:
> > * one exports the data types describing the DRBD status
> > * one exports the parser itself
> >
> > Signed-off-by: Michele Tartara <mtart...@google.com>
> > ---
> >  Makefile.am                        |    8 +
> >  htools/Ganeti/Block/Drbd/Parser.hs |  333
> ++++++++++++++++++++++++++++++++++++
> >  htools/Ganeti/Block/Drbd/Types.hs  |  191 +++++++++++++++++++++
> >  3 files changed, 532 insertions(+), 0 deletions(-)
> >  create mode 100644 htools/Ganeti/Block/Drbd/Parser.hs
> >  create mode 100644 htools/Ganeti/Block/Drbd/Types.hs
>
> LGTM, I'll have a few small indentation fixes while pushing:
>
> > +-- | The parser for the version information lines.
> > +versionInfoParser :: Parser VersionInfo
> > +versionInfoParser =
> > +  VersionInfo
> > +    <$> optional versionP
> > +    <*> optional apiP
> > +    <*> optional protoP
> > +    <*> optional srcVersion
> > +    <*> (fmap unpack <$> optional gh)
> > +    <*> (fmap unpack <$> optional builder)
> > +    where versionP =
>
> Here "where" is indented right under '<*>'…
>
> > +-- | The parser for the connection state.
> > +connectionStateParser :: Parser ConnectionState
> > +connectionStateParser =
> > +  standAlone
> > +  <|> disconnecting
> > +  <|> unconnected
> > +  <|> timeout
> > +  <|> brokenPipe
> > +  <|> networkFailure
> > +  <|> protocolError
> > +  <|> tearDown
> > +  <|> wfConnection
> > +  <|> wfReportParams
> > +  <|> connected
> > +  <|> startingSyncS
> > +  <|> startingSyncT
> > +  <|> wfBitMapS
> > +  <|> wfBitMapT
> > +  <|> wfSyncUUID
> > +  <|> syncSource
> > +  <|> syncTarget
> > +  <|> pausedSyncS
> > +  <|> pausedSyncT
> > +  <|> verifyS
> > +  <|> verifyT
> > +  <|> unconfigured
> > +    where standAlone = A.string "StandAlone" *> pure StandAlone
> > +          disconnecting = A.string "Disconnectiog" *> pure Disconnecting
> > +          unconnected = A.string "Unconnected" *> pure Unconnected
> > +          timeout = A.string "Timeout" *> pure Timeout
> > +          brokenPipe = A.string "BrokenPipe" *> pure BrokenPipe
> > +          networkFailure = A.string "NetworkFailure" *> pure
> NetworkFailure
> > +          protocolError = A.string "ProtocolError" *> pure ProtocolError
> > +          tearDown = A.string "TearDown" *> pure TearDown
> > +          wfConnection = A.string "WFConnection" *> pure WFConnection
> > +          wfReportParams = A.string "WFReportParams" *> pure
> WFReportParams
> > +          connected = A.string "Connected" *> pure Connected
> > +          startingSyncS = A.string "StartingSyncS" *> pure StartingSyncS
> > +          startingSyncT = A.string "StartingSyncT" *> pure StartingSyncT
> > +          wfBitMapS = A.string "WFBitMapS" *> pure WFBitMapS
> > +          wfBitMapT = A.string "WFBitMapT" *> pure WFBitMapT
> > +          wfSyncUUID = A.string "WFSyncUUID" *> pure WFSyncUUID
> > +          syncSource = A.string "SyncSource" *> pure SyncSource
> > +          syncTarget = A.string "SyncTarget" *> pure SyncTarget
> > +          pausedSyncS = A.string "PausedSyncS" *> pure PausedSyncS
> > +          pausedSyncT = A.string "PausedSyncT" *> pure PausedSyncT
> > +          verifyS = A.string "VerifyS" *> pure VerifyS
> > +          verifyT = A.string "VerifyT" *> pure VerifyT
> > +          unconfigured = A.string "Unconfigured" *> pure Unconfigured
>
> FYI, for such block-style declarations we use a different style usually:
>
>           disconnecting  = A.string "Disconnectiog"  *> pure Disconnecting
>           unconnected    = A.string "Unconnected"    *> pure Unconnected
>           timeout        = A.string "Timeout"        *> pure Timeout
>           brokenPipe     = A.string "BrokenPipe"     *> pure BrokenPipe
>           networkFailure = A.string "NetworkFailure" *> pure NetworkFailure
>           protocolError  = A.string "ProtocolError"  *> pure ProtocolError
>           tearDown       = A.string "TearDown"       *> pure TearDown
>           wfConnection   = A.string "WFConnection"   *> pure WFConnection
>           wfReportParams = A.string "WFReportParams" *> pure WFReportParams
>
> aligned on both the '=' and the '*>'. IMHO it results in _much_ better
> readability.
>
> > +-- | Parser for recognizing strings describing two elements of the same
> type
> > +-- separated by a '/'. The first one is considered local, the second
> remote.
> > +localRemoteParser :: Parser a -> Parser (LocalRemote a)
> > +localRemoteParser parser = LocalRemote <$> parser <*> (A.char '/' *>
> parser)
> > +
> > +-- | The parser for resource roles.
> > +roleParser :: Parser Role
> > +roleParser =
> > +  primary
> > +  <|> secondary
> > +  <|> unknown
> > +           where primary = A.string "Primary" *> pure Primary
> > +                 secondary = A.string "Secondary" *> pure Secondary
> > +                 unknown = A.string "Unknown" *> pure Unknown
>
> Whereas here "where" is much more indented. I'd expect it around the
> same level, somewhere under <|>.
>
> > +-- | The parser for disk states.
> > +diskStateParser :: Parser DiskState
> > +diskStateParser =
> > +  diskless
> > +  <|> attaching
> > +  <|> failed
> > +  <|> negotiating
> > +  <|> inconsistent
> > +  <|> outdated
> > +  <|> dUnknown
> > +  <|> consistent
> > +  <|> upToDate
> > +    where diskless = A.string "Diskless" *> pure Diskless
> > +          attaching = A.string "Attaching" *> pure Attaching
> > +          failed = A.string "Failed" *> pure Failed
> > +          negotiating = A.string "Negotiating" *> pure Negotiating
> > +          inconsistent = A.string "Inconsistent" *> pure Inconsistent
> > +          outdated = A.string "Outdated" *> pure Outdated
> > +          dUnknown = A.string "DUnknown" *> pure DUnknown
> > +          consistent = A.string "Consistent" *> pure Consistent
> > +          upToDate = A.string "UpToDate" *> pure UpToDate
> > +
> > +-- | The parser for I/O flags.
> > +ioFlagsParser :: Parser String
> > +ioFlagsParser = fmap unpack . A.takeWhile $ not . isBadEndOfLine
> > +
> > +-- | The parser for performance indicators.
> > +performanceIndicatorsParser :: Parser PerformanceIndicators
> > +performanceIndicatorsParser =
> > +  PerformanceIndicators
> > +    <$> skipSpacesAndString "ns:" A.decimal
> > +    <*> skipSpacesAndString "nr:" A.decimal
> > +    <*> skipSpacesAndString "dw:" A.decimal
> > +    <*> skipSpacesAndString "dr:" A.decimal
> > +    <*> skipSpacesAndString "al:" A.decimal
> > +    <*> skipSpacesAndString "bm:" A.decimal
> > +    <*> skipSpacesAndString "lo:" A.decimal
> > +    <*> skipSpacesAndString "pe:" A.decimal
> > +    <*> skipSpacesAndString "ua:" A.decimal
> > +    <*> skipSpacesAndString "ap:" A.decimal
> > +    <*> optional (skipSpacesAndString "ep:" A.decimal)
> > +    <*> optional (skipSpacesAndString "wo:" A.anyChar)
> > +    <*> optional (skipSpacesAndString "oos:" A.decimal)
> > +    <* skipSpaces <* A.endOfLine
> > +
> > +-- | The parser for the syncronization status.
> > +syncStatusParser :: Parser SyncStatus
> > +syncStatusParser = do
> > +  _ <- statusBarParser
> > +  percent <-
> > +    skipSpacesAndString "sync'ed:" $ skipSpaces *> A.double <* A.char
> '%'
> > +  partSyncSize <- skipSpaces *> A.char '(' *> A.decimal
> > +  totSyncSize <- A.char '/' *> A.decimal <* A.char ')'
> > +  sizeUnit <- sizeUnitParser <* optional A.endOfLine
> > +  timeToEnd <- skipSpacesAndString "finish:" $ skipSpaces *> timeParser
> > +  sp <-
> > +    skipSpacesAndString "speed:" $
> > +      skipSpaces
> > +      *> commaIntParser
> > +      <* skipSpaces
> > +      <* A.char '('
> > +      <* commaIntParser
> > +      <* A.char ')'
> > +  w <- skipSpacesAndString "want:" (
> > +         skipSpaces
> > +         *> (Just <$> commaIntParser)
> > +       )
> > +       <|> pure Nothing
> > +  sSizeUnit <- skipSpaces *> sizeUnitParser
> > +  sTimeUnit <- A.char '/' *> timeUnitParser
> > +  _ <- A.endOfLine
> > +  return $
> > +    SyncStatus percent partSyncSize totSyncSize sizeUnit timeToEnd sp w
> > +      sSizeUnit sTimeUnit
> > +
> > +-- | The parser for recognizing (and discarding) the sync status bar.
> > +statusBarParser :: Parser ()
> > +statusBarParser =
> > +  skipSpaces
> > +  *> A.char '['
> > +  *> A.skipWhile (== '=')
> > +  *> A.skipWhile (== '>')
> > +  *> A.skipWhile (== '.')
> > +  *> A.char ']'
> > +  *> pure ()
> > +
> > +-- | The parser for recognizing data size units (only the ones actually
> found in
> > +-- DRBD files are implemented).
> > +sizeUnitParser :: Parser SizeUnit
> > +sizeUnitParser =
> > +  kilobyte
> > +  <|> megabyte
> > +    where kilobyte = A.string "K" *> pure KiloByte
> > +          megabyte = A.string "M" *> pure MegaByte
> > +
> > +-- | The parser for recognizing time (hh:mm:ss).
> > +timeParser :: Parser Time
> > +timeParser = Time <$> h <*> m <*> s
> > +  where h = A.decimal
> > +        m = A.char ':' *> A.decimal
> > +        s = A.char ':' *> A.decimal
> > +
> > +-- | The parser for recognizing time units (only the ones actually
> found in DRBD
> > +-- files are implemented).
> > +timeUnitParser :: Parser TimeUnit
> > +timeUnitParser = second
> > +  where second = A.string "sec" *> pure Second
> > +
> > +-- | Haskell does not recognises ',' as the separator every 3 digits
> > +-- but DRBD uses it, so we need an ah-hoc parser.
> > +commaIntParser :: Parser Int
> > +commaIntParser = do
> > +  first <- A.decimal
> > +  allDigits <- commaIntHelper first
> > +  pure allDigits
> > +
> > +-- | Helper (triplet parser) for the commaIntParser
> > +commaIntHelper :: Int -> Parser Int
> > +commaIntHelper acc = nextTriplet <|> end
> > +  where nextTriplet = do
> > +          _ <- A.char ','
> > +          triplet <- AC.count 3 A.digit
> > +          commaIntHelper $ acc * 1000 + (read triplet :: Int)
> > +        end = pure acc
> > +
> > +-- | Parser for the additional information provided by DRBD <= 8.0.
> > +additionalInfoParser::Parser AdditionalInfo
> > +additionalInfoParser = AdditionalInfo
> > +  <$> skipSpacesAndString "used:" A.decimal
> > +  <*> (A.char '/' *> A.decimal)
> > +  <*> skipSpacesAndString "hits:" A.decimal
> > +  <*> skipSpacesAndString "misses:" A.decimal
> > +  <*> skipSpacesAndString "starving:" A.decimal
> > +  <*> skipSpacesAndString "dirty:" A.decimal
> > +  <*> skipSpacesAndString "changed:" A.decimal
> > +  <* A.endOfLine
> > diff --git a/htools/Ganeti/Block/Drbd/Types.hs
> b/htools/Ganeti/Block/Drbd/Types.hs
> > new file mode 100644
> > index 0000000..20b57f1
> > --- /dev/null
> > +++ b/htools/Ganeti/Block/Drbd/Types.hs
> > @@ -0,0 +1,191 @@
> > +{-| DRBD Data Types
> > +
> > +This module holds the definition of the data types describing the
> status of
> > +DRBD.
> > +
> > +-}
> > +{-
> > +
> > +Copyright (C) 2012 Google Inc.
> > +
> > +This program is free software; you can redistribute it and/or modify
> > +it under the terms of the GNU General Public License as published by
> > +the Free Software Foundation; either version 2 of the License, or
> > +(at your option) any later version.
> > +
> > +This program is distributed in the hope that it will be useful, but
> > +WITHOUT ANY WARRANTY; without even the implied warranty of
> > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> > +General Public License for more details.
> > +
> > +You should have received a copy of the GNU General Public License
> > +along with this program; if not, write to the Free Software
> > +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> > +02110-1301, USA.
> > +
> > +-}
> > +module Ganeti.Block.Drbd.Types
> > +  ( DRBDStatus(..)
> > +  , VersionInfo(..)
> > +  , DeviceInfo(..)
> > +  , ConnectionState(..)
> > +  , LocalRemote(..)
> > +  , Role(..)
> > +  , DiskState(..)
> > +  , PerformanceIndicators(..)
> > +  , SyncStatus(..)
> > +  , SizeUnit(..)
> > +  , Time(..)
> > +  , TimeUnit(..)
> > +  , AdditionalInfo(..)
> > +  ) where
> > +
> > +--TODO: consider turning deviceInfos into an IntMap
> > +-- | Data type contaning all the data about the status of DRBD.
> > +data DRBDStatus =
> > +  DRBDStatus
> > +  { versionInfo :: VersionInfo -- ^ Version information about DRBD
> > +  , deviceInfos :: [DeviceInfo] -- ^ Per-minor information
> > +  } deriving (Eq, Show)
>
> And the field comments are usually aligned…
>
> > +-- | Data type describing the DRBD version.
> > +data VersionInfo =
> > +  VersionInfo
> > +  { version :: Maybe String -- ^ DRBD driver version
> > +  , api :: Maybe String -- ^ The api version
> > +  , proto :: Maybe String -- ^ The protocol version
> > +  , srcversion :: Maybe String -- ^ The version of the source files
> > +  , gitHash :: Maybe String -- ^ Git hash of the source files
> > +  , buildBy :: Maybe String -- ^ Who built the binary (and, optionally,
> when)
> > +  } deriving (Eq, Show)
>
> And the fields definitely so.
>
> I'd recommend checking the version I will push against the version you
> have, to see the diffs I applied.
>

Ok, I will.

Thanks,
Michele

Reply via email to