Commit Graph

150 Commits

Author SHA1 Message Date
Brion Vibber
0535a3d15c Event hook for SQLProfile 2010-12-17 11:46:11 -08:00
Brion Vibber
a7d98435f6 Tweak DB query logging to also log queries that fail; the exceptions we get are often not very descriptive like "No such table" without saying which table. :) 2010-10-15 11:26:06 -07:00
Brion Vibber
59119482ca Merge branch '0.9.x' of gitorious.org:statusnet/mainline into 1.0.x
Conflicts:
	actions/hostmeta.php
	actions/imsettings.php
	classes/User.php
	lib/adminpanelaction.php
	lib/channel.php
	lib/default.php
	lib/router.php
	lib/util.php
2010-10-04 12:54:36 -07:00
Siebrand Mazeland
b03ece26eb * i18n/L10n and translator documentation updates.
* whitespace and indentation updates
2010-09-28 23:21:09 +02:00
Evan Prodromou
a319b40c97 common_cache_key() -> Cache::key() 2010-09-06 10:07:43 -04:00
Evan Prodromou
e42d2124a3 common_keyize() -> Cache::keyize() 2010-09-06 10:03:51 -04:00
Evan Prodromou
8f81762d68 common_memcache() => Cache::instance() 2010-09-06 09:56:45 -04:00
Brion Vibber
7e55fc0044 OStatus/FeedSub: tweaked PuSH feed garbage collection so other plugins can declare usage of a low-level feed or an OStatus profile besides profile subscriptions & group memberships.
SubMirror: redid add-mirror frontend to accept a feed URL, then pass that on to OStatus, instead of pulling from your subscriptions.
Profile: tweaked subscriberCount() so it doesn't subtract 1 for foreign profiles who aren't subscribed to themselves; instead excludes the self-subscription in the count query.
Memcached_DataObject: tweak to avoid extra error spew in the DB error raising

Work in progress: tweaking feedsub garbage collection so we can count other uses
2010-08-06 11:49:52 -07:00
Evan Prodromou
9f0715a993 Merge branch '0.9.x' into 1.0.x 2010-08-03 16:05:03 -07:00
Siebrand Mazeland
e753422480 * Address i18n related FIXMEs after talk with Brion.
* Tweak message
2010-07-30 19:15:07 +02:00
Siebrand Mazeland
e7acb45b57 * add string for translation with translator documentation
* add FIXMEs for strings that may need i18n, but leaving decision to other dev(s)
2010-07-29 12:58:48 +02:00
Evan Prodromou
d73feb82d8 cache sitemap notice and user counts for 4h 2010-07-14 10:38:34 -04:00
Brion Vibber
004200f958 Merge branch '0.9.x' of gitorious.org:statusnet/mainline into 1.0.x 2010-06-11 12:09:55 -07:00
Evan Prodromou
6d39a75137 use DB_DataObject_Cast objects in a couple of different places in the code 2010-06-04 15:29:38 -04:00
Evan Prodromou
f1ea678aae memcache_dataobject supports some DB_DataObject_Cast objects as values 2010-06-04 12:52:05 -04:00
Evan Prodromou
727ea5a516 Merge branch '0.9.x' into 1.0.x 2010-04-07 10:47:29 -04:00
Evan Prodromou
76cce8a3c5 Merge branch 'master' into 0.9.x 2010-04-07 10:46:23 -04:00
Evan Prodromou
08745e4eac Merge branch 'master' into testing 2010-04-07 10:45:44 -04:00
Evan Prodromou
82326a3b69 show PEAR_Error message, not the object 2010-04-07 10:43:14 -04:00
Brion Vibber
01a03e34c8 Merge branch '0.9.x' into 1.0.x 2010-03-29 15:15:51 -07:00
Brion Vibber
d44e5ac935 Add $config['db']['annotate_queries'] option to include caller ID comments into queries. Comment can then be seen in process list, slow query logs on the server, aiding in tracking down unexpected slow queries.
SELECT /* queuedaemon.php Ostatus_profile->processPost */ * FROM notice WHERE ( notice.uri = 'http://stormcloud.local/mublog2/notice/479' )
INSERT /* POST Notice::saveNew */ INTO notice (profile_id , content ....
2010-03-29 13:14:11 -07:00
Brion Vibber
abf2ce873b Avoid notice when reporting DB errors for objects that don't have an 'id' field 2010-03-24 14:18:25 -07:00
Brion Vibber
2aaf8d4e30 Add class and (if present) id to DB_DataObject error exceptions; often they're VERRRRRY vague, and it helps to know what type of item is failing! 2010-02-24 01:09:12 +00:00
Brion Vibber
81b6b58e33 Merge branch 'master' into testing
Conflicts:
	lib/stompqueuemanager.php
2010-02-16 09:22:02 -08:00
Brion Vibber
c74aea589d Stomp queue restructuring for mass scalability:
- Multiplexing queues into groups and for multiple sites.
- Sharing vs breakout configurable per site and per queue via $config['queue']['breakout']
- Detect how many times a message is redelivered, discard if it's killed too many daemons
 - count configurable with $config['queue']['max_retries']
 - can dump the items to files in $config['queue']['dead_letter_dir']

Queue daemon memory & resource leak fixes:
- avoid unnecessary reconnections to memcached server (switch persistent connections back in on second initialization, assuming it's child process)
- monkey-patch for leaky .ini loads in DB_DataObject::databaseStructure() - was leaking 200k per active switch
- applied leak fixes to Status_network as well, using intermediate base Safe_DataObject for both it and Memcache_DataObject

Misc queue fixes:
- correct handling of child processes exiting due to signal termination instead of regular exit
- shutdown instead of infinite respawn loop if we're already past the soft memory limit at startup
- Added --all option for xmppdaemon... still opens one xmpp connection per site that has xmpp active

Cache updates:
- add Cache::increment() method with native support for memcached atomic increment
2010-02-16 09:16:51 -08:00
Brion Vibber
875e1a70ce Don't spew warnings on usage of MEMCACHE_COMPRESSED constant when memcache PHP extension is not present.
Switched to a locally-defined Cache::COMPRESSED, translating that to MEMCACHE_COMPRESSED in the plugin.
2010-02-05 09:47:56 -08:00
Evan Prodromou
f6eecf02fc add simple cache getter/setter static functions to Memcached_DataObject 2010-01-29 15:01:21 -05:00
Evan Prodromou
513f8be07a hide most DB_DataObject errors 2010-01-28 16:26:55 -05:00
Evan Prodromou
d5f86f7a8a Merge branch 'master' of git@gitorious.org:statusnet/mainline 2010-01-28 13:54:19 -05:00
Evan Prodromou
84b5480007 update mysqltimestamps on insert and update 2010-01-28 13:54:01 -05:00
Brion Vibber
ffaaf9de4a Don't preemptively close existing DB connections for web views (needed to keep # of conns from going insane on multi-site queue daemons, so just doing for CLI)
May, or may not, help with mystery session problems
2010-01-27 23:51:22 -08:00
Evan Prodromou
663e4e02a1 Merge branch 'master' into testing
Conflicts:
	lib/queuemanager.php
2010-01-25 18:13:09 -05:00
Evan Prodromou
e26a843caf Offload inbox updates to a queue handler to speed up posting online
Moved much of the writing that happens when posting a notice to a new
queuehandler, distribqueuehandler. This updates tags, groups, replies
and inboxes at queue time (or at Web time, if queues are disabled).

To make this work well, I had to break up the monolithic
Notice::blowCaches() and make cache blowing happen closer to where
data is updated.

Squashed commit of the following:

commit 5257626c62750ac4ac1db0ce2b71410c5711cfa3
Author: Evan Prodromou <evan@status.net>
Date:   Mon Jan 25 14:56:41 2010 -0500

    slightly better handling of blowing tag memory cache

commit 8a22a3cdf6ec28685da129a0313e7b2a0837c9ef
Author: Evan Prodromou <evan@status.net>
Date:   Mon Jan 25 01:42:56 2010 -0500

    change 'distribute' to 'distrib' so not too long for dbqueue

commit 7a063315b0f7fad27cb6fbd2bdd74e253af83e4f
Author: Evan Prodromou <evan@status.net>
Date:   Mon Jan 25 01:39:15 2010 -0500

    change handle_notice() to handle() in distributqueuehandler

commit 1a39ccd28b9994137d7bfd21bb4f230546938e77
Author: Evan Prodromou <evan@status.net>
Date:   Mon Jan 25 16:05:25 2010 -0500

    error with queuemanager

commit e6b3bb93f305cfd2de71a6340b8aa6fb890049b7
Author: Evan Prodromou <evan@status.net>
Date:   Mon Jan 25 01:11:34 2010 -0500

    Blow memcache at different point rather than one big function for Notice class

commit 94d557cdc016187d1d0647ae1794cd94d6fb8ac8
Author: Evan Prodromou <evan@status.net>
Date:   Mon Jan 25 00:48:44 2010 -0500

    Blow memcache at different point rather than one big function for Notice class

commit 1c781dd08c88a35dafc5c01230b4872fd6b95182
Author: Evan Prodromou <evan@status.net>
Date:   Wed Jan 20 08:54:18 2010 -0500

    move broadcasting and distributing to new queuehandler

commit da3e46d26b84e4f028f34a13fd2ee373e4c1b954
Author: Evan Prodromou <evan@status.net>
Date:   Wed Jan 20 08:53:12 2010 -0500

    Move distribution of notices to new distribute queue handler
2010-01-25 18:08:21 -05:00
Evan Prodromou
e6cf293db8 Recover caching logic lost in bad merge
I made a bad merge on Jan 10th from master to 0.9.x. This lost a number
of memcache enhancements made on the 0.9.x branch. I've been able to
re-do the manual merge, and this represents the changes. Most of them
are related to caching on insert.
2010-01-24 22:39:32 -05:00
Evan Prodromou
29d83c8ca9 Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing 2010-01-22 14:18:21 -05:00
Evan Prodromou
a3e484a0e8 Memcached_DataObject unnecessarily require_once'd itself 2010-01-22 10:46:11 -05:00
Brion Vibber
8dafe09ab2 Option to log slow db queries or all db queries
$config['db']['log_queries'] = true; // all
$config['db']['log_slow_queries'] = 10; // queries taking > 10 seconds
2010-01-21 11:07:52 -08:00
Brion Vibber
ec145b73fc Major refactoring of queue handlers to support running multiple sites in one daemon.
Key changes:
* Initialization code moved from common.php to StatusNet class;
  can now switch configurations during runtime.
* As a consequence, configuration files must now be idempotent...
  Be careful with constant, function or class definitions.
* Control structure for daemons/QueueManager/QueueHandler has been refactored;
  the run loop is now managed by IoMaster run via scripts/queuedaemon.php
  IoManager subclasses are woken to handle socket input or polling, and may
  cover multiple sites.
* Plugins can implement notice queue handlers more easily by registering a
  QueueHandler class; no more need to add a daemon.

The new QueueDaemon runs from scripts/queuedaemon.php:

* This replaces most of the old *handler.php scripts; they've been refactored
  to the bare handler classes.
* Spawns multiple child processes to spread load; defaults to CPU count on
  Linux and Mac OS X systems, or override with --threads=N
* When multithreaded, child processes are automatically respawned on failure.
* Threads gracefully shut down and restart when passing a soft memory limit
  (defaults to 90% of memory_limit), limiting damage from memory leaks.
* Support for UDP-based monitoring: http://www.gitorious.org/snqmon

Rough control flow diagram:
QueueDaemon -> IoMaster -> IoManager
                           QueueManager [listen or poll] -> QueueHandler
                           XmppManager [ping & keepalive]
                           XmppConfirmManager [poll updates]

Todo:

* Respawning features not currently available running single-threaded.
* When running single-site, configuration changes aren't picked up.
* New sites or config changes affecting queue subscriptions are not yet
  handled without a daemon restart.
* SNMP monitoring output to integrate with general tools (nagios, ganglia)
* Convert XMPP confirmation message sends to use stomp queue instead of polling
* Convert xmppdaemon.php to IoManager?
* Convert Twitter status, friends import polling daemons to IoManager
* Clean up some error reporting and failure modes
* May need to adjust queue priorities for best perf in backlog/flood cases

Detailed code history available in my daemon-work branch:
http://www.gitorious.org/~brion/statusnet/brion-fixes/commits/daemon-work
2010-01-12 20:45:09 -08:00
Brion Vibber
4cc9b183d7 Avoid spewing warnings about returning by reference on memcached cache misses by setting a var and returning it instead of trying to return false directly.
This hacky workaround is brought to you by DB_DataObject's PHP 4 roots.
2010-01-12 12:20:45 -08:00
Brion Vibber
f397d35527 Regression fix: don't spew notices to log every time we get a non-cached user object 2010-01-11 13:24:52 -08:00
Evan Prodromou
9d3893255a don't put Users with object IDs in the cache, and don't fetch them 2010-01-10 12:31:43 -08:00
Brion Vibber
78214c4e06 Exclude process-specific link & result cache references from serialized Memcached_Data_Object instances.
Should fix seemingly-random bugs due to destructor free()ing local resources by mistake.

cherry-pick from 0.9.x
2010-01-04 14:38:56 -08:00
Brion Vibber
8f02379f6e Revert "Take Memcached_DataObject destructor back out to check whether it might be causing some under-the-hood problems."
This reverts commit 89cca01259.
2010-01-04 14:37:39 -08:00
Evan Prodromou
d32fb7c7c4 return false from Memcached_DataObject::staticGet() on not found, like DB_DataObject 2010-01-02 16:28:46 -10:00
Evan Prodromou
2bd32dfad7 change harmless check of to check of in Memcached_DataObject 2010-01-02 16:21:19 -10:00
Evan Prodromou
d2bbf65f19 Merge branch 'master' of git@gitorious.org:statusnet/mainline 2010-01-01 11:27:28 -10:00
Evan Prodromou
79c2e3f720 Revert "add cleanup method to cleanup a single row"
This reverts commit b0527801d9.
2010-01-01 11:27:13 -10:00
Evan Prodromou
b0527801d9 add cleanup method to cleanup a single row 2010-01-01 11:02:56 -10:00
Evan Prodromou
727978332a stop using DB_DataObject's staticGet() which caches 2010-01-01 10:57:22 -10:00
Brion Vibber
89cca01259 Take Memcached_DataObject destructor back out to check whether it might be causing some under-the-hood problems. 2009-12-30 16:42:57 -08:00
Brion Vibber
ff50c2b91d Revert debugging code 2009-12-30 16:40:59 -08:00
Brion Vibber
9218cce3cd subbug debug info to check on free ordering 2009-12-30 15:55:15 -08:00
Evan Prodromou
f6bf952980 Merge branch 'testing' 2009-12-22 16:44:19 -08:00
Evan Prodromou
22f02b35ad call DB_DataObject::__destruct() if it exists 2009-12-15 12:38:15 -05:00
Evan Prodromou
945661d942 take out DB_DataObject destructor 2009-12-15 12:33:17 -05:00
Brion Vibber
b9040a7cc4 Add destructor on Memcached_DataObject to free DB_DataObject's global storage for an object when that object itself is destroyed.
Reduces some, but not all, memory leakage for long-running processes.
2009-12-14 16:36:01 -08:00
Brion Vibber
727357695e Debug check to track down live error -- wrong data type sometimes being sent down to Memcached_DataObject::cacheKey() via various fetch functions, need a backtrace to track it down. 2009-12-11 14:19:18 -08:00
Brion Vibber
53c86c43c4 Bringing Sphinx search support up to code: broken out to a plugin, now supports multiple sites on a single server.
Upgrade notes:
* Index names have changed from hardcoded 'Identica_people' and 'Identica_notices' to use the database name and actual table names. Must reindex.

New events:
* GetSearchEngine to override default search engine class selection from plugins

New scripts:
* gen_config.php generates a sphinx.conf from database configuration (with theoretical support for status_network table, but it doesn't seem to be cleanly queriable right now without knowing the db setup info for that. Needs generalized support.)
* Replaced old sphinx-indexer.sh and sphinx-cron.sh with index_update.php

Other fixes:
* sphinx.conf.sample better matches our live config, skipping unused stopword list and using a more realistic indexer memory limit

Further notes:
* Probably doesn't work right with PostgreSQL yet; Sphinx can pull from PG but the extraction queries currently look like they use some MySQL-specific functions.
2009-11-10 13:44:40 -08:00
Evan Prodromou
df86aa7214 define LACONICA and accept LACONICA for backwards compatibility 2009-08-26 10:41:36 -04:00
Evan Prodromou
865b716f09 change LACONICA to STATUSNET 2009-08-25 18:42:34 -04:00
Evan Prodromou
4737563b95 a distributed -> the distributed 2009-08-25 18:14:12 -04:00
Evan Prodromou
c8b8f07af1 change Laconica and Control Yourself to StatusNet in PHP files 2009-08-25 18:12:20 -04:00
Evan Prodromou
a5f78449b1 better check for existing DB connection runs SET NAMES UTF8 less 2009-07-27 13:51:40 -04:00
Evan Prodromou
d4db9d83d8 Revert "Merge branch '0.8.x' into cachenonexistent"
This reverts commit e21d2cfdb5.
2009-07-05 12:44:18 -04:00
Evan Prodromou
9f6bea473e cache failure to find in memcached 2009-07-05 11:31:39 -04:00
Evan Prodromou
876ab05927 Add like for search 2009-06-21 21:50:35 -07:00
Evan Prodromou
aec6456c91 Update copyright dates in files modified in 2009 2009-06-20 16:12:55 -07:00
Evan Prodromou
793a6a1155 change Controlez-Vous to Control Yourself 2009-06-20 16:00:04 -07:00
Zach Copley
e0fb15c185 Make sure we have a DB connection before setting its charset 2009-06-18 19:19:19 +00:00
Evan Prodromou
9e16b7d89b Use mysql_set_charset for connection instead of SET NAMES
PHP doesn't get the info about the charset of the connection if
you use SET NAMES. So, we use the appropriate PHP function instead.
2009-05-30 13:59:57 -04:00
Evan Prodromou
d068680e19 optionally use SET NAMES for utf8 to DB 2009-05-27 14:57:45 -04:00
Evan Prodromou
698228acb9 Revert "Revert "run 'set names' after each connection to deal with UTF8 correctly""
This reverts commit 86770ccde7.
2009-04-26 13:16:59 -04:00
Evan Prodromou
86770ccde7 Revert "run 'set names' after each connection to deal with UTF8 correctly"
This reverts commit 84072aa5cf.

This commit caused grievous harm to old notices on identi.ca.
Reverting until we figure out how to convert the old notices.
2009-04-26 12:28:20 -04:00
Evan Prodromou
a7089de228 run 'set names' after each connection to deal with UTF8 correctly 2009-04-26 12:14:04 -04:00
Evan Prodromou
96bcfa4981 Was accidentally not saving cached items (doh!) 2009-01-22 20:51:05 +00:00
Evan Prodromou
0642b6aa63 Fixed bug in caching of queries 2009-01-22 20:16:19 +00:00
Evan Prodromou
dde1c00ce7 Return $inst, not $cls, if no cache in Memcached_DataObject 2009-01-22 19:54:05 +00:00
Evan Prodromou
8c79646e53 Add a method the memcached_object that lets it cache query results 2009-01-22 19:13:26 +01:00
Evan Prodromou
04ef1ba8ee change function headers to K&R style
Another huge change, for PEAR code standards compliance. Function
headers have to be in K&R style (opening brace on its own line),
instead of having the opening brace on the same line as the function
and parameters. So, a little perl magic found all the function
definitions and move the opening brace to the next line (properly
indented... usually).

darcs-hash:20081223193323-84dde-a28e36ecc66672c783c2842d12fc11043c13ab28.gz
2008-12-23 14:33:23 -05:00
Evan Prodromou
eb2f9c98ac replace NULL with null
Another global search-and-replace update. Here, I've replaced the PHP
keyword 'NULL' with its lowercase version. This is another PEAR code
standards change.

darcs-hash:20081223192129-84dde-4a0182e0ec16a01ad88745ad3e08f7cb501aee0b.gz
2008-12-23 14:21:29 -05:00
Evan Prodromou
edbc0c665c replace all tabs with four spaces
The PEAR coding standards decree: no tabs, but indent by four spaces.
I've done a global search-and-replace on all tabs, replacing them by
four spaces. This is a huge change, but it will go a long way to
getting us towards phpcs-compliance. And that means better code
readability, and that means more participation.

darcs-hash:20081223191907-84dde-21e8efe210e6d5d54e935a22d0cee5c7bbfc007d.gz
2008-12-23 14:19:07 -05:00
Evan Prodromou
be2efe254e always return a variable by reference
darcs-hash:20081210233503-84dde-ae7e4acd0d5e42d6d743b545688ad4ad51bc5014.gz
2008-12-10 18:35:03 -05:00
millette
4206f4d961 sphinx: fallback if no connection
darcs-hash:20081123201616-099f7-54ac0134e38e145b99a81336ae0b51a8ecd560a8.gz
2008-11-23 15:16:16 -05:00
millette
bf72cde96f sphinx search for notices
darcs-hash:20081120215041-099f7-db396a60755d551099122b58634b7550d5606d88.gz
2008-11-20 16:50:41 -05:00
Evan Prodromou
2f71f4d95a add methods to Memcached_DataObject for caching compound keys
darcs-hash:20081002144715-5ed1f-97c8362c4fb4f6a761250b68e2f3311bcc5cba4f.gz
2008-10-02 10:47:15 -04:00
Evan Prodromou
52de32fd82 don't encache on insert; misses timestamps
darcs-hash:20080930130844-5ed1f-217eb0d62fcac4a287ef3e3f213f2ac6bbc70778.gz
2008-09-30 09:08:44 -04:00
Evan Prodromou
a8624b2b72 slightly better check on $orig in update()
darcs-hash:20080927123507-5ed1f-57bc3843352007ae47689a94483d315984276b45.gz
2008-09-27 08:35:07 -04:00
Evan Prodromou
82084ab74c move memcache connections to util.php
darcs-hash:20080926200102-5ed1f-debbc18981424d7724277ac82e5fbfd5e797090e.gz
2008-09-26 16:01:02 -04:00
Evan Prodromou
15c0fb7abd handle multiple memcached servers
darcs-hash:20080926195501-5ed1f-b811fac3320a0b6d8002771caa9463ba9a0889a1.gz
2008-09-26 15:55:01 -04:00
Evan Prodromou
4af31ca98a wasn't returning results of update
darcs-hash:20080926165310-5ed1f-e6d17801c4e9f58cbbbfa774e79583221fdca01f.gz
2008-09-26 12:53:10 -04:00
Evan Prodromou
85c0d71e1f another false-for-error
darcs-hash:20080926164532-5ed1f-1ed3922f205dea0805c7a77618fdf8c9e1a4de02.gz
2008-09-26 12:45:32 -04:00
Evan Prodromou
92e1c41f63 Memcache returns false on cache miss
darcs-hash:20080926164413-5ed1f-d0bbbab5215e43d182e8807fc9fec6cc86dae1ae.gz
2008-09-26 12:44:13 -04:00
Evan Prodromou
98add9803b don't record null key values
darcs-hash:20080926164021-5ed1f-833db670e260c68fc02b0a2a60a2829f247742a1.gz
2008-09-26 12:40:21 -04:00
Evan Prodromou
f01f006615 hack to make keys work
darcs-hash:20080926163555-5ed1f-b2c7f8b9fde0af801e33dc92e4177d1ed4f80159.gz
2008-09-26 12:35:55 -04:00
Evan Prodromou
d3f8cd39a1 handle one-argument calls to staticGet
darcs-hash:20080926163357-5ed1f-49bd6d85d34d0e6ac3514c06d99e5b5b9a78b0fc.gz
2008-09-26 12:33:57 -04:00
Evan Prodromou
88b19d8ab5 better deletes and key names
darcs-hash:20080926163030-5ed1f-c2d375d8a8c2097456ffb3e09e55daacae2cc903.gz
2008-09-26 12:30:30 -04:00
Evan Prodromou
156207d58d try to make some static/non-static stuff work right
darcs-hash:20080926162347-5ed1f-ddb17266f5a60ee85db5fdfb9c8bd12311da3c73.gz
2008-09-26 12:23:47 -04:00
Evan Prodromou
ded5e3dd6c better handling of staticGet
darcs-hash:20080926161946-5ed1f-496b47c72a77fb26610af465af9d9e26c488d315.gz
2008-09-26 12:19:46 -04:00
Evan Prodromou
8da61dc1d3 path correct in require_once for memcached
darcs-hash:20080926161824-5ed1f-b4fb53e5ca65bb099aabbba6ea60a13496f669a2.gz
2008-09-26 12:18:24 -04:00
Evan Prodromou
011ea46022 rename cached object file
darcs-hash:20080926161652-5ed1f-45aee985c6755642d346b864926b2346900c4055.gz
2008-09-26 12:16:52 -04:00