rhmessaging commits: r2556 - in mgmt/trunk/mint: sql and 1 other directory.
by rhmessaging-commits@lists.jboss.org
Author: justi9
Date: 2008-09-30 14:24:39 -0400 (Tue, 30 Sep 2008)
New Revision: 2556
Modified:
mgmt/trunk/mint/python/mint/schema.py
mgmt/trunk/mint/sql/schema.sql
Log:
Update the schema to include the collector
Modified: mgmt/trunk/mint/python/mint/schema.py
===================================================================
--- mgmt/trunk/mint/python/mint/schema.py 2008-09-30 15:40:04 UTC (rev 2555)
+++ mgmt/trunk/mint/python/mint/schema.py 2008-09-30 18:24:39 UTC (rev 2556)
@@ -16,6 +16,7 @@
statsCurr = ForeignKey('SlotStats', cascade='null', default=None)
statsPrev = ForeignKey('SlotStats', cascade='null', default=None)
classInfos = dict() # brokerId => classInfo
+ collector = ForeignKey('Collector', cascade='null', default=None)
AccountingGroup = StringCol(length=1000, default=None)
Arch = StringCol(length=1000, default=None)
CheckpointPlatform = StringCol(length=1000, default=None)
@@ -377,6 +378,36 @@
+class Collector(SQLObject):
+ class sqlmeta:
+ lazyUpdate = True
+
+ recTime = TimestampCol(default=None)
+ sourceScopeId = BigIntCol(default=None)
+ sourceObjectId = BigIntCol(default=None)
+ creationTime = TimestampCol(default=None)
+ deletionTime = TimestampCol(default=None)
+ managedBroker = StringCol(length=1000, default=None)
+ statsCurr = ForeignKey('CollectorStats', cascade='null', default=None)
+ statsPrev = ForeignKey('CollectorStats', cascade='null', default=None)
+ classInfos = dict() # brokerId => classInfo
+ CondorPlatform = StringCol(length=1000, default=None)
+ CondorVersion = StringCol(length=1000, default=None)
+ Name = StringCol(length=1000, default=None)
+ PublicNetworkIpAddr = StringCol(length=1000, default=None)
+
+
+class CollectorStats(SQLObject):
+ class sqlmeta:
+ lazyUpdate = True
+
+ recTime = TimestampCol(default=None)
+ collector = ForeignKey('Collector', cascade='null', default=None)
+ classInfos = dict() # brokerId => classInfo
+
+
+
+
class Acl(SQLObject):
class sqlmeta:
lazyUpdate = True
@@ -938,6 +969,7 @@
clientConnection = ForeignKey('ClientConnection', cascade='null', default=None)
classInfos = dict() # brokerId => classInfo
closing = BoolCol(default=None)
+ federationLink = BoolCol(default=None)
authIdentity = StringCol(length=1000, default=None)
framesFromClient = BigIntCol(default=None)
framesToClient = BigIntCol(default=None)
@@ -1124,6 +1156,9 @@
classToSchemaNameMap['Slot'] = 'Slot'
schemaNameToClassMap['Slot'] = Slot
+Collector.sqlmeta.addJoin(SQLMultipleJoin('Slot', joinMethodName='slots'))
+
+
Slot.sqlmeta.addJoin(SQLMultipleJoin('SlotStats', joinMethodName='stats'))
classToSchemaNameMap['Job'] = 'Job'
@@ -1154,6 +1189,11 @@
Negotiator.sqlmeta.addJoin(SQLMultipleJoin('NegotiatorStats', joinMethodName='stats'))
+classToSchemaNameMap['Collector'] = 'Collector'
+schemaNameToClassMap['Collector'] = Collector
+
+Collector.sqlmeta.addJoin(SQLMultipleJoin('CollectorStats', joinMethodName='stats'))
+
classToSchemaNameMap['Acl'] = 'acl'
schemaNameToClassMap['acl'] = Acl
Modified: mgmt/trunk/mint/sql/schema.sql
===================================================================
--- mgmt/trunk/mint/sql/schema.sql 2008-09-30 15:40:04 UTC (rev 2555)
+++ mgmt/trunk/mint/sql/schema.sql 2008-09-30 18:24:39 UTC (rev 2556)
@@ -217,6 +217,7 @@
rec_time TIMESTAMP,
client_connection_id INT,
closing BOOL,
+ federation_link BOOL,
auth_identity VARCHAR(1000),
frames_from_client BIGINT,
frames_to_client BIGINT,
@@ -249,6 +250,28 @@
cluster_id INT
);
+CREATE TABLE collector (
+ id SERIAL PRIMARY KEY,
+ rec_time TIMESTAMP,
+ source_scope_id BIGINT,
+ source_object_id BIGINT,
+ creation_time TIMESTAMP,
+ deletion_time TIMESTAMP,
+ managed_broker VARCHAR(1000),
+ stats_curr_id INT,
+ stats_prev_id INT,
+ condor_platform VARCHAR(1000),
+ condor_version VARCHAR(1000),
+ name VARCHAR(1000),
+ public_network_ip_addr VARCHAR(1000)
+);
+
+CREATE TABLE collector_stats (
+ id SERIAL PRIMARY KEY,
+ rec_time TIMESTAMP,
+ collector_id INT
+);
+
CREATE TABLE exchange (
id SERIAL PRIMARY KEY,
rec_time TIMESTAMP,
@@ -570,6 +593,7 @@
managed_broker VARCHAR(1000),
stats_curr_id INT,
stats_prev_id INT,
+ collector_id INT,
accounting_group VARCHAR(1000),
arch VARCHAR(1000),
checkpoint_platform VARCHAR(1000),
@@ -851,6 +875,12 @@
ALTER TABLE cluster_stats ADD CONSTRAINT cluster_id_exists FOREIGN KEY (cluster_id) REFERENCES cluster (id) ON DELETE SET NULL;
+ALTER TABLE collector ADD CONSTRAINT stats_curr_id_exists FOREIGN KEY (stats_curr_id) REFERENCES collector_stats (id) ON DELETE SET NULL;
+
+ALTER TABLE collector ADD CONSTRAINT stats_prev_id_exists FOREIGN KEY (stats_prev_id) REFERENCES collector_stats (id) ON DELETE SET NULL;
+
+ALTER TABLE collector_stats ADD CONSTRAINT collector_id_exists FOREIGN KEY (collector_id) REFERENCES collector (id) ON DELETE SET NULL;
+
ALTER TABLE exchange ADD CONSTRAINT stats_curr_id_exists FOREIGN KEY (stats_curr_id) REFERENCES exchange_stats (id) ON DELETE SET NULL;
ALTER TABLE exchange ADD CONSTRAINT stats_prev_id_exists FOREIGN KEY (stats_prev_id) REFERENCES exchange_stats (id) ON DELETE SET NULL;
@@ -919,6 +949,8 @@
ALTER TABLE slot ADD CONSTRAINT stats_prev_id_exists FOREIGN KEY (stats_prev_id) REFERENCES slot_stats (id) ON DELETE SET NULL;
+ALTER TABLE slot ADD CONSTRAINT collector_id_exists FOREIGN KEY (collector_id) REFERENCES collector (id) ON DELETE SET NULL;
+
ALTER TABLE slot_stats ADD CONSTRAINT slot_id_exists FOREIGN KEY (slot_id) REFERENCES slot (id) ON DELETE SET NULL;
ALTER TABLE store ADD CONSTRAINT stats_curr_id_exists FOREIGN KEY (stats_curr_id) REFERENCES store_stats (id) ON DELETE SET NULL;
16 years, 3 months
rhmessaging commits: r2555 - mgmt/trunk/cumin/python/cumin.
by rhmessaging-commits@lists.jboss.org
Author: eallen
Date: 2008-09-30 11:40:04 -0400 (Tue, 30 Sep 2008)
New Revision: 2555
Modified:
mgmt/trunk/cumin/python/cumin/collector.py
Log:
Fixing copy/paste error
Modified: mgmt/trunk/cumin/python/cumin/collector.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/collector.py 2008-09-30 15:38:50 UTC (rev 2554)
+++ mgmt/trunk/cumin/python/cumin/collector.py 2008-09-30 15:40:04 UTC (rev 2555)
@@ -63,8 +63,8 @@
details = CuminDetails(app, "details")
self.__tabs.add_tab(details)
- def render_script(self, session, sched):
- data = "model.xml?class=scheduler;id=%i" % sched.id
+ def render_script(self, session, coll):
+ data = "model.xml?class=collector;id=%i" % coll.id
return "wooly.setIntervalUpdate('%s', updateCollector, 3000)" % data
class CollectorStatus(CuminStatus):
16 years, 3 months
rhmessaging commits: r2554 - mgmt/trunk/cumin/python/cumin.
by rhmessaging-commits@lists.jboss.org
Author: eallen
Date: 2008-09-30 11:38:50 -0400 (Tue, 30 Sep 2008)
New Revision: 2554
Added:
mgmt/trunk/cumin/python/cumin/collector.py
mgmt/trunk/cumin/python/cumin/collector.strings
Modified:
mgmt/trunk/cumin/python/cumin/model.py
mgmt/trunk/cumin/python/cumin/parameters.py
mgmt/trunk/cumin/python/cumin/pool.py
Log:
Adding Collector tab under Pool
Added: mgmt/trunk/cumin/python/cumin/collector.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/collector.py (rev 0)
+++ mgmt/trunk/cumin/python/cumin/collector.py 2008-09-30 15:38:50 UTC (rev 2554)
@@ -0,0 +1,72 @@
+import logging
+
+from wooly import *
+from wooly.widgets import *
+from wooly.forms import *
+from wooly.resources import *
+from wooly.tables import *
+
+from stat import *
+from widgets import *
+from parameters import *
+from formats import *
+from util import *
+from job import *
+
+strings = StringCatalog(__file__)
+log = logging.getLogger("cumin.collector")
+
+class CollectorSet(CuminTable):
+ def __init__(self, app, name):
+ super(CollectorSet, self).__init__(app, name)
+
+ col = self.NameColumn(app, "name")
+ self.add_column(col)
+
+ self.set_default_column(col)
+
+ def render_title(self, session):
+ return "Collectors %s" % fmt_count(Collector.select().count())
+
+ class NameColumn(SqlTableColumn):
+ def render_title(self, session, data):
+ return "Name"
+
+ def render_content(self, session, data):
+ sub = Identifiable(data["id"])
+ branch = session.branch()
+ self.frame.show_collector(branch, sub).show_view(branch)
+ return fmt_olink(branch, sub, name=data["name"])
+
+class CollectorFrame(CuminFrame, JobSetFrame):
+ def __init__(self, app, name):
+ super(CollectorFrame, self).__init__(app, name)
+
+ self.object = CollectorParameter(app, "id")
+ self.add_parameter(self.object)
+
+ view = CollectorView(app, "view")
+ self.add_mode(view)
+ self.set_view_mode(view)
+
+
+class CollectorView(CuminView):
+ def __init__(self, app, name):
+ super(CollectorView, self).__init__(app, name)
+
+ status = CollectorStatus(app, "status")
+ self.add_child(status)
+
+ self.__tabs = TabbedModeSet(app, "tabs")
+ self.add_child(self.__tabs)
+
+ details = CuminDetails(app, "details")
+ self.__tabs.add_tab(details)
+
+ def render_script(self, session, sched):
+ data = "model.xml?class=scheduler;id=%i" % sched.id
+ return "wooly.setIntervalUpdate('%s', updateCollector, 3000)" % data
+
+class CollectorStatus(CuminStatus):
+ pass
+
Added: mgmt/trunk/cumin/python/cumin/collector.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/collector.strings (rev 0)
+++ mgmt/trunk/cumin/python/cumin/collector.strings 2008-09-30 15:38:50 UTC (rev 2554)
@@ -0,0 +1,25 @@
+[CollectorSet.sql]
+select
+ c.id,
+ c.name
+from collector as c
+
+[CollectorSet.count_sql]
+select count(1) from collector
+
+[CollectorView.javascript]
+function updateCollector(data) {
+ var model = data.objectify();
+ var colls = model.collector;
+ var col;
+
+ for (var key in colls) {
+ col = colls[key];
+ break;
+ }
+
+ cumin.runModelListeners(model);
+ cumin.runObjectListeners(col);
+
+ //throw new Error();
+}
Modified: mgmt/trunk/cumin/python/cumin/model.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/model.py 2008-09-30 15:17:23 UTC (rev 2553)
+++ mgmt/trunk/cumin/python/cumin/model.py 2008-09-30 15:38:50 UTC (rev 2554)
@@ -50,6 +50,7 @@
CuminLimit(self)
CuminPool(self)
+ CuminCollector(self)
# Systems
@@ -2042,6 +2043,30 @@
return frame
+class CuminCollector(RemoteClass):
+ def __init__(self, model):
+ super(CuminCollector, self).__init__(model, "collector",
+ Collector, CollectorStats)
+
+ prop = CuminProperty(self, "Name")
+ prop.title = "Name"
+
+ prop = CuminProperty(self, "PublicNetworkIpAddr")
+ prop.title = "IP Address"
+
+ def get_title(self, session):
+ return "Collector"
+
+ def get_object_name(self, coll):
+ return coll.Name
+
+ def show_object(self, session, coll):
+ frame = self.cumin_model.show_main(session)
+ frame = frame.children_by_name["pool"]
+ frame = frame.show_collector(session, coll).show_view(session)
+
+ return frame
+
class ModelPage(Page):
def __init__(self, app, name):
super(ModelPage, self).__init__(app, name)
Modified: mgmt/trunk/cumin/python/cumin/parameters.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/parameters.py 2008-09-30 15:17:23 UTC (rev 2553)
+++ mgmt/trunk/cumin/python/cumin/parameters.py 2008-09-30 15:38:50 UTC (rev 2554)
@@ -150,6 +150,13 @@
def do_marshal(self, sub):
return str(sub.id)
+class CollectorParameter(Parameter):
+ def do_unmarshal(self, string):
+ return Collector.get(int(string))
+
+ def do_marshal(self, coll):
+ return str(coll.id)
+
class SystemParameter(Parameter):
def do_unmarshal(self, string):
return System.get(int(string))
Modified: mgmt/trunk/cumin/python/cumin/pool.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/pool.py 2008-09-30 15:17:23 UTC (rev 2553)
+++ mgmt/trunk/cumin/python/cumin/pool.py 2008-09-30 15:38:50 UTC (rev 2554)
@@ -14,6 +14,7 @@
from job import *
from scheduler import SchedulerSet, SchedulerFrame
from submitter import SubmitterSet, SubmitterFrame
+from collector import CollectorSet, CollectorFrame
from limits import LimitsSet, LimitsFrame
strings = StringCatalog(__file__)
@@ -87,6 +88,9 @@
self.__sub = SubmitterFrame(app, "sub")
self.add_mode(self.__sub)
+ self.__coll = CollectorFrame(app, "coll")
+ self.add_mode(self.__coll)
+
self.__jobs_hold = JobSetHold(app, "jobshold")
self.add_mode(self.__jobs_hold)
@@ -136,6 +140,11 @@
self.page.set_current_frame(session, self.__sub)
return self.show_mode(session, self.__sub)
+ def show_collector(self, session, sub):
+ self.__coll.set_object(session, sub)
+ self.page.set_current_frame(session, self.__coll)
+ return self.show_mode(session, self.__coll)
+
def show_jobs_hold(self, session):
self.page.set_current_frame(session, self.__jobs_hold)
return self.show_mode(session, self.__jobs_hold)
@@ -179,6 +188,9 @@
subs = self.SubmittersTab(app, "subs")
self.__tabs.add_tab(subs)
+ colls = self.CollectorsTab(app, "colls")
+ self.__tabs.add_tab(colls)
+
limits = self.LimitsTab(app, "limits")
self.__tabs.add_tab(limits)
@@ -188,6 +200,9 @@
class SubmittersTab(SubmitterSet):
pass
+ class CollectorsTab(CollectorSet):
+ pass
+
class LimitsTab(LimitsSet):
pass
16 years, 3 months
rhmessaging commits: r2553 - mgmt/trunk/cumin/python/cumin.
by rhmessaging-commits@lists.jboss.org
Author: eallen
Date: 2008-09-30 11:17:23 -0400 (Tue, 30 Sep 2008)
New Revision: 2553
Modified:
mgmt/trunk/cumin/python/cumin/limits.py
Log:
Justin's proposed fix to avoid exception if limits can't be retrieved.
Modified: mgmt/trunk/cumin/python/cumin/limits.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/limits.py 2008-09-30 14:52:48 UTC (rev 2552)
+++ mgmt/trunk/cumin/python/cumin/limits.py 2008-09-30 15:17:23 UTC (rev 2553)
@@ -21,6 +21,8 @@
negotiator = self.get_negotiator(session)
if negotiator:
return self.get_raw_limits(session, negotiator)
+ else:
+ return dict()
def get_negotiator(self, session):
#TODO: find better way to get the negotiator. from pool perhaps?
@@ -90,7 +92,7 @@
if not limits:
limits = self.fetch_limits(session)
self.limits.set(session, limits)
- return len(limits)
+ return limits and len(limits) or 0
class NameColumn(ItemTableColumn):
def render_title(self, session, data):
16 years, 3 months
rhmessaging commits: r2552 - mgmt/trunk/mint/python/mint.
by rhmessaging-commits@lists.jboss.org
Author: justi9
Date: 2008-09-30 10:52:48 -0400 (Tue, 30 Sep 2008)
New Revision: 2552
Modified:
mgmt/trunk/mint/python/mint/__init__.py
Log:
Move spec load inside the try block so we don't lose errors
Modified: mgmt/trunk/mint/python/mint/__init__.py
===================================================================
--- mgmt/trunk/mint/python/mint/__init__.py 2008-09-30 04:12:35 UTC (rev 2551)
+++ mgmt/trunk/mint/python/mint/__init__.py 2008-09-30 14:52:48 UTC (rev 2552)
@@ -210,9 +210,8 @@
self.state = "opening"
- spec = qpid.spec.load(self.model.specPath)
-
try:
+ spec = qpid.spec.load(self.model.specPath)
sock = connect(self.host, self.port)
except Exception, e:
self.exception = e
16 years, 3 months
rhmessaging commits: r2551 - mgmt/trunk/cumin/python/cumin.
by rhmessaging-commits@lists.jboss.org
Author: justi9
Date: 2008-09-30 00:12:35 -0400 (Tue, 30 Sep 2008)
New Revision: 2551
Modified:
mgmt/trunk/cumin/python/cumin/__init__.py
mgmt/trunk/cumin/python/cumin/page.py
mgmt/trunk/cumin/python/cumin/page.strings
mgmt/trunk/cumin/python/cumin/user.py
mgmt/trunk/cumin/python/cumin/util.py
mgmt/trunk/cumin/python/cumin/widgets.py
mgmt/trunk/cumin/python/cumin/widgets.strings
Log:
Make CuminPage a common cumin widget, and move it to widgets.py.
Add a home tab to the main view.
Add a change password form.
Fix crypt_password to take a salt.
Modified: mgmt/trunk/cumin/python/cumin/__init__.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/__init__.py 2008-09-29 13:35:20 UTC (rev 2550)
+++ mgmt/trunk/cumin/python/cumin/__init__.py 2008-09-30 04:12:35 UTC (rev 2551)
@@ -13,7 +13,7 @@
from model import CuminModel, ModelPage
from demo import DemoData
-from page import CuminPage
+from page import MainPage
from stat import StatChartPage
from action import ActionPage
from user import LoginPage
@@ -38,7 +38,7 @@
self.model.data.setCloseListener(closeListener)
- self.main_page = CuminPage(self, "index.html")
+ self.main_page = MainPage(self, "index.html")
self.add_page(self.main_page)
self.set_default_page(self.main_page)
Modified: mgmt/trunk/cumin/python/cumin/page.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/page.py 2008-09-29 13:35:20 UTC (rev 2550)
+++ mgmt/trunk/cumin/python/cumin/page.py 2008-09-30 04:12:35 UTC (rev 2551)
@@ -10,6 +10,7 @@
from pool import *
from job import *
from system import *
+from user import *
from action import *
from widgets import *
from util import *
@@ -20,16 +21,10 @@
strings = StringCatalog(__file__)
-class CuminPage(Page, ModeSet):
+class MainPage(CuminPage, ModeSet):
def __init__(self, app, name):
- super(CuminPage, self).__init__(app, name)
+ super(MainPage, self).__init__(app, name)
- self.__frames = self.FramesAttribute(app, "frames")
- self.add_attribute(self.__frames)
-
- self.__modal = Attribute(app, "modal")
- self.add_attribute(self.__modal)
-
self.__main = MainFrame(app, "main")
self.add_mode(self.__main)
self.set_default_frame(self.__main)
@@ -38,26 +33,10 @@
frame = self.show_mode(session, self.__main)
return self.set_current_frame(session, frame)
- def save_session(self, session):
- if self.app.debug:
- self.app.debug.sessions.append(session)
-
- def set_modal(self, session, modal):
- self.__modal.set(session, modal)
-
- class FramesAttribute(Attribute):
- def get_default(self, session):
- return list()
-
- def get_frames(self, session):
- return self.__frames.get(session)
-
- def render_class(self, session):
- return self.__modal.get(session) and "modal" or "modeless"
-
def render_title(self, session):
return "MRG Management"
+# XXX merge this into the above
class MainFrame(CuminFrame):
def __init__(self, app, name):
super(MainFrame, self).__init__(app, name)
@@ -71,6 +50,9 @@
self.add_mode(view)
self.set_view_mode(view)
+ self.__password = ChangePasswordForm(app, "password")
+ self.add_mode(self.__password)
+
self.__broker = BrokerFrame(app, "broker")
self.add_mode(self.__broker)
@@ -139,6 +121,10 @@
ccount = self.app.model.count_invocations("OK")
return len(self.app.model.invocations) - pcount - ccount
+ def show_change_password(self, session):
+ frame = self.show_mode(session, self.__password)
+ return self.page.set_current_frame(session, frame)
+
def show_broker(self, session, reg):
assert isinstance(reg, BrokerRegistration)
frame = self.show_mode(session, self.__broker)
@@ -183,9 +169,10 @@
super(MainFrameTabs, self).__init__(app, name)
self.selection = Parameter(app, "sel")
- self.selection.default = "mtab"
+ self.selection.default = "htab"
self.add_parameter(self.selection)
+ self.add_link(self.HomeTab(app, "htab"))
self.add_link(self.MessagingTab(app, "mtab"))
self.add_link(self.GridTab(app, "gtab"))
self.add_link(self.SystemsTab(app, "stab"))
@@ -195,8 +182,18 @@
class Tab(Link):
def render_class(self, session):
- return (self.parent.selection.get(session) == self.name) and "selected" or "not-selected"
+ return (self.parent.selection.get(session) == self.name) \
+ and "selected" or "not-selected"
+ class HomeTab(Tab):
+ def render_content(self, session):
+ return "Home"
+
+ def edit_session(self, session):
+ self.parent.selection.set(session, self.name)
+ frame = self.page.show_main(session).show_view(session)
+ frame.show_home(session)
+
class MessagingTab(Tab):
def render_content(self, session):
return "Messaging"
@@ -228,6 +225,9 @@
def __init__(self, app, name):
super(MainView, self).__init__(app, name)
+ self.__home = HomeView(app, "home")
+ self.add_mode(self.__home)
+
self.__messaging = MessagingView(app, "msg")
self.add_mode(self.__messaging)
@@ -237,6 +237,9 @@
self.__systems = SystemsView(app, "sys")
self.add_mode(self.__systems)
+ def show_home(self, session):
+ return self.show_mode(session, self.__home)
+
def show_messaging(self, session):
return self.show_mode(session, self.__messaging)
@@ -246,6 +249,22 @@
def show_systems(self, session):
return self.show_mode(session, self.__systems)
+class HomeView(TabbedModeSet):
+ def __init__(self, app, name):
+ super(HomeView, self).__init__(app, name)
+
+ heading = self.Heading(app, "heading")
+ self.add_child(heading)
+
+ def render_change_password_href(self, session):
+ branch = session.branch()
+ self.frame.show_change_password(branch)
+ return branch.marshal()
+
+ class Heading(CuminHeading):
+ def render_title(self, session):
+ return "MRG Management"
+
class MessagingView(TabbedModeSet):
def __init__(self, app, name):
super(MessagingView, self).__init__(app, name)
@@ -296,4 +315,3 @@
class Heading(CuminHeading):
def render_title(self, session):
return "Systems"
-
Modified: mgmt/trunk/cumin/python/cumin/page.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/page.strings 2008-09-29 13:35:20 UTC (rev 2550)
+++ mgmt/trunk/cumin/python/cumin/page.strings 2008-09-30 04:12:35 UTC (rev 2551)
@@ -1,522 +1,3 @@
-[CuminPage.css]
-body {
- margin: 0;
- padding: 0;
- background-color: #fff;
- font-family: "DejaVu LGC Sans", "Bitstream Vera Sans", "Lucida Grande",
- "Trebuchet MS", verdana, helvetica, arial, sans-serif;
- font-size: 0.9em;
-}
-
-body.modal {
- background-color: #f7f7f7;
-}
-
-img {
- border: none;
-}
-
-a {
- color: #06c;
- text-decoration: none;
-}
-
-a.selected {
- color: black;
-}
-
-ul {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-ul > ul {
- padding: 1em;
-}
-
-h1 {
- font-size: 1.1em;
-}
-
-h2 {
- font-size: 1em;
- margin: 0;
-}
-
-span.none {
- font-style: italic;
- color: #999;
-}
-
-.oblock {
- padding: 0;
- background-color: white;
-}
-
-.iblock {
- margin: 1em 0;
- padding: 0 1em;
-}
-
-.notice {
- margin: 2em;
- padding: 2em;
- border: 1px dotted black;
- width: 66%;
- text-align: center;
-}
-
-ul.actions {
- padding: 0;
- margin: 0 0 1em 0;
- list-style: none;
-}
-
-ul.actions li {
- display: inline;
-}
-
-a.nav:before {
- content: "\00BB \0020";
- font-weight: bold;
- color: #dc9f2e;
-}
-
-div.sactions {
- margin: 0;
- padding: 0.35em 0.75em;
- background-color: #e7e7f7;
-}
-
-div.sactions h2 {
- display: inline;
- font-size: 0.9em;
- font-weight: normal;
- margin: 0 0.5em 0 0;
-}
-
-div.sactions select {
- margin: 0 0.5em 0 0;
-}
-
-div.mobject div.mactions h2 {
- display: inline;
- font-size: 0.9em;
- font-weight: normal;
- margin: 0 0.5em 0 0;
-}
-
-button, ul.actions a, a.action {
- margin: 0;
- border: 1px solid #ddd;
- padding: 0.25em 0.5em 0.15em 0.5em;
- background-color: #f7f7f7;
- color: #000;
- font-size: 0.9em;
-}
-
-button:hover, ul.actions a:hover, a.action:hover {
- background-color: white;
-}
-
-button.disabled {
- color: #666;
- border: 1px solid #EAEAEA;
-}
-button.disabled:hover {
- background-color: #f7f7f7;
-}
-
-ul.mobjects {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-ul.mobjects li {
- margin: 0;
- border-top: 1px solid #ccc;
- padding: 0.5em 0;
-}
-
-ul.mobjects li:first-child {
- margin: 0;
- border: none;
-}
-
-ul.mobjects li a.action {
- float: right;
-}
-
-ul.mobjects .flags {
- font-size: small;
- font-style: italic;
-}
-
-ul.mobjects .config {
- padding: 0 0 0 2em;
-}
-
-ul.mobjects .status {
- padding: 0 0 0 2em;
- color: #936;
-}
-
-table.mobjects {
- width: 100%;
- border-collapse: collapse;
- margin: 0;
-}
-
-table.mobjects tr {
- border-top: 1px dotted #ccc;
- vertical-align: top;
-}
-
-table.mobjects td {
- padding: 0.35em 0.5em;
-}
-
-table.mobjects th {
- padding: 0.35em 0.5em;
-}
-
-table.mobjects th {
- text-align: left;
- font-weight: normal;
- background-color: #f7f7f7;
-}
-
-form.mform {
- width: 50em;
- border: 1px solid #ddd;
- background-color: #fff;
-}
-
-form.mform fieldset {
- border: none;
- padding: 0.75em;
-}
-
-form.mform .legend {
- font-weight: bold;
-}
-
-form.mform .head, .mform .body, .mform .foot {
- padding: 0.5em 0.75em;
- margin: 0;
-}
-
-form.mform .head {
- font-weight: bold;
- color: white;
- background-color: #685b8a;
- /* background-color: #564979; */
-}
-
-form.mform .head h1 {
- margin: 0;
- font-size: 1.1em;
-}
-
-form.mform .foot {
- text-align: right;
- border-top: 1px solid #ddd;
-}
-
-form.mform .field {
- margin: 0.25em 0;
-}
-
-form.mform .field input {
- border-style: groove;
-}
-
-form.mform ul.errors {
- list-style: none;
- display: block;
- float: right;
- color: red;
- padding: 0.25em 0.5em;
- border: 1px solid red;
- margin: 0 0.5em;
- max-width: 20em;
-}
-
-form.mform button, form.mform a.help {
- margin: 0.5em;
- padding: 0.25em 0.25em 0 0.25em;
-}
-
-form.mform a.help {
- float: left;
- margin: 0.5em;
- padding: 0.25em 0.35em 0 0.5em;
-}
-
-form.mform a.help:before {
- content: url(resource?name=help-20.png);
- padding: 0 0.25em 0 0;
- vertical-align: -35%;
-}
-
-form.mform button.cancel:before {
- content: url(resource?name=cancel-20.png);
- padding: 0 0.25em 0 0;
- vertical-align: -35%;
-}
-
-form.mform button.submit:before {
- content: url(resource?name=submit-20.png);
- padding: 0 0.25em 0 0;
- vertical-align: -35%;
-}
-
-form.mform td {
- vertical-align: top;
-}
-
-ul.radiotabs {
- list-style: none;
- margin: 0 0 1em 0;
- padding: 0;
-}
-
-ul.radiotabs li {
- display: inline;
- padding: 0 0.75em 0 0;
-}
-
-ul.radiotabs li:last-child {
- display: inline;
- margin: 0;
-}
-
-ul.radiotabs li a:before {
- content: url(resource?name=radio-button.png);
- margin: 0 0.5em 0 0;
- vertical-align: -15%;
-}
-
-ul.radiotabs li a.selected {
- color: black;
-}
-
-ul.radiotabs li a.selected:before {
- content: url(resource?name=radio-button-checked.png);
-}
-
-ul.radiotabs li a.disabled:before {
- content: url(resource?name=radio-button.png);
-}
-ul.radiotabs li a.disabled {
- color: #666666;
-}
-
-div.statuslight {
- float: left;
- width: 1em;
- height: 1em;
- margin: 0.25em 1px 0 0;
- padding: 0.15em;
- font-size: 0.8em;
- text-align: center;
- line-height: 1.1em;
-}
-
-div.statuslight.red {
- background-color: #e33;
- color: #fd3;
-}
-
-div.statuslight.yellow {
- background-color: #fd3;
- color: #e33;
-}
-
-div.statuslight.green {
- background-color: #9e9;
-}
-
-pre.code {
- background-color: #f7f7f7;
- padding: 1em;
- border: 1px dotted #ddd;
-}
-
-ul.comma {
- list-style: none;
-}
-
-ul.comma li {
- display: inline;
-}
-
-ul.comma li:after {
- content: ", "
-}
-
-ul.comma li:last-child:after {
- content: ""
-}
-
-ul.slist a:before {
- content: url(resource?name=radio-button.png);
- vertical-align: -10%;
- margin: 0 0.5em 0 0;
-}
-
-ul.slist a.selected:before {
- content: url(resource?name=radio-button-checked.png);
-}
-
-table.twocol {
- width: 100%;
-}
-
-table.twocol > tbody > tr > td {
- width: 50%;
- vertical-align: top;
-}
-
-table.twocol > tbody > tr > td:first-child {
- padding: 0 1.5em 0 0;
-}
-
-table.twocol > tbody > tr > td:last-child {
- padding: 0 0 0 1.5em;
-}
-
-.ralign, table.mobjects .ralign, div.mstatus table .ralign {
- text-align: right;
-}
-
-form.inline {
- display: inline;
-}
-
-span.count {
- font-size: 0.9em;
- color: #999;
-}
-
-.rfloat {
- float: right;
-}
-
-.rclear {
- font-size:0.01em;
- width: 0.01px;
- clear:right;
- line-height:0.01px;
-}
-
-table.Editable input.edit_string,
-table.Editable textarea.edit_bigstring,
-div.inline_help span.edit_string {
- border: 1px solid #CCCCCC;
-}
-table.Editable input.edit_number,
-div.inline_help span.edit_number {
- border: 1px dashed #66CCFF;
-}
-table.Editable input.numeric_error,
-div.inline_help span.numeric_error {
- border: 1px dashed #FF0000;
-}
-table.Editable span.edit_readonly {
- background-color: #FFFFFF;
- color: #444444;
-}
-
-table.Editable input.edit_string,
-table.Editable input.edit_number,
-table.Editable input.numeric_error {
- width: 20em;
-}
-table.Editable textarea.edit_bigstring {
- width: 25em;
-}
-table.Editable div.error {
- color: #FF0000;
- font-size: 0.9em;
-}
-
-form.editform {
- border:0 none !important;
- width: 100% !important;
-}
-
-div.inline_help {
- margin: 1em;
-}
-
-div.inline_help span.edit_string,
-div.inline_help span.edit_number,
-div.inline_help span.numeric_error {
- color: #444444;
- font-weight: normal;
- margin-right: 0.5em;
- padding:0.05em 0.2em;
-}
-div.inline_help h2 {
- margin-right: 1em;
-}
-
-span.prop_example {
- font-size: 0.9em;
-}
-span.prop_example:before {
- content: "Example:";
- padding-right: 0.25em;
-}
-
-[CuminPage.javascript]
-var cumin;
-
-(function() {
- cumin = new Cumin();
-
- function Cumin() {
- this.modelListeners = new Object();
- this.objectListeners = new Object();
-
- this.runModelListeners = function(model) {
- for (var id in this.modelListeners) {
- this.modelListeners[id](id, model);
- }
- }
-
- this.runObjectListeners = function(object) {
- for (var id in this.objectListeners) {
- this.objectListeners[id](id, object);
- }
- }
- }
-}())
-function addEvent(obj, event_type, funct) {
- if (obj.addEventListener)
- obj.addEventListener(event_type, funct, false);
- else if (obj.attachEvent)
- obj.attachEvent("on"+event_type, funct);
-}
-[CuminPage.html]
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
- <head>
- <title>{title}</title>
- <link rel="stylesheet" type="text/css" href="cumin.css"/>
- <link rel="shortcut icon" href="resource?name=favicon.ico" type="image/x-icon"/>
- <script src="resource?name=wooly.js" type="text/javascript"> </script>
- <script src="cumin.js" type="text/javascript"> </script>
- </head>
- <body class="{class}">
- {mode}
- </body>
-</html>
-
[MainFrame.css]
#head {
padding: 0;
@@ -692,11 +173,20 @@
[MainFrame.frame_html]
<li><a href="{frame_href}">{frame_title}</a></li>
-[MessagingView.css]
-img#msg_logo {
- margin: 0 0 1em 0;
-}
+[HomeView.html]
+<script type="text/javascript">
+<![CDATA[
+ wooly.setIntervalUpdate("{data_url}", updateMain, 3000);
+]]>
+</script>
+<div class="oblock">
+ {heading}
+ <ul class="actions">
+ <a class="nav" href="{change_password_href}">Change Password</a>
+ </ul>
+</div>
+
[MessagingView.html]
<script type="text/javascript">
<![CDATA[
Modified: mgmt/trunk/cumin/python/cumin/user.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/user.py 2008-09-29 13:35:20 UTC (rev 2550)
+++ mgmt/trunk/cumin/python/cumin/user.py 2008-09-30 04:12:35 UTC (rev 2551)
@@ -120,3 +120,80 @@
class Submit(FormButton):
def render_content(self, session):
return "Submit"
+
+class ChangePasswordForm(CuminFieldForm):
+ def __init__(self, app, name):
+ super(ChangePasswordForm, self).__init__(app, name)
+
+ self.__errors = self.Errors(app, "errors")
+ self.add_attribute(self.__errors)
+
+ self.__current = self.Current(app, "current", self)
+ self.add_field(self.__current)
+ self.__current.get_input().set_size(20)
+
+ self.__new0 = self.New0(app, "new0", self)
+ self.add_field(self.__new0)
+ self.__new0.get_input().set_size(20)
+
+ self.__new1 = self.New1(app, "new1", self)
+ self.add_field(self.__new1)
+ self.__new1.get_input().set_size(20)
+
+ def process_cancel(self, session):
+ branch = session.branch()
+ self.page.show_main(branch).show_view(branch)
+ self.page.set_redirect_url(session, branch.marshal())
+
+ def process_submit(self, session):
+ curr = self.__current.get(session)
+ new0 = self.__new0.get(session)
+ new1 = self.__new1.get(session)
+
+ errors = self.validate(session)
+
+ subject = session.user_session.subject
+ crypted = subject.password
+
+ if crypt_password(curr, crypted) != crypted:
+ msg = "The current password you entered is incorrect"
+ self.__errors.get(session).append(msg)
+ errors.append(msg)
+
+ if new0 != new1:
+ msg = "The new passwords do not match"
+ self.__errors.get(session).append(msg)
+ errors.append(msg)
+
+ if not errors:
+ subject.password = crypt_password(new0)
+ subject.syncUpdate()
+
+ self.process_cancel(session)
+
+ def render_title(self, session):
+ return "Change Password"
+
+ def render_form_error(self, session):
+ errors = self.__errors.get(session)
+
+ if errors:
+ return "<ul class=\"errors\" style=\"margin:0; float:left;\"><li>" + \
+ ("</li><li>".join(errors)) + \
+ "</li></ul>"
+
+ class Current(PasswordField):
+ def render_title(self, session):
+ return "Current Password"
+
+ class New0(PasswordField):
+ def render_title(self, session):
+ return "New Password"
+
+ class New1(PasswordField):
+ def render_title(self, session):
+ return "Repeat New Password"
+
+ class Errors(Attribute):
+ def get_default(self, session):
+ return list()
Modified: mgmt/trunk/cumin/python/cumin/util.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/util.py 2008-09-29 13:35:20 UTC (rev 2550)
+++ mgmt/trunk/cumin/python/cumin/util.py 2008-09-30 04:12:35 UTC (rev 2551)
@@ -202,5 +202,8 @@
password_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-def crypt_password(password):
- return crypt(password, "".join(sample(password_chars, 2)))
+def crypt_password(password, salt=None):
+ if not salt:
+ salt = "".join(sample(password_chars, 2))
+
+ return crypt(password, salt)
Modified: mgmt/trunk/cumin/python/cumin/widgets.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/widgets.py 2008-09-29 13:35:20 UTC (rev 2550)
+++ mgmt/trunk/cumin/python/cumin/widgets.py 2008-09-30 04:12:35 UTC (rev 2551)
@@ -14,9 +14,35 @@
import time
-
strings = StringCatalog(__file__)
+class CuminPage(Page):
+ def __init__(self, app, name):
+ super(CuminPage, self).__init__(app, name)
+
+ self.__frames = self.FramesAttribute(app, "frames")
+ self.add_attribute(self.__frames)
+
+ self.__modal = Attribute(app, "modal")
+ self.add_attribute(self.__modal)
+
+ def save_session(self, session):
+ if self.app.debug:
+ self.app.debug.sessions.append(session)
+
+ def set_modal(self, session, modal):
+ self.__modal.set(session, modal)
+
+ def get_frames(self, session):
+ return self.__frames.get(session)
+
+ def render_class(self, session):
+ return self.__modal.get(session) and "modal" or "modeless"
+
+ class FramesAttribute(Attribute):
+ def get_default(self, session):
+ return list()
+
class CuminFrame(Frame, ModeSet):
def __init__(self, app, name):
super(CuminFrame, self).__init__(app, name)
@@ -128,7 +154,7 @@
class CuminForm(Form):
def __init__(self, app, name):
super(CuminForm, self).__init__(app, name)
-
+
self.__cancel = self.Cancel(app, "cancel", self)
self.__cancel.set_tab_index(201)
self.add_child(self.__cancel)
Modified: mgmt/trunk/cumin/python/cumin/widgets.strings
===================================================================
--- mgmt/trunk/cumin/python/cumin/widgets.strings 2008-09-29 13:35:20 UTC (rev 2550)
+++ mgmt/trunk/cumin/python/cumin/widgets.strings 2008-09-30 04:12:35 UTC (rev 2551)
@@ -1,3 +1,523 @@
+[CuminPage.css]
+body {
+ margin: 0;
+ padding: 0;
+ background-color: #fff;
+ font-family: "DejaVu LGC Sans", "Bitstream Vera Sans", "Lucida Grande",
+ "Trebuchet MS", verdana, helvetica, arial, sans-serif;
+ font-size: 0.9em;
+}
+
+body.modal {
+ background-color: #f7f7f7;
+}
+
+img {
+ border: none;
+}
+
+a {
+ color: #06c;
+ text-decoration: none;
+}
+
+a.selected {
+ color: black;
+}
+
+ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+ul > ul {
+ padding: 1em;
+}
+
+h1 {
+ font-size: 1.1em;
+}
+
+h2 {
+ font-size: 1em;
+ margin: 0;
+}
+
+span.none {
+ font-style: italic;
+ color: #999;
+}
+
+.oblock {
+ padding: 0;
+ background-color: white;
+}
+
+.iblock {
+ margin: 1em 0;
+ padding: 0 1em;
+}
+
+.notice {
+ margin: 2em;
+ padding: 2em;
+ border: 1px dotted black;
+ width: 66%;
+ text-align: center;
+}
+
+ul.actions {
+ padding: 0;
+ margin: 0 0 1em 0;
+ list-style: none;
+}
+
+ul.actions li {
+ display: inline;
+}
+
+a.nav:before {
+ content: "\00BB \0020";
+ font-weight: bold;
+ color: #dc9f2e;
+}
+
+div.sactions {
+ margin: 0;
+ padding: 0.35em 0.75em;
+ background-color: #e7e7f7;
+}
+
+div.sactions h2 {
+ display: inline;
+ font-size: 0.9em;
+ font-weight: normal;
+ margin: 0 0.5em 0 0;
+}
+
+div.sactions select {
+ margin: 0 0.5em 0 0;
+}
+
+div.mobject div.mactions h2 {
+ display: inline;
+ font-size: 0.9em;
+ font-weight: normal;
+ margin: 0 0.5em 0 0;
+}
+
+button, ul.actions a, a.action {
+ margin: 0;
+ border: 1px solid #ddd;
+ padding: 0.25em 0.5em 0.15em 0.5em;
+ background-color: #f7f7f7;
+ color: #000;
+ font-size: 0.9em;
+}
+
+button:hover, ul.actions a:hover, a.action:hover {
+ background-color: white;
+}
+
+button.disabled {
+ color: #666;
+ border: 1px solid #EAEAEA;
+}
+button.disabled:hover {
+ background-color: #f7f7f7;
+}
+
+ul.mobjects {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+ul.mobjects li {
+ margin: 0;
+ border-top: 1px solid #ccc;
+ padding: 0.5em 0;
+}
+
+ul.mobjects li:first-child {
+ margin: 0;
+ border: none;
+}
+
+ul.mobjects li a.action {
+ float: right;
+}
+
+ul.mobjects .flags {
+ font-size: small;
+ font-style: italic;
+}
+
+ul.mobjects .config {
+ padding: 0 0 0 2em;
+}
+
+ul.mobjects .status {
+ padding: 0 0 0 2em;
+ color: #936;
+}
+
+table.mobjects {
+ width: 100%;
+ border-collapse: collapse;
+ margin: 0;
+}
+
+table.mobjects tr {
+ border-top: 1px dotted #ccc;
+ vertical-align: top;
+}
+
+table.mobjects td {
+ padding: 0.35em 0.5em;
+}
+
+table.mobjects th {
+ padding: 0.35em 0.5em;
+}
+
+table.mobjects th {
+ text-align: left;
+ font-weight: normal;
+ background-color: #f7f7f7;
+}
+
+form.mform {
+ width: 50em;
+ border: 1px solid #ddd;
+ background-color: #fff;
+}
+
+form.mform fieldset {
+ border: none;
+ padding: 0.75em;
+}
+
+form.mform .legend {
+ font-weight: bold;
+}
+
+form.mform .head, .mform .body, .mform .foot {
+ padding: 0.5em 0.75em;
+ margin: 0;
+}
+
+form.mform .head {
+ font-weight: bold;
+ color: white;
+ background-color: #685b8a;
+ /* background-color: #564979; */
+}
+
+form.mform .head h1 {
+ margin: 0;
+ font-size: 1.1em;
+}
+
+form.mform .foot {
+ text-align: right;
+ border-top: 1px solid #ddd;
+}
+
+form.mform .field {
+ margin: 0.25em 0;
+}
+
+form.mform .field input {
+ border-style: groove;
+}
+
+form.mform ul.errors {
+ list-style: none;
+ display: block;
+ float: right;
+ color: red;
+ padding: 0.25em 0.5em;
+ border: 1px solid red;
+ margin: 0 0.5em;
+ max-width: 20em;
+}
+
+form.mform button, form.mform a.help {
+ margin: 0.5em;
+ padding: 0.25em 0.25em 0 0.25em;
+}
+
+form.mform a.help {
+ float: left;
+ margin: 0.5em;
+ padding: 0.25em 0.35em 0 0.5em;
+}
+
+form.mform a.help:before {
+ content: url(resource?name=help-20.png);
+ padding: 0 0.25em 0 0;
+ vertical-align: -35%;
+}
+
+form.mform button.cancel:before {
+ content: url(resource?name=cancel-20.png);
+ padding: 0 0.25em 0 0;
+ vertical-align: -35%;
+}
+
+form.mform button.submit:before {
+ content: url(resource?name=submit-20.png);
+ padding: 0 0.25em 0 0;
+ vertical-align: -35%;
+}
+
+form.mform td {
+ vertical-align: top;
+}
+
+ul.radiotabs {
+ list-style: none;
+ margin: 0 0 1em 0;
+ padding: 0;
+}
+
+ul.radiotabs li {
+ display: inline;
+ padding: 0 0.75em 0 0;
+}
+
+ul.radiotabs li:last-child {
+ display: inline;
+ margin: 0;
+}
+
+ul.radiotabs li a:before {
+ content: url(resource?name=radio-button.png);
+ margin: 0 0.5em 0 0;
+ vertical-align: -15%;
+}
+
+ul.radiotabs li a.selected {
+ color: black;
+}
+
+ul.radiotabs li a.selected:before {
+ content: url(resource?name=radio-button-checked.png);
+}
+
+ul.radiotabs li a.disabled:before {
+ content: url(resource?name=radio-button.png);
+}
+ul.radiotabs li a.disabled {
+ color: #666666;
+}
+
+div.statuslight {
+ float: left;
+ width: 1em;
+ height: 1em;
+ margin: 0.25em 1px 0 0;
+ padding: 0.15em;
+ font-size: 0.8em;
+ text-align: center;
+ line-height: 1.1em;
+}
+
+div.statuslight.red {
+ background-color: #e33;
+ color: #fd3;
+}
+
+div.statuslight.yellow {
+ background-color: #fd3;
+ color: #e33;
+}
+
+div.statuslight.green {
+ background-color: #9e9;
+}
+
+pre.code {
+ background-color: #f7f7f7;
+ padding: 1em;
+ border: 1px dotted #ddd;
+}
+
+ul.comma {
+ list-style: none;
+}
+
+ul.comma li {
+ display: inline;
+}
+
+ul.comma li:after {
+ content: ", "
+}
+
+ul.comma li:last-child:after {
+ content: ""
+}
+
+ul.slist a:before {
+ content: url(resource?name=radio-button.png);
+ vertical-align: -10%;
+ margin: 0 0.5em 0 0;
+}
+
+ul.slist a.selected:before {
+ content: url(resource?name=radio-button-checked.png);
+}
+
+table.twocol {
+ width: 100%;
+}
+
+table.twocol > tbody > tr > td {
+ width: 50%;
+ vertical-align: top;
+}
+
+table.twocol > tbody > tr > td:first-child {
+ padding: 0 1.5em 0 0;
+}
+
+table.twocol > tbody > tr > td:last-child {
+ padding: 0 0 0 1.5em;
+}
+
+.ralign, table.mobjects .ralign, div.mstatus table .ralign {
+ text-align: right;
+}
+
+form.inline {
+ display: inline;
+}
+
+span.count {
+ font-size: 0.9em;
+ color: #999;
+}
+
+.rfloat {
+ float: right;
+}
+
+.rclear {
+ font-size:0.01em;
+ width: 0.01px;
+ clear:right;
+ line-height:0.01px;
+}
+
+table.Editable input.edit_string,
+table.Editable textarea.edit_bigstring,
+div.inline_help span.edit_string {
+ border: 1px solid #CCCCCC;
+}
+table.Editable input.edit_number,
+div.inline_help span.edit_number {
+ border: 1px dashed #66CCFF;
+}
+table.Editable input.numeric_error,
+div.inline_help span.numeric_error {
+ border: 1px dashed #FF0000;
+}
+table.Editable span.edit_readonly {
+ background-color: #FFFFFF;
+ color: #444444;
+}
+
+table.Editable input.edit_string,
+table.Editable input.edit_number,
+table.Editable input.numeric_error {
+ width: 20em;
+}
+table.Editable textarea.edit_bigstring {
+ width: 25em;
+}
+table.Editable div.error {
+ color: #FF0000;
+ font-size: 0.9em;
+}
+
+form.editform {
+ border:0 none !important;
+ width: 100% !important;
+}
+
+div.inline_help {
+ margin: 1em;
+}
+
+div.inline_help span.edit_string,
+div.inline_help span.edit_number,
+div.inline_help span.numeric_error {
+ color: #444444;
+ font-weight: normal;
+ margin-right: 0.5em;
+ padding:0.05em 0.2em;
+}
+div.inline_help h2 {
+ margin-right: 1em;
+}
+
+span.prop_example {
+ font-size: 0.9em;
+}
+span.prop_example:before {
+ content: "Example:";
+ padding-right: 0.25em;
+}
+
+[CuminPage.javascript]
+var cumin;
+
+(function() {
+ cumin = new Cumin();
+
+ function Cumin() {
+ this.modelListeners = new Object();
+ this.objectListeners = new Object();
+
+ this.runModelListeners = function(model) {
+ for (var id in this.modelListeners) {
+ this.modelListeners[id](id, model);
+ }
+ }
+
+ this.runObjectListeners = function(object) {
+ for (var id in this.objectListeners) {
+ this.objectListeners[id](id, object);
+ }
+ }
+ }
+}())
+function addEvent(obj, event_type, funct) {
+ if (obj.addEventListener)
+ obj.addEventListener(event_type, funct, false);
+ else if (obj.attachEvent)
+ obj.attachEvent("on"+event_type, funct);
+}
+
+[CuminPage.html]
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
+ <head>
+ <title>{title}</title>
+ <link rel="stylesheet" type="text/css" href="cumin.css"/>
+ <link rel="shortcut icon" href="resource?name=favicon.ico" type="image/x-icon"/>
+ <script src="resource?name=wooly.js" type="text/javascript"> </script>
+ <script src="cumin.js" type="text/javascript"> </script>
+ </head>
+ <body class="{class}">
+ {mode}
+ </body>
+</html>
+
[BindingSet.sql]
select
b.id,
16 years, 3 months
rhmessaging commits: r2550 - store/trunk/cpp/lib/jrnl.
by rhmessaging-commits@lists.jboss.org
Author: kpvdr
Date: 2008-09-29 09:35:20 -0400 (Mon, 29 Sep 2008)
New Revision: 2550
Modified:
store/trunk/cpp/lib/jrnl/fcntl.cpp
store/trunk/cpp/lib/jrnl/fcntl.hpp
store/trunk/cpp/lib/jrnl/jcntl.cpp
Log:
Added lid to class fcntl; removed some unneeded methods, made initialize() protected.
Modified: store/trunk/cpp/lib/jrnl/fcntl.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/fcntl.cpp 2008-09-26 21:00:58 UTC (rev 2549)
+++ store/trunk/cpp/lib/jrnl/fcntl.cpp 2008-09-29 13:35:20 UTC (rev 2550)
@@ -45,24 +45,11 @@
namespace journal
{
-fcntl::fcntl(const u_int32_t jfsize_sblks, const u_int16_t fid):
- _fname(),
- _fid(fid),
- _ffull_dblks(JRNL_SBLK_SIZE * (jfsize_sblks + 1)),
- _rd_fh(-1),
- _wr_fh(-1),
- _rec_enqcnt(0),
- _rd_subm_cnt_dblks(0),
- _rd_cmpl_cnt_dblks(0),
- _wr_subm_cnt_dblks(0),
- _wr_cmpl_cnt_dblks(0),
- _aio_cnt(0)
-{}
-
-fcntl::fcntl(const std::string& fbasename, const u_int16_t fid, const u_int32_t jfsize_sblks,
+fcntl::fcntl(const std::string& fbasename, const u_int16_t fid, const u_int16_t lid, const u_int32_t jfsize_sblks,
const rcvdat* const ro):
_fname(),
_fid(fid),
+ _lid(lid),
_ffull_dblks(JRNL_SBLK_SIZE * (jfsize_sblks + 1)),
_rd_fh(-1),
_wr_fh(-1),
@@ -73,7 +60,7 @@
_wr_cmpl_cnt_dblks(0),
_aio_cnt(0)
{
- initialize(fbasename, fid, jfsize_sblks, ro);
+ initialize(fbasename, fid, lid, jfsize_sblks, ro);
open_fh();
}
@@ -82,46 +69,6 @@
close_fh();
}
-void
-fcntl::initialize(const std::string& fbasename, const u_int16_t fid,
- const u_int32_t jfsize_sblks, const rcvdat* const ro)
-{
- _fid = fid;
- _fname = filename(fbasename, fid);
-
-#ifdef RHM_JOWRITE
- // In test mode, only create file if it does not exist
- struct stat s;
- if (::stat(_fname.c_str(), &s))
- {
-#endif
- if (ro) // Recovery initialization: set counters only
- {
- if (!ro->_jempty)
- {
- // For last file only, set write counters to end of last record (the
- // continuation point); for all others, set to eof.
- if (ro->_lfid == _fid)
- {
- _wr_subm_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE;
- _wr_cmpl_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE;
- }
- else
- {
- _wr_subm_cnt_dblks = _ffull_dblks;
- _wr_cmpl_cnt_dblks = _ffull_dblks;
- }
- // Set the number of enqueued records for this file.
- _rec_enqcnt = ro->_enq_cnt_list[_fid];
- }
- }
- else // Normal initialization: create empty journal files
- create_jfile(jfsize_sblks);
-#ifdef RHM_JOWRITE
- }
-#endif
-}
-
bool
fcntl::reset(const rcvdat* const ro)
{
@@ -273,9 +220,50 @@
return oss.str();
}
-// Private functions
+// Protected functions
void
+fcntl::initialize(const std::string& fbasename, const u_int16_t fid, const u_int16_t lid, const u_int32_t jfsize_sblks,
+ const rcvdat* const ro)
+{
+ _fid = fid;
+ _lid = lid;
+ _fname = filename(fbasename, fid);
+
+#ifdef RHM_JOWRITE
+ // In test mode, only create file if it does not exist
+ struct stat s;
+ if (::stat(_fname.c_str(), &s))
+ {
+#endif
+ if (ro) // Recovery initialization: set counters only
+ {
+ if (!ro->_jempty)
+ {
+ // For last file only, set write counters to end of last record (the
+ // continuation point); for all others, set to eof.
+ if (ro->_lfid == _fid)
+ {
+ _wr_subm_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE;
+ _wr_cmpl_cnt_dblks = ro->_eo/JRNL_DBLK_SIZE;
+ }
+ else
+ {
+ _wr_subm_cnt_dblks = _ffull_dblks;
+ _wr_cmpl_cnt_dblks = _ffull_dblks;
+ }
+ // Set the number of enqueued records for this file.
+ _rec_enqcnt = ro->_enq_cnt_list[_fid];
+ }
+ }
+ else // Normal initialization: create empty journal files
+ create_jfile(jfsize_sblks);
+#ifdef RHM_JOWRITE
+ }
+#endif
+}
+
+void
fcntl::open_fh()
{
_rd_fh = ::open(_fname.c_str(), O_RDONLY | O_DIRECT);
@@ -387,23 +375,5 @@
clean_file(jfsize_sblks);
}
-void
-fcntl::get_jfile()
-{
- // Step 1: stat _pool_dir, locate first available file, check file size matches
- // Step 2: move file to current directory
-}
-
-void return_jfile()
-{
- // Step 1: Clean file (if req'd)
- // Step 2: Move file to _pool_dir
-}
-
-
-// Static declarations
-
-std::string fcntl::_pool_dir;
-
} // namespace journal
} // namespace mrg
Modified: store/trunk/cpp/lib/jrnl/fcntl.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/fcntl.hpp 2008-09-26 21:00:58 UTC (rev 2549)
+++ store/trunk/cpp/lib/jrnl/fcntl.hpp 2008-09-29 13:35:20 UTC (rev 2550)
@@ -57,9 +57,9 @@
class fcntl
{
protected:
- static std::string _pool_dir; ///< Directory containing unused file pool
std::string _fname; ///< File name
- u_int16_t _fid; ///< File ID (ordinal number in ring buffer)
+ u_int16_t _fid; ///< File ID (file number in order of creation)
+ u_int16_t _lid; ///< Logical ID (ordinal number in ring store)
const u_int32_t _ffull_dblks; ///< File size in dblks (incl. file header)
int _rd_fh; ///< Read file handle
int _wr_fh; ///< Write file handle
@@ -71,23 +71,19 @@
u_int16_t _aio_cnt; ///< Outstanding AIO operations on this file
public:
- fcntl(const u_int32_t jfsize_sblks, const u_int16_t fid);
// Constructors with implicit initialize() and open()
- fcntl(const std::string& fbasename, const u_int16_t fid, const u_int32_t jfsize_sblks,
+ fcntl(const std::string& fbasename, const u_int16_t fid, const u_int16_t lid, const u_int32_t jfsize_sblks,
const rcvdat* const ro);
virtual ~fcntl();
- inline static std::string& pool_dir() { return _pool_dir; }
- inline static void set_pool_dir(const std::string pool_dir) { _pool_dir = pool_dir; }
-
- virtual void initialize(const std::string& fbasename, const u_int16_t fid,
- const u_int32_t jfsize_sblks, const rcvdat* const ro);
virtual bool reset(const rcvdat* const ro = 0);
virtual void rd_reset();
virtual bool wr_reset(const rcvdat* const ro = 0);
inline const std::string& fname() const { return _fname; }
inline u_int16_t fid() const { return _fid; }
+ inline u_int16_t lid() const { return _lid; }
+ inline void set_lid(const u_int16_t lid) { _lid = lid; }
inline int rd_fh() const { return _rd_fh; }
inline int wr_fh() const { return _wr_fh; }
inline u_int32_t enqcnt() const { return _rec_enqcnt; }
@@ -120,38 +116,32 @@
inline bool rd_void() const { return _wr_cmpl_cnt_dblks == 0; }
inline bool rd_empty() const { return _wr_cmpl_cnt_dblks <= JRNL_SBLK_SIZE; }
- inline u_int32_t rd_remaining_dblks() const
- { return _wr_cmpl_cnt_dblks - _rd_subm_cnt_dblks; }
+ inline u_int32_t rd_remaining_dblks() const { return _wr_cmpl_cnt_dblks - _rd_subm_cnt_dblks; }
inline bool is_rd_full() const { return _wr_cmpl_cnt_dblks == _rd_subm_cnt_dblks; }
- inline bool is_rd_compl() const
- { return _wr_cmpl_cnt_dblks == _rd_cmpl_cnt_dblks; }
- inline u_int32_t rd_aio_outstanding_dblks() const
- { return _rd_subm_cnt_dblks - _rd_cmpl_cnt_dblks; }
+ inline bool is_rd_compl() const { return _wr_cmpl_cnt_dblks == _rd_cmpl_cnt_dblks; }
+ inline u_int32_t rd_aio_outstanding_dblks() const { return _rd_subm_cnt_dblks - _rd_cmpl_cnt_dblks; }
inline bool rd_file_rotate() const { return is_rd_full() && is_wr_compl(); }
inline bool wr_void() const { return _wr_subm_cnt_dblks == 0; }
inline bool wr_empty() const { return _wr_subm_cnt_dblks <= JRNL_SBLK_SIZE; }
- inline u_int32_t wr_remaining_dblks() const
- { return _ffull_dblks - _wr_subm_cnt_dblks; }
+ inline u_int32_t wr_remaining_dblks() const { return _ffull_dblks - _wr_subm_cnt_dblks; }
inline bool is_wr_full() const { return _ffull_dblks == _wr_subm_cnt_dblks; }
inline bool is_wr_compl() const { return _ffull_dblks == _wr_cmpl_cnt_dblks; }
- inline u_int32_t wr_aio_outstanding_dblks() const
- { return _wr_subm_cnt_dblks - _wr_cmpl_cnt_dblks; }
+ inline u_int32_t wr_aio_outstanding_dblks() const { return _wr_subm_cnt_dblks - _wr_cmpl_cnt_dblks; }
inline bool wr_file_rotate() const { return is_wr_full(); }
// Debug aid
const std::string status_str() const;
protected:
+ virtual void initialize(const std::string& fbasename, const u_int16_t fid, const u_int16_t lid,
+ const u_int32_t jfsize_sblks, const rcvdat* const ro);
+
virtual void open_fh();
virtual void close_fh();
static std::string filename(const std::string& fbasename, const u_int16_t fid);
void clean_file(const u_int32_t jfsize_sblks);
void create_jfile(const u_int32_t jfsize_sblks);
-
- // These functions for future use of file pool
- void get_jfile();
- void return_jfile();
};
} // namespace journal
Modified: store/trunk/cpp/lib/jrnl/jcntl.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jcntl.cpp 2008-09-26 21:00:58 UTC (rev 2549)
+++ store/trunk/cpp/lib/jrnl/jcntl.cpp 2008-09-29 13:35:20 UTC (rev 2550)
@@ -134,7 +134,8 @@
{
std::ostringstream oss;
oss << _jdir << "/" << _base_filename;
- _fc_arr[i] = new fcntl(oss.str(), i, _jfsize_sblks, 0);
+ // TODO: resolve fid/lid in following stmt:
+ _fc_arr[i] = new fcntl(oss.str(), i, i, _jfsize_sblks, 0);
}
_wrfc.initialize(_num_jfiles, _jfsize_sblks, _fc_arr);
@@ -200,7 +201,8 @@
{
std::ostringstream oss;
oss << _jdir << "/" << _base_filename;
- _fc_arr[i] = new fcntl(oss.str(), i, _jfsize_sblks, &_rcvdat);
+ // TODO: resolve fid/lid in following stmt:
+ _fc_arr[i] = new fcntl(oss.str(), i, i, _jfsize_sblks, &_rcvdat);
}
_wrfc.initialize(_num_jfiles, _jfsize_sblks, _fc_arr, &_rcvdat);
16 years, 3 months
rhmessaging commits: r2549 - in store/trunk/cpp: tests/jrnl and 1 other directory.
by rhmessaging-commits@lists.jboss.org
Author: kpvdr
Date: 2008-09-26 17:00:58 -0400 (Fri, 26 Sep 2008)
New Revision: 2549
Modified:
store/trunk/cpp/lib/jrnl/jcntl.cpp
store/trunk/cpp/lib/jrnl/jinf.cpp
store/trunk/cpp/lib/jrnl/jinf.hpp
store/trunk/cpp/lib/jrnl/lf_map.cpp
store/trunk/cpp/lib/jrnl/lf_map.hpp
store/trunk/cpp/tests/jrnl/_ut_jinf.cpp
Log:
Completed new jinf class analyze function and comprehensive boost tests. This is in preparation for journal file insertion.
Modified: store/trunk/cpp/lib/jrnl/jcntl.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jcntl.cpp 2008-09-26 19:25:40 UTC (rev 2548)
+++ store/trunk/cpp/lib/jrnl/jcntl.cpp 2008-09-26 21:00:58 UTC (rev 2549)
@@ -606,8 +606,8 @@
try
{
- rd._ffid = ji.get_start_file();
- rd._lfid = ji.get_end_file();
+ rd._ffid = ji.get_first_fid();
+ rd._lfid = ji.get_last_fid();
rd._owi = ji.get_initial_owi();
rd._frot = ji.get_frot();
rd._jempty = false;
Modified: store/trunk/cpp/lib/jrnl/jinf.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jinf.cpp 2008-09-26 19:25:40 UTC (rev 2548)
+++ store/trunk/cpp/lib/jrnl/jinf.cpp 2008-09-26 21:00:58 UTC (rev 2549)
@@ -59,8 +59,6 @@
_tm_ptr(0),
_valid_flag(false),
_analyzed_flag(false),
- _start_file(0),
- _end_file(0),
_initial_owi(false),
_frot(false)
{
@@ -88,8 +86,6 @@
_tm_ptr(std::localtime(&ts.tv_sec)),
_valid_flag(false),
_analyzed_flag(false),
- _start_file(0),
- _end_file(0),
_initial_owi(false)
{}
@@ -142,72 +138,21 @@
_valid_flag = true;
}
-u_int16_t
+void
jinf::analyze()
{
-// lf_map early_map; // map for all owi flags same as fid 0
-// lf_map late_map; // map for all owi flags opposite to fid 0
-//
-// if (!_valid_flag)
-// validate();
-// bool done = false;
-// for (u_int16_t fid=0; fid<_num_jfiles && !done; fid++)
-// {
-// std::ostringstream oss;
-// oss << _jdir << "/" << _base_filename << ".";
-// oss << std::setw(4) << std::setfill('0') << std::hex << fid;
-// oss << "." << JRNL_DATA_EXTENSION;
-// std::ifstream jifs(oss.str().c_str());
-// if (!jifs.good())
-// throw jexception(jerrno::JERR__FILEIO, oss.str(), "jinf", "analyze");
-// file_hdr fhdr;
-// jifs.read((char*)&fhdr, sizeof(fhdr));
-// if (fhdr._magic != RHM_JDAT_FILE_MAGIC) // No file header
-// {
-// if (!fid)
-// throw jexception(jerrno::JERR_JINF_JDATEMPTY, "jinf", "analyze");
-// _frot = true;
-// done = true;
-// }
-// else
-// {
-// assert(fid == fhdr._fid);
-// if (fid == 0)
-// {
-// _initial_owi = fhdr.get_owi();
-// early_map.insert(fhdr._lid, fid);
-// }
-// else
-// {
-// if (_initial_owi == fhdr.get_owi())
-// early_map.insert(fhdr._lid, fid);
-// else
-// late_map.insert(fhdr._lid, fid);
-// }
-// }
-// jifs.close();
-// } // for (fid)
-//
-// // If this is not the first rotation, all files should be in either early or late maps
-// if (!_frot) assert(early_map.size() + late_map.size() == _num_jfiles);
-//
-// if (late_map.empty())
-// _start_file = 0;
-// else
-// _start_file = (*late_map.begin()).second;
-// -------------------
- u_int16_t ffid = 0xffff;
- bool owi = false;
bool done = false;
-
- if (!_valid_flag)
- validate();
- u_int16_t fnum=0;
- while (!done && fnum < _num_jfiles)
+ lf_map early_map; // map for all owi flags same as fid 0
+ lf_map late_map; // map for all owi flags opposite to fid 0
+
+ if (!_valid_flag)
+ validate();
+ done = false;
+ for (u_int16_t fid=0; fid<_num_jfiles && !done; fid++)
{
std::ostringstream oss;
oss << _jdir << "/" << _base_filename << ".";
- oss << std::setw(4) << std::setfill('0') << std::hex << fnum;
+ oss << std::setw(4) << std::setfill('0') << std::hex << fid;
oss << "." << JRNL_DATA_EXTENSION;
std::ifstream jifs(oss.str().c_str());
if (!jifs.good())
@@ -216,30 +161,37 @@
jifs.read((char*)&fhdr, sizeof(fhdr));
if (fhdr._magic != RHM_JDAT_FILE_MAGIC) // No file header
{
- if (!fnum)
+ if (!fid) // fid 0 == lid 0 cannot be empty
throw jexception(jerrno::JERR_JINF_JDATEMPTY, "jinf", "analyze");
_frot = true;
done = true;
}
- else if (fnum == 0) // First file only
+ else
{
- owi = fhdr.get_owi();
- _initial_owi = owi;
- ffid = 0;
+ assert(fid == fhdr._fid);
+ if (fid == 0)
+ {
+ _initial_owi = fhdr.get_owi();
+ early_map.insert(fhdr._lid, fid);
+ }
+ else
+ {
+ if (_initial_owi == fhdr.get_owi())
+ early_map.insert(fhdr._lid, fid);
+ else
+ late_map.insert(fhdr._lid, fid);
+ }
}
- else if (fhdr.get_owi() != owi) // Change in OWI
- {
- ffid = fnum;
- done = true;
- }
- else
- _end_file = fnum;
jifs.close();
- fnum++;
- }
- _start_file = ffid;
+ } // for (fid)
+
+ // If this is not the first rotation, all files should be in either early or late maps
+ if (!_frot) assert(early_map.size() + late_map.size() == _num_jfiles);
+
+ _fidl.clear();
+ late_map.get_fid_list(_fidl);
+ early_map.get_fid_list(_fidl);
_analyzed_flag = true;
- return _start_file;
}
void
@@ -263,21 +215,29 @@
}
u_int16_t
-jinf::get_start_file()
+jinf::get_first_fid()
{
if (!_analyzed_flag)
analyze();
- return _start_file;
+ return *_fidl.begin();
}
u_int16_t
-jinf::get_end_file()
+jinf::get_last_fid()
{
if (!_analyzed_flag)
analyze();
- return _end_file;
+ return *_fidl.rbegin();
}
+jinf::fid_list&
+jinf::get_fid_list()
+{
+ if (!_analyzed_flag)
+ analyze();
+ return _fidl;
+}
+
bool
jinf::get_initial_owi()
{
@@ -302,8 +262,7 @@
oss << "Journal ID \"" << _jid << "\" initialized " << (_tm_ptr->tm_year + 1900) << "/";
oss << std::setw(2) << (_tm_ptr->tm_mon + 1) << "/" << std::setw(2) << _tm_ptr->tm_mday << " ";
oss << std::setw(2) << _tm_ptr->tm_hour << ":" << std::setw(2) << _tm_ptr->tm_min << ":";
- oss << std::setw(2) << _tm_ptr->tm_sec << "." << std::setw(9) << _ts.tv_nsec << ":" <<
- std::endl;
+ oss << std::setw(2) << _tm_ptr->tm_sec << "." << std::setw(9) << _ts.tv_nsec << ":" << std::endl;
oss << " Journal directory: \"" << _jdir << "\"" << std::endl;
oss << " Journal base filename: \"" << _base_filename << "\"" << std::endl;
oss << " Journal version: " << (unsigned)_jver << std::endl;
@@ -313,8 +272,7 @@
oss << " Datablock size (JRNL_DBLK_SIZE): " << _dblk_size << " bytes" << std::endl;
oss << " Write page size: " << _wcache_pgsize_sblks << " sblks" << std::endl;
oss << " Number of write pages: " << _wcache_num_pages << std::endl;
- oss << " Read page size (JRNL_RMGR_PAGE_SIZE): " << _rcache_pgsize_sblks << " sblks" <<
- std::endl;
+ oss << " Read page size (JRNL_RMGR_PAGE_SIZE): " << _rcache_pgsize_sblks << " sblks" << std::endl;
oss << " Number of read pages (JRNL_RMGR_PAGES): " << _rcache_num_pages << std::endl;
return oss.str();
}
@@ -322,9 +280,10 @@
const std::string
jinf::xml_str() const
{
+ // TODO: This is *not* an XML writer, rather for simplicity, it uses literals. I'm sure a more elegant way can be
+ // found to do this using the real thing...
+
std::ostringstream oss;
- // TODO: I'm sure a more elegant way can be found to do this, but direct and simple
- // seems like a good start!
oss << std::setfill('0');
oss << "<?xml version=\"1.0\" ?>" << std::endl;
oss << "<jrnl>" << std::endl;
@@ -362,16 +321,16 @@
void
jinf::read(const std::string& jinf_filename)
{
- // TODO: This is *not* an XML reader, rather for simplicity, it is a brute-force
- // line reader which relies on string recognition.
+ // TODO: This is *not* an XML reader, rather for simplicity, it is a brute-force line reader which relies on string
+ // recognition. Can it be replaced cheaply by the real thing?
- char buff[1024];
+ char buff[1024]; // limit of line input length
std::ifstream jinfs(jinf_filename.c_str());
if (!jinfs.good())
throw jexception(jerrno::JERR__FILEIO, jinf_filename.c_str(), "jinf", "read");
while (jinfs.good())
{
- jinfs.getline(buff, 1024);
+ jinfs.getline(buff, 1023);
if (std::strstr(buff, "journal_version"))
_jver = u_int16_value(buff);
else if(std::strstr(buff, "id_string"))
Modified: store/trunk/cpp/lib/jrnl/jinf.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/jinf.hpp 2008-09-26 19:25:40 UTC (rev 2548)
+++ store/trunk/cpp/lib/jrnl/jinf.hpp 2008-09-26 21:00:58 UTC (rev 2549)
@@ -35,6 +35,7 @@
#include <ctime>
#include <string>
#include <sys/types.h>
+#include <vector>
namespace mrg
{
@@ -46,6 +47,9 @@
*/
class jinf
{
+ public:
+ typedef std::vector<u_int16_t> fid_list;
+
private:
u_int8_t _jver;
std::string _jid;
@@ -63,8 +67,7 @@
std::tm* _tm_ptr;
bool _valid_flag;
bool _analyzed_flag;
- u_int16_t _start_file;
- u_int16_t _end_file;
+ fid_list _fidl;
bool _initial_owi;
bool _frot;
@@ -79,7 +82,7 @@
virtual ~jinf();
void validate();
- u_int16_t analyze();
+ void analyze();
void write();
inline u_int8_t jver() const { return _jver; }
@@ -97,8 +100,9 @@
inline u_int16_t wcache_num_pages() const { return _wcache_num_pages; }
inline u_int32_t rcache_pgsize_sblks() const { return _rcache_pgsize_sblks; }
inline u_int16_t rcache_num_pages() const { return _rcache_num_pages; }
- u_int16_t get_start_file();
- u_int16_t get_end_file();
+ u_int16_t get_first_fid();
+ u_int16_t get_last_fid();
+ fid_list& get_fid_list();
bool get_initial_owi();
bool get_frot();
Modified: store/trunk/cpp/lib/jrnl/lf_map.cpp
===================================================================
--- store/trunk/cpp/lib/jrnl/lf_map.cpp 2008-09-26 19:25:40 UTC (rev 2548)
+++ store/trunk/cpp/lib/jrnl/lf_map.cpp 2008-09-26 21:00:58 UTC (rev 2549)
@@ -61,5 +61,20 @@
fid_list.push_back(i->second);
}
+// debug aid
+std::string
+lf_map::to_string()
+{
+ std::ostringstream oss;
+ oss << "{lid:fid ";
+ for (lfmap_citr i=_map.begin(); i!=_map.end(); i++)
+ {
+ if (i != _map.begin()) oss << ", ";
+ oss << (*i).first << ":" << (*i).second;
+ }
+ oss << "}";
+ return oss.str();
+}
+
} // namespace journal
} // namespace mrg
Modified: store/trunk/cpp/lib/jrnl/lf_map.hpp
===================================================================
--- store/trunk/cpp/lib/jrnl/lf_map.hpp 2008-09-26 19:25:40 UTC (rev 2548)
+++ store/trunk/cpp/lib/jrnl/lf_map.hpp 2008-09-26 21:00:58 UTC (rev 2549)
@@ -34,6 +34,7 @@
#define mrg_journal_lf_map_hpp
#include <map>
+#include <string>
#include <sys/types.h>
#include <vector>
@@ -52,6 +53,7 @@
public:
typedef std::map<u_int16_t, u_int16_t> lfmap;
typedef lfmap::const_iterator lfmap_citr;
+ typedef lfmap::const_reverse_iterator lfmap_critr;
private:
typedef std::pair<u_int16_t, u_int16_t> lfpair;
@@ -67,7 +69,12 @@
inline bool empty() const { return _map.empty(); }
inline lfmap_citr begin() { return _map.begin(); }
inline lfmap_citr end() { return _map.end(); }
+ inline lfmap_critr rbegin() { return _map.rbegin(); }
+ inline lfmap_critr rend() { return _map.rend(); }
void get_fid_list(std::vector<u_int16_t>& fid_list);
+
+ // debug aid
+ std::string to_string();
};
} // namespace journal
Modified: store/trunk/cpp/tests/jrnl/_ut_jinf.cpp
===================================================================
--- store/trunk/cpp/tests/jrnl/_ut_jinf.cpp 2008-09-26 19:25:40 UTC (rev 2548)
+++ store/trunk/cpp/tests/jrnl/_ut_jinf.cpp 2008-09-26 21:00:58 UTC (rev 2549)
@@ -35,9 +35,11 @@
#include <iostream>
#include "jrnl/file_hdr.hpp"
#include "jrnl/jcfg.hpp"
+#include "jrnl/jdir.hpp"
#include "jrnl/jerrno.hpp"
#include "jrnl/jexception.hpp"
#include "jrnl/jinf.hpp"
+#include <map>
#include <vector>
#define NUM_JFILES 4
@@ -56,95 +58,456 @@
// === Helper functions ===
const string jid("test journal id");
-const string base_filename("test_base");
+const string base_filename("test_base_");
timespec ts;
-enum rid_scheme { RID_NONE, RID_LINEAR };
-void create_journal_filenames(vector<string>& jfiles)
+/*
+* This test helper class is used by first setting up a map or "blueprint" of what the journal should
+* look like for recovery, then creating it. The jinf object under test then reads and analyzes the
+* created journal, and its analysis is checked against what is expected.
+*
+* General usage pattern:
+* 1. create instance of lid_fid_map.
+* 2. call lid_fid_map::initial_journal_create() to simulate initial journal creation.
+* 3. (optional) call lid_fid_map::journal_append() one or more times to simulate the addition of journal files.
+* 4. call lid_fid_map::create_journal() to create dummy journal files (files containing only file headers)
+* 5. create and initialize the jinf object under test
+* 6. call jinf::analyze() to determine the fid order - and thus also first and last lids
+* 7. call lid_fid_map::check_analysis() to check the conclusions of the analysis
+* 8. call lid_fid_map::destroy_journal() to delete the journal files and reset the lid_fid_map object.
+* 9. (optional) back to step 2 for more tests
+*
+* See the individual methods below for more details.
+*/
+class lid_fid_map
{
- for (int fnum=0; fnum<NUM_JFILES; fnum++)
- {
- stringstream fn;
- fn << test_dir << "/" << base_filename << ".";
- fn << setfill('0') << hex << setw(4) << fnum << "." << JRNL_DATA_EXTENSION;
- jfiles.push_back(fn.str());
- }
-}
+ public:
+ typedef pair<u_int16_t, file_hdr> lfpair; // Used for loading the map
+ typedef multimap<u_int16_t, file_hdr> lfmap; // Stores the journal "plan" before it is created on-disk
+ typedef lfmap::const_iterator lfmap_citr; // General purpose iterator
+ typedef pair<lfmap_citr, lfmap_citr> lfmap_range; // Range of values returned by multimap's equal_range() fn
-void init_fhdr(file_hdr& fh, const u_int32_t fid, const u_int64_t rid, const bool owi,
- const bool no_enq = false)
-{
- fh._magic = RHM_JDAT_FILE_MAGIC;
- fh._version = RHM_JDAT_VERSION;
+ private:
+ lfmap _map; // Stores the journal "blueprint" before it is created on-disk
+ u_int16_t _num_used_files; // number of files which contain jorunals
+ u_int16_t _oldest_lid; // lid where owi flips; always 0 if !_full
+ u_int16_t _last_fid; // last fid (ie file added)
+
+ public:
+ lid_fid_map() : _num_used_files(0), _oldest_lid(0), _last_fid(0) {}
+ virtual ~lid_fid_map() {}
+
+ // Mainly used for debugging
+ void print()
+ {
+ int cnt = 0;
+ for (lfmap_citr i=_map.begin(); i!=_map.end(); i++, cnt++)
+ {
+ const file_hdr fh = i->second;
+ cout << " " << cnt << ": owi=" << (fh.get_owi()?"t":"f") << hex << " frid=0x" << fh._rid;
+ cout << " fid=0x" << fh._fid << " lid=0x" << fh._lid << " fro=0x" << fh._fro << dec << endl;
+ }
+ }
+
+ std::size_t size()
+ {
+ return _map.size();
+ }
+
+ /*
+ * Method initial_journal_create(): Used to simulate the initial creation of a journal before file insertions
+ * take place.
+ *
+ * num_jfiles: The initial journal file count.
+ * num_used_jfiles: If this number is less than num_jfiles, it indicates a clean journal that has not yet
+ * completed its first rotation, and some files are empty (ie all null). The first
+ * num_used_jfiles will contain file headers, the remainder will be blank.
+ * oldest_lid: The lid (==fid, see note 1 below) at which the owi flag flips. During normal operation, each
+ * time the journal rotates back to file 0, a flag (called the overwrite indicator or owi) is
+ * flipped. This flag is saved in the file header. During recovery, if scanning from logical
+ * file 0 upwards, the file at which this flag reverses from its value in file 0 is the file
+ * that was to have been overwritten next, and is thus the "oldest" file. Recovery analysis must
+ * start with this file. oldest_lid sets the file at which this flag will flip value for the
+ * simulated recovery analysis. Note that this will be ignored if num_used_jfiles < num_jfiles,
+ * as it is not possible for an overwrite to have occurred if not all the files have been used.
+ * first_owi: Sets the value of the owi flag in file 0. If set to false, then the flip will be found with
+ * a true flag (and visa versa).
+ *
+ * NOTES:
+ * 1. By definition, the lids and fids coincide for a journal containing no inserted files. Thus fid == lid for
+ * all journals created after using initial_journal_create() alone.
+ * 2. By definition, if a journal is not full (num_used_jfiles < num_jfiles), then all owi flags for those files
+ * that are used must be the same. It is not possible for an overwrite situation to arise if a journal is not
+ * full.
+ * 3. This function acts on map _map only, and does not create any test files. Call journal_create() to do that.
+ * 4. This function must be called on a clean test object or on one where the previous test data has been
+ * cleared by calling journal_destroy(). Running this function moret than once on existing data will
+ * result in invalid journals which cannot be recovered.
+ */
+ void initial_journal_create(const u_int16_t num_jfiles, // Total number of files
+ const u_int16_t num_used_jfiles, // Number of used files, rest empty at end
+ const u_int16_t oldest_lid = 0, // Fid where owi reverses
+ const bool first_owi = false) // Value of first owi flag (ie fid=0)
+ {
+ const bool full = num_used_jfiles == num_jfiles;
+ bool owi = first_owi;
+ _oldest_lid = full ? oldest_lid : 0;
+ for (u_int16_t lid = 0; lid < num_jfiles; lid++)
+ {
+ const u_int16_t fid = lid;
+ file_hdr fh;
+ if (fid < num_used_jfiles)
+ {
+ _num_used_files = num_used_jfiles;
+ if (full && oldest_lid > 0 && lid == oldest_lid)
+ owi = ~owi; // Flip owi if all files in use and oldest_lid > 0
+ const u_int64_t frid = u_int64_t(random());
+ init_fhdr(fh, frid, fid, lid, owi);
+ }
+ _map.insert(lfpair(lid, fh));
+ }
+ }
+
+ /*
+ * Method journal_append(): Used to simulate the addition of journal files into an existing journal. When one or
+ * more files are inserted after a particular lid, the lids of the following files are incremented. The fids of
+ * the inserted files follow those of all existing files, thus leading to a lid-fid discreppancy.
+ *
+ * Example: Before insertion:
+ * Logical view: Physical view:
+ * +---+---+---+---+---+---+ +---+---+---+---+---+---+
+ * lid --> | 0 | 1 | 2 | 3 | 4 | 5 | lid --> | 0 | 1 | 2 | 3 | 4 | 5 |
+ * +---+---+---+---+---+---+ +---+---+---+---+---+---+
+ * fid --> 0 1 2 3 4 5 fid --> 0 1 2 3 4 5
+ *
+ * After insertion of 2 files after lid 2 (marked with *s):
+ * Logical view: Physical view:
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * lid --> | 0 | 1 | 2 |*3*|*4*| 5 | 6 | 7 | lid --> | 0 | 1 | 2 | 5 | 6 | 7 |*3*|*4*|
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * fid --> 0 1 2 6 7 3 4 5 fid --> 0 1 2 3 4 5 6 7
+ *
+ * Note that the journal only writes file headers (and hence the lids in those headers) as the files are
+ * overwritten. If the journal should fail after insertion but before the files following those inserted are
+ * overwritten, then duplicate lids will be present (though no duplicate fids are possible). The overwrite
+ * indicator (owi) flag and the fid numbers may be used to resolve the ambiguity and determine the logically
+ * earlier lid in this case as follows:
+ *
+ * Example: Before insertion:
+ * Logical view: Physical view:
+ * +---+---+---+---+---+---+ +---+---+---+---+---+---+
+ * lid --> | 0 | 1 | 2 | 3 | 4 | 5 | lid --> | 0 | 1 | 2 | 3 | 4 | 5 |
+ * owi --> | t | t | t | f | f | f | owi --> | t | t | t | f | f | f |
+ * +---+---+---+---+---+---+ +---+---+---+---+---+---+
+ * fid --> 0 1 2 3 4 5 fid --> 0 1 2 3 4 5
+ *
+ * After insertion of 2 files after lid 2 (marked with *s) and failure:
+ * Logical view: Physical view:
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * lid --> | 0 | 1 | 2 |*3*|*4*| 3 | 4 | 5 | lid --> | 0 | 1 | 2 | 3 | 4 | 5 |*3*|*4*|
+ * owi --> | t | t | t | t | t | f | f | f | owi --> | t | t | t | f | f | f | t | t |
+ * +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+
+ * fid --> 0 1 2 6 7 3 4 5 fid --> 0 1 2 3 4 5 6 7
+ *
+ * Test 1: Correct lid has owi flag that matches that of fid/lid 0
+ * Test 2: Correct lid has higher fids
+ *
+ * after_lid: The logical id (lid) after which the new file is to be inserted.
+ * num_files: The number of files to be inserted.
+ * adjust_lids: Flag indicating that the lids of files _following_ the inserted files are to be adjusted upwards
+ * by the number of inserted files. Not doing so simulates a recovery immediatly after insertion
+ * but before the following files are overwritten with their new lids. If this is set false, then:
+ * a) after_lid MUST be the most recent file (_oldest_lid-1 ie last lid before owi changes).
+ * b) This call must be the last insert call.
+ *
+ * NOTES:
+ * 1. It is not possible to insert before lid/fid 0; thus these are always coincident. This operation is
+ * logically equivilent to inserting after the last lid, which is possible.
+ * 2. It is not possible to append to a journal that is not full. Doing so will result in an unrecoverable
+ * journal (one that is logically inconsistent that can never occur in reality).
+ * 3. If a journal is stopped/interrupted immediately after a file insertion, there could be duplicate lids in
+ * play at recovery, as the following file lids in their headers are only overwritten when the file is
+ * eventually written to during normal operation. The owi flags, however, are used to determine which of the
+ * ambiguous lids are the inserted files.
+ */
+ void journal_append(const u_int16_t after_lid, // Insert files after this lid
+ const u_int16_t num_files = 1, // Number of files to insert
+ const bool adjust_lids = true) // Adjust lids following inserted files
+ {
+ _num_used_files += num_files;
+ const u_int16_t num_jfiles_before_append = _map.size();
+ lfmap_citr i = _map.find(after_lid);
+ if (i == _map.end()) BOOST_FAIL("Unable to find lid=" << after_lid << " in map.");
+ const file_hdr fh_before = (*i).second;
+
+ // Move overlapping lids (if req'd)
+ if (adjust_lids && after_lid < num_jfiles_before_append - 1)
+ {
+ for (u_int16_t lid = num_jfiles_before_append - 1; lid > after_lid; lid--)
+ {
+ lfmap_citr itr = _map.find(lid);
+ if (itr == _map.end()) BOOST_FAIL("Unable to find lid=" << after_lid << " in map.");
+ file_hdr fh = itr->second;
+ _map.erase(lid);
+ fh._lid += num_files;
+ if (lid == _oldest_lid)
+ _oldest_lid += num_files;
+ _map.insert(lfpair(fh._lid, fh));
+ }
+ }
+
+ // Add new file headers
+ u_int16_t fid = num_jfiles_before_append;
+ u_int16_t lid = after_lid + 1;
+ while (fid < num_jfiles_before_append + num_files)
+ {
+ const u_int64_t frid = u_int64_t(random());
+ const size_t fro = 0x200;
+ const file_hdr fh(RHM_JDAT_FILE_MAGIC, RHM_JDAT_VERSION, frid, fid, lid, fro, fh_before.get_owi(), true);
+ _map.insert(lfpair(lid, fh));
+ _last_fid = fid;
+ fid++;
+ lid++;
+ }
+ }
+
+ /*
+ * Method check_analysis(): Used to check the result of the test jinf object analysis by comparing the fid order
+ * array it produces against the internal map.
+ *
+ * ji: A ref to the jinf object under test.
+ */
+ void check_analysis(jinf& ji) // jinf object under test after analyze() has been called
+ {
+ BOOST_CHECK_EQUAL(ji.get_first_fid(), get_first_fid());
+ BOOST_CHECK_EQUAL(ji.get_last_fid(), get_last_fid());
+
+ jinf::fid_list& fidl = ji.get_fid_list();
+ const u_int16_t num_jfiles = _map.size();
+ const bool all_used = _num_used_files == num_jfiles;
+ BOOST_CHECK_EQUAL(fidl.size(), _num_used_files);
+
+ const u_int16_t lid_start = all_used ? _oldest_lid : 0;
+ // Because a simulated failure would leave lid dups in map and last_fid would not exist in map in this
+ // case, we must find lid_stop via fid instead. Search for fid == num_files.
+ lfmap_citr itr = _map.begin();
+ while (itr != _map.end() && itr->second._fid != _num_used_files - 1) itr++;
+ if (itr == _map.end())
+ BOOST_FAIL("check(): Unable to find fid=" << (_num_used_files - 1) << " in map.");
+ const u_int16_t lid_stop = itr->second._lid;
+
+ std::size_t fidl_index = 0;
+ for (u_int16_t lid_cnt = lid_start; lid_cnt < lid_stop; lid_cnt++, fidl_index++)
+ {
+ const u_int16_t lid = lid_cnt % num_jfiles;
+ lfmap_citr itr = _map.find(lid);
+ if (itr == _map.end())
+ BOOST_FAIL("check(): Unable to find lid=" << lid << " in map.");
+ BOOST_CHECK_EQUAL(itr->second._fid, fidl[fidl_index]);
+ }
+ }
+
+ /*
+ * Method get_fid(): Look up a fid from a known lid.
+ */
+ u_int16_t get_fid(const u_int16_t lid, const bool initial_owi = false)
+ {
+ switch (_map.count(lid))
+ {
+ case 1:
+ return _map.find(lid)->second._fid;
+ case 2:
+ for (lfmap_citr itr = _map.lower_bound(lid); itr != _map.upper_bound(lid); itr++)
+ {
+ if (itr->second.get_owi() != initial_owi)
+ return itr->second._fid;
+ }
+ default:;
+ }
+ BOOST_FAIL("get_fid(): lid=" << lid << " not found in map.");
+ return 0xffff;
+ }
+
+ /*
+ * Method get_first_fid(): Look up the first (oldest, or next-to-be-overwritten) fid in the analysis sequence.
+ */
+ u_int16_t get_first_fid()
+ {
+ return get_fid(_oldest_lid);
+ }
+
+ /*
+ * Method get_last_fid(): Look up the last (newest, or most recently written) fid in the analysis sequence.
+ */
+ u_int16_t get_last_fid()
+ {
+ u_int16_t flid = 0;
+ if (_num_used_files == _map.size()) // journal full?
+ {
+ if (_oldest_lid)
+ {
+ // if failed insert, cycle past duplicate lids
+ while (_map.count(_oldest_lid) == 2)
+ _oldest_lid++;
+ while (_map.find(_oldest_lid) != _map.end() && _map.find(_oldest_lid)->second.get_owi() == false)
+ _oldest_lid++;
+ flid = _oldest_lid - 1;
+ }
+ else
+ flid = _map.size() - 1;
+ }
+ else
+ flid = _num_used_files - 1;
+ return get_fid(flid, true);
+ }
+
+ /*
+ * Method create_journal(): Used to create the dummy journal files from the built-up map created by calling
+ * initial_journal_create() and optionally journal_append() one or more times. Since the jinf object reads the
+ * jinf file and the file headers only, the create object creates a dummy journal file containing only a file
+ * header (512 bytes each) and a single jinf file which contains the journal metadata required for recovery
+ * analysis.
+ */
+ void create_journal()
+ {
+ create_jinf();
+ u_int16_t fid = 0;
+ for (lfmap_citr itr = _map.begin(); itr != _map.end(); itr++, fid++)
+ {
+ if (itr->second._fid == 0 && itr->second._magic == 0) // empty header, use fid counter instaed
+ create_journal_file(fid, itr->second);
+ else
+ create_journal_file(itr->second._fid, itr->second);
+ }
+ }
+
+ /*
+ * Method destroy_journal(): Destroy the files created by create_journal() and reset the lid_fid_map test object.
+ * A new test may be started using the same lid_fid_map test object once this call has been made.
+ */
+ void destroy_journal()
+ {
+ for (u_int16_t fid = 0; fid < _map.size(); fid++)
+ {
+ string fn = create_journal_filename(fid);
+ BOOST_WARN_MESSAGE(::unlink(fn.c_str()) == 0, "destroy_journal(): Failed to remove file " << fn);
+ }
+ clean_journal_info_file();
+ _map.clear();
+ _num_used_files = 0;
+ _oldest_lid = 0;
+ _last_fid = 0;
+ }
+
+ /*
+ * Method create_new_jinf(): This static call creates a default jinf file only. This is used to test the read
+ * constructor of a jinf test object which reads a jinf file at instantiation.
+ */
+ static void create_new_jinf()
+ {
+ if (jdir::exists(test_dir))
+ jdir::delete_dir(test_dir);
+ create_jinf(NUM_JFILES);
+ }
+
+ /*
+ * Method clean_journal_info_file(): This static method deletes only a jinf file without harming any other
+ * journal file or its directory. This is used to clear those tests which rely only on the existance of a
+ * jinf file.
+ */
+ static void clean_journal_info_file()
+ {
+ stringstream fn;
+ fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
+ BOOST_WARN_MESSAGE(::unlink(fn.str().c_str()) == 0, "clean_journal_info_file(): Failed to remove file " << fn.str());
+ }
+
+ private:
+ static void init_fhdr(file_hdr& fh,
+ const u_int64_t frid,
+ const u_int16_t fid,
+ const u_int16_t lid,
+ const bool owi,
+ const bool no_enq = false)
+ {
+ fh._magic = RHM_JDAT_FILE_MAGIC;
+ fh._version = RHM_JDAT_VERSION;
#if defined(JRNL_BIG_ENDIAN)
- fh._eflag = RHM_BENDIAN_FLAG;
+ fh._eflag = RHM_BENDIAN_FLAG;
#else
- fh._eflag = RHM_LENDIAN_FLAG;
+ fh._eflag = RHM_LENDIAN_FLAG;
#endif
- fh._uflag = owi ? rec_hdr::HDR_OVERWRITE_INDICATOR_MASK : 0;
- fh._rid = rid;
- fh._fid = fid;
- fh._fro = no_enq ? 0 : 0x200;
- timespec ts;
- ::clock_gettime(CLOCK_REALTIME, &ts);
- fh._ts_sec = ts.tv_sec;
- fh._ts_nsec = ts.tv_nsec;
-}
+ fh._uflag = owi ? rec_hdr::HDR_OVERWRITE_INDICATOR_MASK : 0;
+ fh._rid = frid;
+ fh._fid = fid;
+ fh._lid = lid;
+ fh._fro = no_enq ? 0 : 0x200;
+ timespec ts;
+ ::clock_gettime(CLOCK_REALTIME, &ts);
+ fh._ts_sec = ts.tv_sec;
+ fh._ts_nsec = ts.tv_nsec;
+ }
-void create_journal_files(vector<string>& jfiles, rid_scheme scheme,
- u_int32_t min_fid_offs = 0, u_int64_t rid_offs = 0)
-{
- const u_int64_t rid_incr = 0x10;
- file_hdr fh;
- vector<string>::iterator itr;
- u_int32_t fid = 0;
- u_int64_t rid = rid_offs + ((NUM_JFILES - min_fid_offs) % NUM_JFILES) * rid_incr;
- for (itr=jfiles.begin(); itr<jfiles.end(); itr++)
- {
-
- ofstream of(itr->c_str(), ofstream::out | ofstream::trunc);
- if (!of.good())
- BOOST_FAIL("Unable to open test journal file " << *itr << " for writing.");
-
- // prepare file_hdr
- int cnt = sizeof(file_hdr);
- if (scheme == RID_NONE) // create file containing 0s
- std::memset(&fh, 0, cnt);
- else
- init_fhdr(fh, fid, rid, fid >= min_fid_offs);
-
- // write file header
- of.write((const char*)&fh, cnt);
-
- // fill remaining sblk with 0s
- while (cnt++ < JRNL_DBLK_SIZE * JRNL_SBLK_SIZE)
- of.put(0);
- of.close();
-
- if (++fid == min_fid_offs)
- rid -= rid_incr * (NUM_JFILES - 1);
- else
- rid += rid_incr;
- }
-}
+ void create_jinf()
+ {
+ if (jdir::exists(test_dir))
+ jdir::delete_dir(test_dir);
+ create_jinf(_map.size());
+ }
-void clean_journal_info_file()
-{
- stringstream fn;
- fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
- BOOST_WARN_MESSAGE(::unlink(fn.str().c_str()) == 0, "Failed to remove file " << fn.str());
-}
+ static void create_jinf(u_int16_t num_files)
+ {
+ jdir::create_dir(test_dir); // Check test dir exists; create it if not
+ ::clock_gettime(CLOCK_REALTIME, &ts);
+ jinf ji(jid, test_dir, base_filename, num_files, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE, JRNL_WMGR_DEF_PAGES,
+ ts);
+ ji.write();
+ }
-void clean_journal_files(vector<string>& jfiles)
-{
- for (vector<string>::iterator itr=jfiles.begin(); itr != jfiles.end(); itr++)
- BOOST_WARN_MESSAGE(::unlink(itr->c_str()) == 0, "Failed to remove file " << *itr);
- jfiles.clear();
-}
+ static void create_journal_file(const u_int16_t fid, const file_hdr& fh)
+ {
+ write_file_header(fh, create_journal_filename(fid));
+ }
+ static void write_file_header(const file_hdr& fh,
+ const string filename)
+ {
+ ofstream of(filename.c_str(), ofstream::out | ofstream::trunc);
+ if (!of.good())
+ BOOST_FAIL("Unable to open test journal file \"" << filename << "\" for writing.");
+
+ // write file header
+ u_int32_t cnt = sizeof(file_hdr);
+ of.write((const char*)&fh, cnt);
+ if (of.fail() || of.bad())
+ BOOST_FAIL("Error writing file header to test journal file \"" << filename << "\".");
+
+ // fill remaining sblk with 0s
+ while (cnt++ < JRNL_DBLK_SIZE * JRNL_SBLK_SIZE)
+ {
+ of.put(0);
+ if (of.fail() || of.bad())
+ BOOST_FAIL("Error writing filler to test journal file \"" << filename << "\".");
+ }
+
+ of.close();
+ if (of.fail() || of.bad())
+ BOOST_FAIL("Error closing test journal file \"" << filename << "\".");
+ }
+
+ static string create_journal_filename(const u_int16_t fid)
+ {
+ stringstream fn;
+ fn << test_dir << "/" << base_filename << ".";
+ fn << setfill('0') << hex << setw(4) << fid << "." << JRNL_DATA_EXTENSION;
+ return fn.str();
+ }
+};
+
QPID_AUTO_TEST_CASE(write_constructor)
{
cout << test_filename << ".write_constructor: " << flush;
+ jdir::create_dir(test_dir); // Check test dir exists; create it if not
::clock_gettime(CLOCK_REALTIME, &ts);
jinf ji(jid, test_dir, base_filename, NUM_JFILES, JFSIZE_SBLKS, JRNL_WMGR_DEF_PAGE_SIZE,
JRNL_WMGR_DEF_PAGES, ts);
@@ -152,20 +515,26 @@
BOOST_CHECK(ji.jid().compare(jid) == 0);
BOOST_CHECK(ji.jdir().compare(test_dir) == 0);
BOOST_CHECK(ji.base_filename().compare(base_filename) == 0);
- timespec this_ts = ji.ts();
+ const timespec this_ts = ji.ts();
BOOST_CHECK_EQUAL(this_ts.tv_sec, ts.tv_sec);
BOOST_CHECK_EQUAL(this_ts.tv_nsec, ts.tv_nsec);
- BOOST_CHECK_EQUAL(ji.num_jfiles(), (u_int16_t)NUM_JFILES);
- BOOST_CHECK_EQUAL(ji.jfsize_sblks(), (u_int32_t)JFSIZE_SBLKS);
- BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), (u_int16_t)JRNL_SBLK_SIZE);
- BOOST_CHECK_EQUAL(ji.dblk_size(), (u_int32_t)JRNL_DBLK_SIZE);
+ BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES));
+ BOOST_CHECK_EQUAL(ji.jfsize_sblks(), u_int32_t(JFSIZE_SBLKS));
+ BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), u_int16_t(JRNL_SBLK_SIZE));
+ BOOST_CHECK_EQUAL(ji.dblk_size(), u_int32_t(JRNL_DBLK_SIZE));
+ BOOST_CHECK_EQUAL(ji.wcache_pgsize_sblks(), u_int32_t(JRNL_WMGR_DEF_PAGE_SIZE));
+ BOOST_CHECK_EQUAL(ji.wcache_num_pages(), u_int16_t(JRNL_WMGR_DEF_PAGES));
+ BOOST_CHECK_EQUAL(ji.rcache_pgsize_sblks(), u_int32_t(JRNL_RMGR_PAGE_SIZE));
+ BOOST_CHECK_EQUAL(ji.rcache_num_pages(), u_int16_t(JRNL_RMGR_PAGES));
ji.write();
- cout << "ok" << endl;
+ cout << "done" << endl;
}
QPID_AUTO_TEST_CASE(read_constructor)
{
cout << test_filename << ".read_constructor: " << flush;
+ lid_fid_map::create_new_jinf();
+
stringstream fn;
fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
jinf ji(fn.str(), false);
@@ -176,31 +545,63 @@
const timespec this_ts = ji.ts();
BOOST_CHECK_EQUAL(this_ts.tv_sec, ts.tv_sec);
BOOST_CHECK_EQUAL(this_ts.tv_nsec, ts.tv_nsec);
- BOOST_CHECK_EQUAL(ji.num_jfiles(), (u_int16_t)NUM_JFILES);
- BOOST_CHECK_EQUAL(ji.jfsize_sblks(), (u_int32_t)JFSIZE_SBLKS);
- BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), (u_int16_t)JRNL_SBLK_SIZE);
- BOOST_CHECK_EQUAL(ji.dblk_size(), (u_int32_t)JRNL_DBLK_SIZE);
- cout << "ok" << endl;
+ BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES));
+ BOOST_CHECK_EQUAL(ji.jfsize_sblks(), u_int32_t(JFSIZE_SBLKS));
+ BOOST_CHECK_EQUAL(ji.sblk_size_dblks(), u_int16_t(JRNL_SBLK_SIZE));
+ BOOST_CHECK_EQUAL(ji.dblk_size(), u_int32_t(JRNL_DBLK_SIZE));
+ BOOST_CHECK_EQUAL(ji.wcache_pgsize_sblks(), u_int32_t(JRNL_WMGR_DEF_PAGE_SIZE));
+ BOOST_CHECK_EQUAL(ji.wcache_num_pages(), u_int16_t(JRNL_WMGR_DEF_PAGES));
+ BOOST_CHECK_EQUAL(ji.rcache_pgsize_sblks(), u_int32_t(JRNL_RMGR_PAGE_SIZE));
+ BOOST_CHECK_EQUAL(ji.rcache_num_pages(), u_int16_t(JRNL_RMGR_PAGES));
+
+ cout << "done" << endl;
}
+QPID_AUTO_TEST_CASE(set_functions)
+{
+ cout << test_filename << ".set_functions: " << flush;
+ lid_fid_map::create_new_jinf();
+
+ stringstream fn;
+ fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
+ jinf ji(fn.str(), false);
+
+ ji.set_jdir("abc123");
+ BOOST_CHECK(ji.jdir().compare("abc123") == 0);
+ ji.set_jdir(test_dir);
+ BOOST_CHECK(ji.jdir().compare(test_dir) == 0);
+ ji.incr_num_jfiles();
+ BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES+1));
+ ji.incr_num_jfiles();
+ BOOST_CHECK_EQUAL(ji.num_jfiles(), u_int16_t(NUM_JFILES+2));
+
+ lid_fid_map::clean_journal_info_file();
+ cout << "done" << endl;
+}
+
QPID_AUTO_TEST_CASE(validate)
{
cout << test_filename << ".validate: " << flush;
+ lid_fid_map::create_new_jinf();
+
stringstream fn;
fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
jinf ji(fn.str(), true);
// TODO: Check validation picks up conflict, but need to be friend to jinf to do it
- cout << "ok" << endl;
+
+ lid_fid_map::clean_journal_info_file();
+ cout << "done" << endl;
}
-
+
QPID_AUTO_TEST_CASE(analyze_empty_journal)
{
cout << test_filename << ".analyze_empty_journal: " << flush;
- vector<string> jfiles;
- create_journal_filenames(jfiles);
-
- create_journal_files(jfiles, RID_NONE);
+ jdir::create_dir(test_dir); // Check test dir exists; create it if not
+ lid_fid_map m;
+ m.initial_journal_create(NUM_JFILES, 0, 0);
+ m.create_journal();
+
stringstream fn;
fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
jinf ji(fn.str(), false);
@@ -211,31 +612,140 @@
BOOST_ERROR("Failed to throw expected exception jerrno::JERR_JINF_JDATEMPTY");
}
- clean_journal_files(jfiles);
- cout << "ok" << endl;
+ m.destroy_journal();
+ cout << "done" << endl;
}
-QPID_AUTO_TEST_CASE(analyze_linear_journal)
+QPID_AUTO_TEST_CASE(analyze_part_full_journal)
{
- cout << test_filename << ".analyze_linear_journal: " << flush;
- vector<string> jfiles;
- for (int i=0; i<NUM_JFILES; i++)
+ cout << test_filename << ".analyze_part_full_journal: " << flush;
+ lid_fid_map m;
+ for (u_int16_t num_files = 1; num_files < NUM_JFILES; num_files++)
{
- create_journal_filenames(jfiles);
-
- create_journal_files(jfiles, RID_LINEAR, i, 0x12340000);
+ m.initial_journal_create(NUM_JFILES, num_files, 0);
+ m.create_journal();
stringstream fn;
fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
jinf ji(fn.str(), false);
- BOOST_CHECK_EQUAL(ji.analyze(), i);
+ ji.analyze();
+ m.check_analysis(ji);
- clean_journal_files(jfiles);
+ m.destroy_journal();
}
-
- // last test cleans up jinf file
- clean_journal_info_file();
- cout << "ok" << endl;
+ cout << "done" << endl;
}
+QPID_AUTO_TEST_CASE(analyze_full_journal)
+{
+ cout << test_filename << ".analyze_full_journal: " << flush;
+ lid_fid_map m;
+ for (u_int16_t file_num = 0; file_num < NUM_JFILES; file_num++)
+ {
+ m.initial_journal_create(NUM_JFILES, NUM_JFILES, file_num);
+ m.create_journal();
+
+ stringstream fn;
+ fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
+ jinf ji(fn.str(), false);
+ ji.analyze();
+ m.check_analysis(ji);
+
+ m.destroy_journal();
+ }
+ cout << "done" << endl;
+}
+
+QPID_AUTO_TEST_CASE(analyze_single_appended_journal)
+{
+ cout << test_filename << ".analyze_single_appended_journal: " << flush;
+ lid_fid_map m;
+ for (u_int16_t oldest_lid = 0; oldest_lid < NUM_JFILES; oldest_lid++)
+ for (u_int16_t after_lid = 0; after_lid < NUM_JFILES; after_lid++)
+ for (u_int16_t num_files = 1; num_files <= 5; num_files++)
+ {
+ m.initial_journal_create(NUM_JFILES, NUM_JFILES, oldest_lid);
+ m.journal_append(after_lid, num_files);
+ m.create_journal();
+
+ stringstream fn;
+ fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
+ jinf ji(fn.str(), false);
+ ji.analyze();
+ m.check_analysis(ji);
+
+ m.destroy_journal();
+ }
+ cout << "done" << endl;
+}
+
+QPID_AUTO_TEST_CASE(analyze_multi_appended_journal)
+{
+ cout << test_filename << ".analyze_multi_appended_journal: " << flush;
+ lid_fid_map m;
+ ::srand48(1);
+
+ for (u_int16_t num_appends = 1; num_appends <= 2*NUM_JFILES; num_appends++)
+ {
+ const u_int16_t oldest_lid = u_int16_t(NUM_JFILES * ::drand48());
+ m.initial_journal_create(NUM_JFILES, NUM_JFILES, oldest_lid);
+ for (u_int16_t a = 0; a < num_appends; a++)
+ {
+ const u_int16_t num_files = u_int16_t(1 + (NUM_JFILES * ::drand48()));
+ const u_int16_t after_lid = u_int16_t(m.size() * ::drand48());
+ m.journal_append(after_lid, num_files);
+ }
+ m.create_journal();
+
+ stringstream fn;
+ fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
+ jinf ji(fn.str(), false);
+ ji.analyze();
+ m.check_analysis(ji);
+
+ m.destroy_journal();
+ }
+
+ cout << "done" << endl;
+}
+
+QPID_AUTO_TEST_CASE(analyze_multi_appended_then_failed_journal)
+{
+ cout << test_filename << ".analyze_multi_appended_then_failed_journal: " << flush;
+ lid_fid_map m;
+ ::srand48(1);
+
+ // As this test relies on repeatable but random sequences, use many ierations for coverage
+ for (int c = 1; c <= 100; c++)
+ {
+ for (u_int16_t num_appends = 1; num_appends <= 2*NUM_JFILES; num_appends++)
+ {
+ u_int16_t oldest_lid = u_int16_t(NUM_JFILES * ::drand48());
+ m.initial_journal_create(NUM_JFILES, NUM_JFILES, oldest_lid);
+ for (u_int16_t a = 0; a < num_appends-1; a++)
+ {
+ const u_int16_t num_files = u_int16_t(1 + (NUM_JFILES * ::drand48()));
+ const u_int16_t after_lid = u_int16_t(m.size() * ::drand48());
+ m.journal_append(after_lid, num_files);
+ if (after_lid < oldest_lid)
+ oldest_lid += num_files;
+ }
+ const u_int16_t num_files = u_int16_t(1 + (NUM_JFILES * ::drand48()));
+ const u_int16_t after_lid = oldest_lid == 0 ? m.size() - 1 : oldest_lid - 1;
+ m.journal_append(after_lid, num_files, false);
+ m.create_journal();
+
+ stringstream fn;
+ fn << test_dir << "/" << base_filename << "." << JRNL_INFO_EXTENSION;
+ jinf ji(fn.str(), false);
+ ji.analyze();
+ m.check_analysis(ji);
+
+ m.destroy_journal();
+ }
+ }
+
+ cout << "done" << endl;
+}
+
QPID_AUTO_TEST_SUITE_END()
16 years, 3 months
rhmessaging commits: r2548 - mgmt/trunk/cumin/python/cumin.
by rhmessaging-commits@lists.jboss.org
Author: justi9
Date: 2008-09-26 15:25:40 -0400 (Fri, 26 Sep 2008)
New Revision: 2548
Modified:
mgmt/trunk/cumin/python/cumin/tools.py
Log:
Refactor add user, and add a change password admin command
Modified: mgmt/trunk/cumin/python/cumin/tools.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/tools.py 2008-09-26 19:24:30 UTC (rev 2547)
+++ mgmt/trunk/cumin/python/cumin/tools.py 2008-09-26 19:25:40 UTC (rev 2548)
@@ -2,14 +2,26 @@
from parsley.command import *
from mint import *
-from crypt import crypt
from getpass import getpass
-from random import sample
from psycopg2 import IntegrityError
from cumin import CuminConfig
from util import *
+def prompt_password():
+ password = None
+
+ while password is None:
+ once = getpass("Type password: ")
+ twice = getpass("Retype password: ")
+
+ if once == twice:
+ password = once
+ else:
+ print "Passwords don't match; try again"
+
+ return password
+
class BaseCuminTool(Command):
def __init__(self, name):
super(BaseCuminTool, self).__init__(None, name)
@@ -140,6 +152,10 @@
command.description = "Remove USER from ROLE"
command.arguments = ("USER", "ROLE")
+ command = self.ChangePassword(self, "change-password")
+ command.description = "Change password of USER"
+ command.arguments = ("USER",)
+
def init(self):
super(CuminAdminTool, self).init()
@@ -178,20 +194,8 @@
print "Error: a user called '%s' already exists" % name
sys.exit(1)
- password = None
+ crypted = crypt_password(prompt_password())
- while password is None:
- once = getpass("Set password: ")
- twice = getpass("Retype password: ")
-
- if once == twice:
- password = once
- else:
- print "Passwords don't match; try again"
-
- chs = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- crypted = crypt(password, "".join(sample(chs, 2)))
-
try:
subject = Subject(name=name, password=crypted)
@@ -311,4 +315,20 @@
class ChangePassword(Command):
def run(self, opts, args):
- pass
+ try:
+ ssubject = args[1]
+ except IndexError:
+ raise CommandException(self, "USER is required")
+
+ subject = Subject.getByName(ssubject)
+
+ if not subject:
+ raise CommandException\
+ (self, "User '%s' is unknown" % subject.name)
+
+ crypted = crypt_password(prompt_password())
+
+ subject.password = crypted
+ subject.syncUpdate()
+
+ print "Password of user '%s' is changed" % subject.name
16 years, 3 months
rhmessaging commits: r2547 - mgmt/trunk/cumin/python/cumin.
by rhmessaging-commits@lists.jboss.org
Author: justi9
Date: 2008-09-26 15:24:30 -0400 (Fri, 26 Sep 2008)
New Revision: 2547
Modified:
mgmt/trunk/cumin/python/cumin/util.py
Log:
Move the password crypt function to util, since we'll be using it from several places now
Modified: mgmt/trunk/cumin/python/cumin/util.py
===================================================================
--- mgmt/trunk/cumin/python/cumin/util.py 2008-09-25 20:11:49 UTC (rev 2546)
+++ mgmt/trunk/cumin/python/cumin/util.py 2008-09-26 19:24:30 UTC (rev 2547)
@@ -1,3 +1,4 @@
+import sys
from ConfigParser import SafeConfigParser
from datetime import datetime, timedelta
from logging import getLogger
@@ -4,7 +5,8 @@
from time import mktime, time, sleep
from random import randint
from xml.sax.saxutils import escape as xml_escape
-import sys
+from crypt import crypt
+from random import sample
def short_id():
return "%08x" % randint(0, sys.maxint)
@@ -197,3 +199,8 @@
return False
sleep(1)
+
+password_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+
+def crypt_password(password):
+ return crypt(password, "".join(sample(password_chars, 2)))
16 years, 3 months