text:
Memo to Members
Senate Releases FY2020 Housing Spending Bill with Modest Increases
The Senate Appropriations Committee voted unanimously on September 19 to approve a spending bill for affordable housing and community development programs for fiscal year (FY) 2020. The bill must now head to the Senate floor for approval. More details on the Senate spending bill can be found below and in NLIHC's updated budget chart. Members of the Campaign for Housing and Community Development Funding (CHCDF) will hold a webinar on Thursday, September 26 at 4:00 p.m. ET to review the affordable housing funding outlook for FY20.
Thanks to the leadership of Subcommittee Chair Susan Collins (R-ME) and Ranking Member Jack Reed (D-RI), the Senate bill provides modest funding increases for affordable housing programs, clearly rejecting President Trump's call for deep cuts to and even the elimination of affordable housing investments. The Senate bill also clearly rebukes the harmful rent increases, rigid work requirements, and de facto time limits proposed by the president in his past budget requests and in subsequent legislation. The bill fails, however, to include legislative language approved in the House version that would halt cruel proposals from the president to evict mixed-status families from assisted housing and to roll back LGBTQ protections.
Overall, the bill provides HUD programs with more than $11.9 billion above the president's FY20 request and $2.3 billion above FY19 enacted levels. This amount is likely enough funding to renew all existing contracts provided through Housing Choice Vouchers ($23.8 billion) and Project-Based Rental Assistance ($12.6 billion) and give level funding or modest increases to other programs, including Public Housing Capital Fund ($2.86 billion), Homeless Assistance Grants ($2.76 billion), Section 202 Housing for the Elderly ($696 million), and Healthy Housing ($290 million). Other programs saw decreases in funding, including Choice Neighborhoods ($100 million), Housing for Persons with AIDS ($330 million), and Community Development Block Grants ($3.33 billion).
The Senate bill provides $1.5 billion less in funding for HUD programs than the House version, which was written before Congress reached a bipartisan agreement in August to lift the low spending caps on defense and domestic programs. While the budget agreement ensures significant funding, it provides approximately $15 billion less for domestic spending overall than the amounts used by the House.
Advocates should continue to urge their senators and representatives to ensure HUD programs receive the highest level of funding possible in any final bill.
Given the tight timeline before the start of the fiscal year on October 1, lawmakers are moving quickly to pass a stopgap funding measure, known as a continuing resolution (CR), to avoid a lapse in funding and a government shutdown. On September 19, the House passed by a vote of 301-123 a CR to fund the government through November 21. The bill will now need to pass the Senate to avoid a government shutdown.
Key Policy Changes:
The Senate bill does not include a number of provisions approved by the House that would stop harmful proposals by the Trump administration. The House bill would prevent HUD from taking steps to "implement, administer, enforce, or in any way make effective" its proposal to evict mixed-status immigrant families from assisted housing or force them to break up. Language was also included in the House bill to prevent HUD from rolling back LBGT protections, including the agency's Equal Access rule, and to ensure transgender individuals have access to single-sex emergency shelters and other facilities that match their gender identity.
Tenant-Based Rental Assistance:
The Senate bill provides $23.833 billion for tenant-based rental assistance (TBRA), including $21.5 billion to renew previous contracts. This is a significant increase over President Trump's $20.116 billion request for TBRA for FY20 and will adequately renew all vouchers.
The bill allocates $40 million for Veterans Affairs Supportive Housing (VASH), the same amount as FY19, and $1 million to serve Native American veterans, a decrease of $3 million.
The bill provides $218 million for Section 811 mainstream vouchers, a slight decrease from amounts provided in FY19. The bill also includes level funding for Family Unification vouchers at $20 million.
Project-Based Rental Housing:
The bill provides $12.6 billion to renew project-based rental assistance contracts for calendar year 2020, an increase of $539 million above the president's request and $813 million more than the FY19 funding level. Advocates estimate this amount will be sufficient to renew all contracts.
Public Housing:
The bill provides the public housing capital account with $2.855 billion, an $80 million increase from the FY19 funding level. This modest increase will enable housing agencies to make critical repairs, such as fixing leaky roofs and replacing outdated heating systems, that will improve living conditions for tens of thousands of residents and help preserve this essential part of the nation's affordable housing infrastructure for the future. President Trump had proposed zeroing out funding for this account in his FY20 budget.
Funding for the public housing operating fund decreased slightly to $4.650 billion. Funding for the Family Self-Sufficiency program stayed level at $80 million.
The bill also sets out new funding opportunities impacting public housing, including $40 million in competitive grants to public housing agencies (PHA) to reduce lead-based paint hazards ($25 million) and other health hazards, including mold and carbon monoxide poisoning ($15 million).
Homelessness:
The bill increases funding for homeless assistance programs to $2.8 billion from $2.64 billion in FY19. The president would have funded the programs at $2.6 billion. Of these funds, $80 million will target addressing youth homelessness in urban and rural areas.
Other Housing Programs:
The bill provides $696 million to the Section 202 Housing for the Elderly program, a slight increase of $18 million from the FY19 funding bill. The bill maintains funding for the Section 811 Housing for People with Disabilities program at $184 million, $75 million less than the House bill. These amounts provide sufficient funding to renew all contracts but may not provide new construction for both programs.
The bill would decrease funding for the Community Development Block Grant (CDBG) program at $3.3 billion and provide level-funding for the HOME Investments Partnerships program (HOME) at $1.25 billion. Both programs would have been eliminated under the president's budget request.
Funding for the Housing Opportunities for People with AIDS (HOPWA) program was decreased by $63 million to $330 million, the same amount included in the president's budget.
Funding for the Choice Neighborhoods Initiative is reduced to $100 million, although it would have received no funding in the president's budget.
The bill provides $646 million for the Native American Housing Block Grant program, a decrease from FY19 but more than proposed in the president's budget. The bill also includes an additional $100 million for competitive grants.
The Native Hawaiian Housing Block Grant program received $2 million in the FY20 House bill, the same amount as FY19.
Healthy Homes:
The bill provides $290 million to the Office of Lead Hazard Control and Healthy Homes' grants, a modest increase from FY19 and the same level included in the president's budget.
Fair Housing:
The bill includes $65 million for HUD's office of Fair Housing and Equal Opportunity, the same amount as in FY19.
To learn more about the funding outlook for FY20, register for a CHCDF webinar on September 26 at 4:00 p.m. ET at: https://tinyurl.com/y3e73253
Take Action to Advance the HoUSed Campaign's Affordable Housing Agenda in Build Back Better and FY22 Spending Bill
Advocates have two major opportunities in 2022 to advance the HoUSed campaign's bold agenda of advancing anti-racist policies and achieving the large-scale, sustained investments and reforms…
Congress Enacts Continuing Resolution to Fund Government through February 18
Congress enacted a continuing resolution (CR) on December 2 to extend current levels of funding for federal agencies and programs through February 18, 2022. The stop-gap funding bill (HR 6119), which…
Appropriations Negotiations Stall as December 3 Deadline Draws Near
Congress passed on September 30 a continuing resolution (CR) extending current funding levels for the federal government until December 3, 2021 (see Memo, 10/4), but since the CR was enacted, little…


text:
import argparse
import logging
import os

from .exporter import add_stdout_logging, establish_and_return_ldap_connection, \
    establish_and_return_session, fake_connection, fetch_current_ldap_users, \
    fetch_current_ldap_groups, fetch_current_ldap_properties, fetch_users_to_sync, \
    fetch_groups_to_sync, fetch_properties_to_sync, get_config_or_exit, logger, sync_all

logger = logging.getLogger('ldap_sync')

def sync_production():
    logger.info("Starting the production sync. See --help for other options.")
    config = get_config_or_exit(required_property='ldap', use_ssl='False',
                                ca_certs_file=None, ca_certs_data=None)

    db_session = establish_and_return_session(config.db_uri)
    connection = establish_and_return_ldap_connection(
        host=config.host,
        port=config.port,
        use_ssl=config.use_ssl,
        ca_certs_file=config.ca_certs_file,
        ca_certs_data=config.ca_certs_data,
        bind_dn=config.bind_dn,
        bind_pw=config.bind_pw,
    )

    fetch_and_sync(db_session, connection, config.base_dn, config.required_property)

def sync_fake():
    logger.info("Starting sync using a mocked LDAP backend. See --help for other options.")
    try:
        db_uri = os.environ['PYCROFT_DB_URI']
    except KeyError:
        logger.critical('PYCROFT_DB_URI not set')
        exit()

    db_session = establish_and_return_session(db_uri)
    connection = fake_connection()
    BASE_DN = 'ou=pycroft,dc=agdsn,dc=de'

    fetch_and_sync(db_session, connection, BASE_DN)

def fetch_and_sync(db_session, connection, base_dn, required_property=None):
    db_users = fetch_users_to_sync(
        session=db_session,
        required_property=required_property,
    )
    logger.info("Fetched %s database users", len(db_users))

    db_groups = fetch_groups_to_sync(db_session)
    logger.info("Fetched %s database groups", len(db_groups))

    db_properties = fetch_properties_to_sync(db_session)
    logger.info("Fetched %s database properties", len(db_properties))

    user_base_dn='ou=users,{}'.format(base_dn)
    ldap_users = fetch_current_ldap_users(connection, base_dn=user_base_dn)
    logger.info("Fetched %s ldap users", len(ldap_users))

    group_base_dn = 'ou=groups,{}'.format(base_dn)
    ldap_groups = fetch_current_ldap_groups(connection, base_dn=group_base_dn)
    logger.info("Fetched %s ldap groups", len(ldap_groups))

    property_base_dn = 'ou=properties,{}'.format(base_dn)
    ldap_properties = fetch_current_ldap_properties(connection, base_dn=property_base_dn)
    logger.info("Fetched %s ldap properties", len(ldap_properties))

    sync_all(connection, ldap_users, db_users, user_base_dn, ldap_groups,
             db_groups, group_base_dn, ldap_properties, db_properties,
             property_base_dn)

NAME_LEVEL_MAPPING = {
    'debug': logging.DEBUG,
    'info': logging.INFO,
    'warning': logging.WARNING,
    'error': logging.ERROR,
    'critical': logging.CRITICAL,
}

parser = argparse.ArgumentParser(description="Pycroft ldap syncer")
parser.add_argument('--fake', dest='fake', action='store_true', default=False,
                    help="Use a mocked LDAP backend")
parser.add_argument("-l", "--log", dest='loglevel', type=str,
                    choices=list(NAME_LEVEL_MAPPING.keys()), default='info',
                    help="Set the loglevel")
parser.add_argument("-d", "--debug", dest='loglevel', action='store_const',
                    const='debug', help="Short for --log=debug")

def main():
    args = parser.parse_args()

    add_stdout_logging(logger, level=NAME_LEVEL_MAPPING[args.loglevel])

    try:
        if args.fake:
            sync_fake()
        else:
            sync_production()
    except KeyboardInterrupt:
        logger.fatal("SIGINT received, stopping.")
        logger.info("Re-run the syncer to retain a consistent state.")
        return 1
    return 0

if __name__ == '__main__':
    exit(main())

redpajama_set_name: RedPajamaGithub


text:
from skimage import feature, io, filters, transform

img_file = "../data/similar_objects/4.JPG"

# load the image and convert it to a floating point data type
image = io.imread(img_file)
image = transform.rescale(image, 0.4)

from matplotlib import pyplot as plt
from skimage import data
from skimage.feature import blob_dog, blob_log, blob_doh
from math import sqrt
from skimage.color import rgb2gray

image_gray = rgb2gray(image)

plt.imshow(image_gray)
plt.show()

blobs_log = blob_log(image_gray, max_sigma=30, num_sigma=10, threshold=.1)
# Compute radii in the 3rd column.
blobs_log[:, 2] = blobs_log[:, 2] * sqrt(2)

#blobs_doh = blob_doh(image_gray, max_sigma=30, threshold=.01)

blobs_list = [blobs_log]
colors = ['yellow']
titles = ['Laplacian of Gaussian']
sequence = zip(blobs_list, colors, titles)

fig,axes = plt.subplots(1, 2, sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
axes = axes.ravel()
for blobs, color, title in sequence:
    ax = axes[0]
    axes = axes[1:]
    ax.set_title(title)
    ax.imshow(image, interpolation='nearest')
    for blob in blobs:
        y, x, r = blob
        c = plt.Circle((x, y), 2, color=color, linewidth=2, fill=False)
        ax.add_patch(c)

plt.show()


A new report published in December 2012 talks about the benefits of using a certain type of Energy Psychology, which is in effect a system of tapping round certain points in the body and how it is helping those with mental health issues.
It is of course referring to Meridian Tapping, i.e. EFT and it's use as a clinical and self-help modality that combines verbal and physical procedures to make therapeutic change.
It's becoming more apparent that growing time restraints, growing numbers needing help with mental health issues and mounting stress that room can be made for newer techniques that are showing themselves to be super efficient at clearing past trauma (and in some cases not so much trauma in the traditional sense) but also super-sensitivity to situations and people.
I was invited to train a closed group of counselors, teachers and therapists as part of their CPD last year and they really like how quickly they were able to get to an event, uncomfortable feeling, that created the disharmony they worked on.
The pitfall for them was that as they all specialised in working with children, and their particular organisation (who I won't name) haven't yet recognised the Energy Psychology's for general use within their practitioner practices.
Which gives this type of research paramount importance, so we can get these efficient, effective and non-invasive techniques integrated into the services psychotherapists already offer – in order to help clients – as quickly as possible.
We want to see this up and running as soon as we possible in order to help more people feel better, faster, and as the pace of life gets busier, it's becoming essential for the mainstream services to open up to these new understandings.
And the more those traditional fields become receptive the more research will be commissioned, which those of us using EFT, TFT and other Meridian therapies would welcome it.
Experiencing the way these tools shift the energy, is evidence in itself, but it needs qualifying with reports like this one that help the mainstream take it seriously and integrate it into their own practices, as healthcare professional, psychotherapists, counsellors and teachers.
I for one welcome it with open-arms and look forward to masses more research, because we know there is good-clean science behind what is going on in the meridian energy system and it wouldn't be a far cry for those who already deal in scientific terminology to reach across and evaluate for themselves.
As mentioned experiencing it is key and that leaves no uncertainly when you can be someone who has been troubled by something going on in your life, and within a relatively short span of time, have a completely new perspective, and emotional response to what may have been plaguing you for decades in some cases.
That has got to be work further investigation hasn't it? And of course it is, but let's have more.
What difference does EFT Tapping make?
This isn't just good for food cravings and phobias, it helps with deep-rooted anxiety, depression, pain, incredibly painful past trauma's, hopelessness, helplessness, having no real sense of identification or purpose.
This brings people back into alignment and some people have NEVER felt that, they almost don't feel they're worth it nor dream they could 'fit-in'. Of course life is not about fitting-in with others but more about feeling good enough about yourself so you are fully integrated into being your self, which is what makes it much easier to fit in.
And the confidence that exudes from feeling integrated with yourself is what leads to being so with others, and is what makes a significant difference to how you act with others, and once you find your authentic self it means you're the same whether with others or when no-one else is around.


Iran has raised the death toll from Saturday's twin earthquakes to 306, a day after rescuers called off the search for survivors.
Health Minister Marzieh Vahid Dastjerdi told a session of parliament on Monday that the number of dead had jumped by about 50 after victims expired in the hospital.
More than 3000 people were injured in the earthquakes, he said.
On Sunday the official death toll was given as 227, with about 1380 people injured.
Scores of aftershocks have shaken Iran's mountainous northeast since the 6.4 and 6.3 magnitude quakes hit the region, where some 300,000 people live near the borders with Azerbaijan and Armenia.
Iran is located on seismic fault lines and is prone to earthquakes. In 2003, about 26,000 people were killed by a 6.6 magnitude quake that flattened the historic southeastern city of Bam.


The monograph is a collection of Guest Lectures given by the author, at various places throughout the years 1949 to 1953. As such, it is a natural sequel to Dr. Means' text, The Thyroid and Its Diseases, and brings many items of that book up to date in the ever changing field of thyroid physiology, pathology and therapy.
Any publication by Dr. Means is worth reading and monographs such as this are destined to be collectors' items. A worthwhile addition to the library of any internist.
Published: Ann Intern Med. 1955;43(6):1348.
Endocrine Diseases and the Liver: An Update.


text:
Yahoo Lifestyle SEA
Four tips to write better work emails on mobile phones
(Photo: Getty Images)
Nowadays, people mostly use emails for work, and working from home has become a particularly important work model during the epidemic. However, if you happen to be out having a meal and your supervisor needs something done immediately, you'll need to use your mobile phone to check your emails.
When sending emails with signatures such as "Sent from my mobile phone" you may be mistaken for being out of the home office for no good reason. In addition, if you want to respond urgently, the contents of the letters might be difficult to read if you include a lot of images. I sincerely suggest that you include them as attachments instead of oversizing all emails. Learn these four email messaging skills to leave a good impression on your supervisor. Study these tips and send them to your colleagues!
Method 1: Avoid using the "Sent from my mobile phone" automatic signature
The signature at the bottom of an email is a thoughtful gesture for supervisors or recipients as it helps them reach you immediately after reading the email. However, if an email is sent from your mobile phone, you should avoid using the "sent from my XX." For supervisors, it may feel slightly too casual and they may even believe that you're out there having fun instead of sitting in front of the computer after they allowed you to work from home. It may damage their impression of you. Go change the email signature in the mobile app now!
For example, in the Yahoo Mail app (which I usually use), you can open the app and click on the portrait on the top left corner to enter "Settings." The "Signature" setting is at the bottom of the page. Click to change settings. I recommend using "company name, title, and your name" as the first line of your signature so that the recipient can immediately see the company and department of the sender. It leaves a more lasting impression. You should then add your contact number, email address, and business number.
The convenient thing about the Yahoo Mail app is the fact that it can integrate with other mail accounts, and you can set different signatures for each account. You can use a casual signature for your personal account but more formal titles and information for the company account. This will ensure that the emails you send to your boss do not include an unprofessional ending. (The Yahoo Mail app also allows you to set different background colours for the email accounts you import so that you don't confuse one for the other. This will help you separate personal emails from work emails.)
Method 2: Get rid of the same old email format and add stationery to attract more attention
Do you want to attract the attention of the recipient from among tens of thousands of similar emails with white backgrounds and black fonts cluttering their inbox? You just need a little stationery to make your email special! Yahoo Mail allows senders to add stationery to emails. The sender can choose a suitable background for different types of letters and there are nearly one hundred stationery themes to choose from, including popular comics, dogs and cats, and elegant greeting cards. There are also cards for special occasions such as sweet Valentine's Day, festive Christmas and Chinese New Year, and indispensable birthday cards. The stationery will make your emails and wishes more unique and personal.
Method 3: Send images as attachments to avoid oversized emails
The most common issue for sending emails from mobile phones is "image attachments." Many users include images in the main text which makes the entire email oversized. Mixing images and text affects readability and I recommend using attachments to separate text from image files. In Yahoo Mail, as an example, after you upload images to the text, the "···" symbol will appear on the top right corner of the image. Click on the symbol and the "Send as attachment" option will appear. This allows you to send the image as an attachment so that the email will not become oversized.
Method 4: Save yourself from your clumsy hands by writing emails backwards to avoid sending emails by mistake
Have you ever sent an email before you finished writing it? Sending an email by mistake occurs even more often on mobile phones with smaller screens. I recommend writing the entire email backwards by first including the attachments, next writing the contents, then writing the subject and entering or selecting the recipient. Reminder: read your email and verify that everything makes sense before sending. You should also check for typos.
In addition, the mobile app offers fewer text editing functions than the desktop version. For iPhones, the only functions are bold fonts, italic type, and underline, which are quite sufficient if you know how to use them. Press and hold on the finished text to select the segment to be highlighted and select your desired font format to emphasise the key points of the content. It helps the recipient view the key points of the entire email with ease. It's one of the most important mobile phone app skills for office workers.
◤ The next-generation inbox is here! 1000GB of free storage◢
Click here to download the Yahoo Mail 6 app.
11 Actors Over 90 Still Making a Mark in Hollywood, From Mel Brooks to Betty White (Photos)
Mel Brooks (born 1926) The EGOT winner and comedy legend has kept working into his 90s, with roles in films like 2018's "Hotel Transylvania 3" and 2019's "Toy Story 4." He's also been working on a stage musical adaptation of his 1974 comedy Western "Blazing Saddles." Ed Asner (born 1929) The Emmy-winning star of "The Mary Tyler Moore Show" and "Lou Grant" has kept working, with 2020 appearances in TV shows like "Modern Family," "Blue Bloods" and "Briarpatch." Cicely Tyson (born 1924) An Oscar nominee for 1972's "Sounder" (and an honorary Oscar winner in 2019), Tyson has stayed on screen in films like "The Help" and 2017's "Fall From Grace" as well as TV shows like "Cherish the Day" and "How to Get Away With Murder." Dick Van Dyke (born 1925) The Emmy-winning star of the '60s sitcom "The Dick Van Dyke Show" also broke out on the big screen in films like 1964's "Mary Poppins" and 1968's "Chitty Chitty Bang Bang." But he's had a resurgence in this century with roles in the "Night at the Museum" series, Showtime's "Kidding" and 2018's "Mary Poppins Returns." Betty White (born 1922) The Emmy-winning star of "The Mary Tyler Moore Show" and "Golden Girls" had another sitcom hit in her 90s with "Hot in Cleveland." She also voiced a character in 2019's "Toy Story 4." Bob Newhart (born 1929) The standup comic became a sitcom legend with three shows that bore his name. And he's made appearances in shows like "The Big Bang Theory" (finally winning his first Emmy in 2013) as well as "The Librarians" and "Young Sheldon." Angela Lansbury (born 1925) A three-time Oscar nominee for films like "Gaslight" and "The Manchurian Candidate," Lansbury earned fame on TV as well, particularly the long-running mystery "Murder She Wrote." A six-time Tony winner for her work on Broadway, she has continued working in projects like 2018's "Mary Poppins Returns." Cloris Leachman (born 1926) Leachman won an Oscar for her work in 1971's "The Last Picture Show," and followed that with work in comedy like "Young Frankenstein" and her long-running sitcom "Phyllis." More recently, she's appeared in shows like "Raising Hope," "American Gods" and the reboot of "Mad About You." Estelle Parsons (born 1927) Parsons won an Oscar for 1967's "Bonnie and Clyde" and she's kept working on both stage and screen well into her 90s, appearing in shows like "The Good Wife," "Grace and Frankie" and "The Conners." Read original story 11 Actors Over 90 Still Making a Mark in Hollywood, From Mel Brooks to Betty White (Photos) At TheWrap

redpajama_set_name: RedPajamaCommonCrawl


text:
Also by Liam Heagney
Premiership club signs Pumas forward who helped to beat England
Nigel Owens: Why Barrett yellow didn't lead to England penalty try
Ex-Wasps out-half Haydon-Wood makes switch to France his next move
More by Liam Heagney
Gallagher Premiership News
Clock-in-the-red Hougaard try denies Bristol at Saracens
Leaking players to England effecting Leicester's 'consistency'
Exeter back in playoff spot after a hard-fought win over Gloucester
'Francois is Hollywood, isn't he': Saracens boss Mark McCall heaps praise on former Springbok
More Gallagher Premiership
The All Blacks resting policy may actually work
Bruce 6 hours ago
Hamish I think in Rugby the international game is king and will always be the case. However I think in NZ we don't have the balance right. As you say the total focus has been on the All Blacks and not enough attention has been put on Super Rugby and how to enhance that. They have seen it as a high performance tool to service the AB's and have not valued it as a competition in it's own right. However I think the current board have a different view and moving in the right direction. Having created an independent board to look solely after the competition is definitely a step in the right direction. I see the growing of the Super comp as the number one priority for NZ and Aus.
Gallagher PremiershipUlster
'The pain was almost like a ripping across my abdomen. I'd no idea what was going on'
By Liam Heagney
Ross Adair scoring for Ballynahinch RFC
https://www.rugbypass.com/news/the-pain-was-almost-like-a-ripping-across-my-abdomen-id-no-idea-what-was-going-on/
Pull up a chair and be inspired. Ross Adair's attempt to fight his way back into the professional ranks is a winter's tale to warm the heart at a time of year when so much talk is of bulging Six Nations win bonuses and other money-spinning incentives at the elite end of rugby.
Adair's name doesn't roll off many tongues despite representing Ireland in both rugby and cricket at underage level. A single PRO12 appearance a month before his 21st birthday was his lot at Ulster in 2015 before he took a well trodden Irish route abroad in search of fame and fortune – the stepping stone that is the English Championship.
Life in the second tier shadows can often be the springboard to a glamorous breakthrough higher up the food chain. Think Gareth Steenson, another ex-Ulster who found refuge at the Chiefs long before they were promoted and winning Premiership trophies.
Or Robin Copeland, whose far from flash existence at Plymouth and Rotherham opened the Cardiff door that then unlocked Munster and an Ireland cap within a few months of his 2014 return home.
Championship didn't work out as successfully for Adair. There were 40-plus appearances along with a British & Irish Cup runners-up medal, but the desired upward mobility didn't transpire.
Instead, degenerative hips brought a premature end to his two-and-a-half year stint at Jersey, the Channel Island club where Harry Williams and Gary Graham proved themselves before securing the Premiership transfers that led to their respective England and Scotland recognition.
Adair is still bravely fighting his corner, however. Rather than call it quits and hobble away when neither Jersey nor his insurer would provide medical bill assistance, Adair took out a personal loan of £15,000 at the start of 2018 to fund the pair of hip operations that now have him back on his feet.
He is playing pain-free All-Ireland League rugby at outside centre with Brian McLaughlin's Ballynahinch, rubbing shoulders with Ulster squad members Peter Nelson, Johnny McPhillips, Kyle McCall and Tom O'Toole, and dreaming of a return to the professional ranks somewhere in Ireland or abroad next season.
It would be quite the heroic comeback if his ambition is fulfilled. Degenerative hips is an ordeal only supposed to affect people twice the 24-year-old's age, but Adair has been to hell and back – mentally, physically and financially – to keep his career prospects alive.
HT in the 'A' interpro – The Ravens are leading Connacht 19-7 thank to tries from Jack Owens (2) and Ross Adair (pic) pic.twitter.com/N5k2hl8iG1
— Ulster Rugby (@UlsterRugby) October 2, 2014
He had positively rolled with the initial punches. He scored a try at Rodney Parade during his short-lived Ulster cameo off the bench, but he knew the province had nothing for him so he willingly embraced island life in the Championship.
'I wasn't going to be offered an academy or development contract, so going away was the right thing. Going to the Championship was the way to chase it. I wanted to be a professional, wanted to do anything to get there.'
His face fitted for quite a while but then came his 2017 torment, something he is still in the throes of only rebounding from a month into 2019. 'Towards the end of my second season at Jersey I started getting pain in my pelvic area,' he explained, taking up a story that should make every fan grimace about the harsh realities of a rugby existence far away from the bright Six Nations lights.
'I wanted another club to come and sign me because of the confidence I had in myself. I thought I was good enough to go on, but nothing came in so I went back to Jersey and got stuck into pre-season.
He's back! Ross Adair may have left Jersey Reds at the end of last season, but he's returned to the island: https://t.co/CyGuWWkDSv pic.twitter.com/pQIXF15d60
— BBC Jersey Sport (@BBCJerseySport) July 7, 2017
'I was aware for years I'd tight hips but just thought it was from playing rugby all the time. You don't actually know what is going on inside, but I got to a stage where I couldn't even run anymore. I couldn't stride forward, so that is why I knew something was definitely wrong.
'It was a bit rough. I went well in pre-season, but from September to December there was just months of not being able to do anything and worrying about what was going to happen. It was bleak. Dark times.
'The pain was almost like a ripping across my abdomen. I'd no idea what was going on. We thought it was a hernia at the start but it wasn't that. There was hours on an MRI machine. I got my spine checked, got everything checked and everything was fine apart from my hips.
'We were all set for my operation on December 1 and then it all started going wrong with my insurance. My insurer realised it was degenerative so they backed out of paying and then Jersey wouldn't help pay either and they released me just before Christmas.
'When I had re-signed they said they would help get me fixed, get me better and get me fresh, so I was pretty disappointed Jersey turned around and said: "We unfortunately can't help you". But that's just Championship rugby.
'The RPA looked into it to see if they could do anything but there was nothing so I decided to pay for all the surgery and physio myself. I was in pain every day, sat on a sofa and couldn't do much everyday stuff, so it was more a life decision.
'It was a lot of money and the eight weeks between the two operations were extremely miserable as well as the weeks on crutches afterwards. The surgeon said it was an absolute war zone, but it needed to be done.
'Whether or not I was going to play rugby after the operations was dependant on how I reacted to the rehab. There was also abdomen and adductor rehab. I'm not going to lie, it was tough and there was a lot of emotion. But I'm through it now.
'Not being in pain every day is a relief and I now want to prove people wrong. I wouldn't say it [the comeback] has been a complete success. I haven't got a professional contract yet. We'll see what the next few months bring.'
Adair's younger brother Mark helped immensely during rehab. He'd been on Warwickshire's books in English county cricket, but his need to have a screw inserted in his spine in October 2017 left the brothers nursing each other along to better health at home in Holywood just outside Belfast.
Holywood all out for 225… losing only by 14 runs. Congratulations to @WoodvaleCC1887! MOTM goes to Ross Adair (10 overs, 0 wkts, 18 runs). pic.twitter.com/lxxQbjJwCw
— Laure James (@LaureJames) May 20, 2017
Ross scored a summer ton for fun in a local cricket match and there is now new year optimism for the siblings. Mark's currently touring with Cricket Ireland A in Sri Lanka while Ross is scoring tries for promotion-chasing Ballynahinch after taking first steps with their seconds team in November.
'It was a big relief. There was no point worrying about getting injured. I just went out, pretended nothing was wrong and I have moved on in the last nine weeks. I'm alright, touchwood, and don't see why I can't do it professionally. I feel I definitely can do a job.
Adair scoring for Ballynahinch RFC
'I've a lot of ambition and my agent is sniffing around. Hopefully some club takes a chance because I believe I have what it takes and have a desire to get through. Getting back to professional level is what is keeping me going.
'It would be interesting – not just for rugby but for all sports – to see if a guy can go back playing professionally after getting both hips done. It's a bit of motivation and if I walk on to a pitch professionally next season it would take back all the hard times I have had over the last 15 months.
'The lesson I have learned is to get everything checked before signing a contract. The insurance I had wasn't good enough, so I'd be checking the small print next time.'
A spokesperson for Jersey Reds told RugbyPass in a statement: ""We take pride in the way we have always looked after the welfare of our players and believe the club has earned an excellent reputation in this area. We have never released a player as a result of a rugby-related injury.
"We were pleased to learn that Ross Adair had been able to return to playing and wish him all the best with his ongoing recovery and for the future."
TRENDING How 'a dumb play or two' could have hurt Jonny Hill with England How 'a dumb play or two' could have hurt Jonny Hill with England


Forte Build and Design is a company that offers exceptional workmanship and service at a price that fits your budget. They are the preferred choice for all residential and commercial remodeling and construction projects throughout Los Angeles County.
THE CHALLENGE: Forte Build and Design wanted a website that would showcase their expertise in residential and commercial contracting. They wanted the whole package and were looking for a new marketing technique to one up the competition. In order to make their company number one, Forte Build and Design needed the latest in web marketing to outshine their competitors. Starting off as a small company they were wanting to grow and expand their business as well as define them as a professional construction company.
THE SOLUTION: To get Forte Build and Design looking as eminent as their work, we created a new website that is easy to navigate, visually appealing, and responsive on all devices. Our dedicated marketing team used strong call-to-actions to appropriately navigate prospective customers and turn them into clients. At the end of our work, we had provided Forte Build and Design with a sleek look and unique brand.


There are no comments for Alone At Last. Click here to post the first comment.
Captured this pretty female ruby throated hummingbird at my feeder last summer. Caught her sipping quietly at the feeder.
Thanks for viewing my Photography, it means just as much to me as breathing. My life as a photographer started 8 years ago, professionally. My specialty is Nature, the way sun hits an object, or a sparkle on a glass. I want the excitement captured, something that makes a moment REAL. Within these years I finally found my calling and my own unique take on Nature and Macro photography. I live in Maine with my husband of 25 years, with our two daughters. Maine has so much to offer a photographer, the winter snow to the color changing autumn months. I want to capture it all! So, feel free to browse all I have to offer! Any questions, message me. Thanks again!


text:
Michigan Fisherman Catches Whitefish, Gets A Bonus Northern Pike
It was two for the price of one for Sault Ste. Marie's Steve Miller this week.
The Soo Evening News tells the tale of Miller's fishing foray at the St. Mary's River.
Miller casted off from his friend Keven Savoie's boat on Monday. He thought a small whitefish hit his line. It did, but at the same moment, he got a bonus he wasn't counting on.
The moment he started reeling the smaller fish in, a giant Northern Pike went to eat the Whitefish, and the fight was on for Miller.
For a moment, Miller thought he had a salmon on the line, and was just hoping his four-pound test line would hold.
It did, and then Miller saw the reality of his catch, a 33-pound Northern Pike.
The Evening News picks up the story from there:
...there was another thing that made this unusual.
The pike wasn't even hooked.
The fly was buried in the mouth of the whitefish — which had served as the prize in this tug of war. Had the pike just once released its grip on the smaller fish, it would have left Miller with a sad tale of the one that got away.
The pike's stubbornness and a little bit of luck produced the river's equivalent of killing two birds with one stone. It also provided the 35-year-old Miller with a meal and a story he can share of the time he landed two fish on a single fly.
Categories: Animals, Michigan News


At The Fellowship, you do not just go to church...you ARE the church. We gather to scatter – living the life the Lord asks of us every day, in a multitude of ways that strengthen our family, marriage, work life, community and the world.
We are a multi-generational, multi-cultural congregation that strongly believes that transformation does not come through learning; it comes from experiencing life-changing moments ... and we want you to experience those moments to the fullest.
We serve every day to fill the needs of the community for the glory of God. Join us to become a whole people who take the whole gospel to the whole world.


Matt in American Horror Story. promo pic for Matty's guest role as Andy in Season 4. HD Wallpaper and background images in the Matt Bomer club tagged: photo matt bomer american horror story promo pic season 4.
This Matt Bomer photo might contain hip boot, thigh boot, combishort, combinaison de jeu, and combi.


Iconbrickell condo no 1 Unit 4514.
On brickell avenue going north just past se 5 street. Icon brickell condo will be on the right..
Live on icon brickell in a beautiful luxury unit and condominium building right on biscayne bay in the financial district.
Live on icon brickell in a beautiful luxury unit and condominium building right on biscayne bay in the financial district. This stunning unit features with marble countertop kitchen, ss appliances, washer and dryer. Incredible balcony with spectacular view. Architecture is by world renowned arquitectonica. Marvelous lobby design by phillipe starck. Concierge services, valet, conference room, exercise room, tv lounge, movie theater, billiard room, pool and more... Fully furnished..
Community pool,elevator,exercise room,management on site,pool table.


One was a leader 20 years ago. The other a decade. Both have fallen far in recent years.
****** ****** ******** ***** *** ***** ** ***************************** ** *****.
** **** ****, ** ***** **** ***** **********, ********* *** future *** *** ******** *********.
***** *** ****** ** ****************************** **** *** **% ** *** ******** *******, **** * sad ****** ********* ** ~$** ******* ***(*.*., ****'* **.*% **** **** ********'* $*.* *******).
*** ********* ****** ******** **** ******* ** $** ******* ***. Given *****'***** ********** $**.* *******, **** **** **********'* ** $**.* *******.
***** ***** ** ***** ***** ** ******** ** ****** * / * ($** ******* ****** *** / $** ******* *******). A ******** ******* ** **** ******** *** * ***** ** 1 ** * ***** ****** ********* *** ***** *:* ** even *:*. **** ***** *** ****** *** ****** ***** ** their ******* ** **** *** ******** *******.
*************, **** ******* *** ******* ** ***** ****** ** **** than $** *******, **** *********** *** *******'* ********** ******* *** valuation.
**** ****** *** ******** ********* *** ****** *****.
***** *** ********* **** *********** ****** *** *****. *** ********, in ****, *** ******* *** ** ********* **** ** $* million.
************* *** *** ********** ** **** **** ******* *** **** over *** **** *** *****, ******** **** *** ******** ******** to ****** *.***, ******* ******* ********** *******, ** ***** **** ***** *********.
**** ********* ******* ** **** *******. *** ********,******** ** *** ** **** **** $** ******* ****** *******, had ***** ** ****** $** ********* ****.
*** ****** *** **** **** *** ***** *** *****. ***************** ***** ******* ** ** **** ** *** **** ** **** **** Vicon **** *** **** *******.
*** ******** ** ***************** ****** ****** *********** *** ********** **** *** ******* *****. *** *******, ******'* ************ ******** *****,**************** * ******** ***** ******* **% ************* *** ** *** ****** ** *%. ***** ** ***** hear ****** *** **********, **** ******** ***** ****** ************.
** *** ***** ****, *** ** ****** ******** *** ****** a *** **** *********** ***** **********'* ***** * ** * years ***, *** **** **** **** * *** ** ***** key ****** ** ****.
*************, ** ** * ************* ****** ** * **** ****** beginning. ********, **** ** * **** ****** ** *******.
***** ** ** **** ** ******* *** ******** ******* **** regain ***** ****** ***** ** ******** *****, ***** ** ******, primarily ******* *** *******'* ********* ** ******** ***.
** *** ******* ***** ****** ********* ******, ******* ** *** point ***** ** ********* * ****** ****** **** ******** ***** to ***** ******* ******** $** *******, ***** ****** ********* ***** double ** ******.
Oh, hey, I remember Vicon.
The valuation for Vicon alone is $15.9 million according to its stock price today. I don't understand why the valuation for the two companies combined are only about 15 million.
As of the time of this comment, there are 4.5 million shares outstanding, trading at $3.52 for a market capitalization of $15.9 million USD.
As of the beginning of this year, Vicon has ~$8 million USD cash in the bank. They are going to issue a one time dividend of 55 cents to existing shareholders (4.5 million shares). That will be a cash outflow of $2.5 million.
IQinVision shareholders will get 4.5 million new Vicon shares, increasing total Vicon shares to 9 million. There is no other cash changing hands.
The news has been public for the past day (and known by insiders for some time). However, the stock price was unchanged today and has been in the same range for the past month.
When those shares are issued (doubling), it will dilute current Vicon shareholders. The valuation will depend what happens when those extra shares are issued.
The valuation will depend what happens when those extra shares are issued.
To the degree that this is viewed as a 'done deal', the current valuation already has already 'priced in' the announced future issuance; Likewise the actual issuance of shares will have no effect at that time, agree?
That's my interpretation but I could be wrong.
Two sad stories about once innovative companies.
What happened at Vicon? How did the end up where they are today?
Is it because they were not prepared for IP. Because their solution doesn't work or buggy software or ???
In fairness, many, if not most of the leaders of the past era have struggled in this one. Pelco, AD, Interlogix, Dedicated Micros, etc.
Vicon's fall has been more public primarily because it is an independent publicly traded company so it's easy to see the specific decline.
It's not all doom and gloom. Maybe I'll be able to finally dump my nearly worthless IQinVision stock I've been forced to hold on to for years.
In my humble opinion, if there are funds available a CEO with a strong vision could still create a recovery once the companies have been stabilized. Never say never - it's a dynamic marketplace.
Hate to sound like a cynic, but it seems these days when there are funds available CEO's usually worry first about bonuses and golden parachutes. A good indicator of their intention would be to look and see if they are buying or selling shares themlseves.
Any idea yet how this is fairing a year later?
Work in progress. They hired a new CEO 6 months ago and he is implementing a lot of changes. Still needs more time to get a clear sense of how well it will work.


text:
O Municipionline é um banco de dados sobre todos os municípios brasileiros. O serviço iniciou suas atividades na internet em 1996, no Rio de Janeiro.

Atualmente, o sítio na internet é uma das maiores fontes de dados da malha municipal brasileira. Consultado por milhares de pessoas diariamente.

O site conta com uma ferramenta de busca, onde se pode fazer pesquisas usando opções como nome, população, estado, ano de fundação e outros. Esta ferramenta ajuda o usuário a navegar nas quase 60.000 páginas do site.

Para cada um dos 5.561 municípios, foi criado um espaço chamado Mural, onde o usuário pode deixar perguntas, comentários e tirar dúvidas sobre o respectivo município de busca. Milhares de perguntas já foram encaminhadas e solucionadas em centenas de municípios.

História

O Municipionline originou-se da publicação, em 1995, da Enciclopédia dos Municípios Brasileiros. A Enciclopédia publicada no começo daquele ano, foi publicada em 10 volumes, trazendo um verbete de meia página com os dados de todos municípios brasileiros e seus administradores. Para facilitar o trabalho de atualização constante, todas as informações e mapas foram digitalizadas e colocados online para consulta geral.

Ligações externas
 Município Online Acessado em 11 de Julho de 2008.

redpajama_set_name: RedPajamaWikipedia


text:
begin
  require_relative 'helper'
  require 'fiddle/cparser'
rescue LoadError
end

module Fiddle
  class TestCParser < TestCase
    include CParser

    def test_char_ctype
      assert_equal(TYPE_CHAR, parse_ctype('char'))
      assert_equal(TYPE_CHAR, parse_ctype('signed char'))
      assert_equal(-TYPE_CHAR, parse_ctype('unsigned char'))
    end

    def test_short_ctype
      assert_equal(TYPE_SHORT, parse_ctype('short'))
      assert_equal(TYPE_SHORT, parse_ctype('short int'))
      assert_equal(TYPE_SHORT, parse_ctype('signed short'))
      assert_equal(TYPE_SHORT, parse_ctype('signed short int'))
      assert_equal(-TYPE_SHORT, parse_ctype('unsigned short'))
      assert_equal(-TYPE_SHORT, parse_ctype('unsigned short int'))
    end

    def test_int_ctype
      assert_equal(TYPE_INT, parse_ctype('int'))
      assert_equal(TYPE_INT, parse_ctype('signed int'))
      assert_equal(-TYPE_INT, parse_ctype('uint'))
      assert_equal(-TYPE_INT, parse_ctype('unsigned int'))
    end

    def test_long_ctype
      assert_equal(TYPE_LONG, parse_ctype('long'))
      assert_equal(TYPE_LONG, parse_ctype('long int'))
      assert_equal(TYPE_LONG, parse_ctype('signed long'))
      assert_equal(TYPE_LONG, parse_ctype('signed long int'))
      assert_equal(-TYPE_LONG, parse_ctype('unsigned long'))
      assert_equal(-TYPE_LONG, parse_ctype('unsigned long int'))
    end

    def test_size_t_ctype
      assert_equal(TYPE_SIZE_T, parse_ctype("size_t"))
    end

    def test_ssize_t_ctype
      assert_equal(TYPE_SSIZE_T, parse_ctype("ssize_t"))
    end

    def test_ptrdiff_t_ctype
      assert_equal(TYPE_PTRDIFF_T, parse_ctype("ptrdiff_t"))
    end

    def test_intptr_t_ctype
      assert_equal(TYPE_INTPTR_T, parse_ctype("intptr_t"))
    end

    def test_uintptr_t_ctype
      assert_equal(TYPE_UINTPTR_T, parse_ctype("uintptr_t"))
    end

    def test_undefined_ctype
      assert_raises(DLError) { parse_ctype('DWORD') }
    end

    def test_undefined_ctype_with_type_alias
      assert_equal(-TYPE_LONG, parse_ctype('DWORD', {"DWORD" => "unsigned long"}))
    end

    def test_struct_basic
      assert_equal [[TYPE_INT, TYPE_CHAR], ['i', 'c']], parse_struct_signature(['int i', 'char c'])
    end

    def test_struct_array
      assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature(['char buffer[80]', 'int[5] x'])
    end

    def test_struct_array_str
      assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature('char buffer[80], int[5] x')
    end

    def test_struct_function_pointer
      assert_equal [[TYPE_VOIDP], ['cb']], parse_struct_signature(['void (*cb)(const char*)'])
    end

    def test_struct_function_pointer_str
      assert_equal [[TYPE_VOIDP,TYPE_VOIDP], ['cb', 'data']], parse_struct_signature('void (*cb)(const char*), const char* data')
    end

    def test_struct_string
      assert_equal [[TYPE_INT,TYPE_VOIDP,TYPE_VOIDP], ['x', 'cb', 'name']], parse_struct_signature('int x; void (*cb)(); const char* name')
    end

    def test_struct_undefined
      assert_raises(DLError) { parse_struct_signature(['int i', 'DWORD cb']) }
    end

    def test_struct_undefined_with_type_alias
      assert_equal [[TYPE_INT,-TYPE_LONG], ['i', 'cb']], parse_struct_signature(['int i', 'DWORD cb'], {"DWORD" => "unsigned long"})
    end

    def test_signature_basic
      func, ret, args = parse_signature('void func()')
      assert_equal 'func', func
      assert_equal TYPE_VOID, ret
      assert_equal [], args
    end

    def test_signature_semi
      func, ret, args = parse_signature('void func();')
      assert_equal 'func', func
      assert_equal TYPE_VOID, ret
      assert_equal [], args
    end

    def test_signature_void_arg
      func, ret, args = parse_signature('void func(void)')
      assert_equal 'func', func
      assert_equal TYPE_VOID, ret
      assert_equal [], args
    end

    def test_signature_type_args
      types = [
        'char', 'unsigned char',
        'short', 'unsigned short',
        'int', 'unsigned int',
        'long', 'unsigned long',
        'long long', 'unsigned long long',
        'float', 'double',
        'const char*', 'void*',
      ]
      func, ret, args = parse_signature("void func(#{types.join(',')})")
      assert_equal 'func', func
      assert_equal TYPE_VOID, ret
      assert_equal [
        TYPE_CHAR, -TYPE_CHAR,
        TYPE_SHORT, -TYPE_SHORT,
        TYPE_INT, -TYPE_INT,
        TYPE_LONG, -TYPE_LONG,
        TYPE_LONG_LONG, -TYPE_LONG_LONG,
        TYPE_FLOAT, TYPE_DOUBLE,
        TYPE_VOIDP, TYPE_VOIDP,
      ], args
    end

    def test_signature_single_variable
      func, ret, args = parse_signature('void func(int x)')
      assert_equal 'func', func
      assert_equal TYPE_VOID, ret
      assert_equal [TYPE_INT], args
    end

    def test_signature_multiple_variables
      func, ret, args = parse_signature('void func(int x, const char* s)')
      assert_equal 'func', func
      assert_equal TYPE_VOID, ret
      assert_equal [TYPE_INT, TYPE_VOIDP], args
    end

    def test_signature_array_variable
      func, ret, args = parse_signature('void func(int x[], int y[40])')
      assert_equal 'func', func
      assert_equal TYPE_VOID, ret
      assert_equal [TYPE_VOIDP, TYPE_VOIDP], args
    end

    def test_signature_function_pointer
      func, ret, args = parse_signature('int func(int (*sum)(int x, int y), int x, int y)')
      assert_equal 'func', func
      assert_equal TYPE_INT, ret
      assert_equal [TYPE_VOIDP, TYPE_INT, TYPE_INT], args
    end

    def test_signature_return_pointer
      func, ret, args = parse_signature('void* malloc(size_t)')
      assert_equal 'malloc', func
      assert_equal TYPE_VOIDP, ret
      assert_equal [TYPE_SIZE_T], args
    end

    def test_signature_return_array
      func, ret, args = parse_signature('int (*func())[32]')
      assert_equal 'func', func
      assert_equal TYPE_VOIDP, ret
      assert_equal [], args
    end

    def test_signature_return_array_with_args
      func, ret, args = parse_signature('int (*func(const char* s))[]')
      assert_equal 'func', func
      assert_equal TYPE_VOIDP, ret
      assert_equal [TYPE_VOIDP], args
    end

    def test_signature_return_function_pointer
      func, ret, args = parse_signature('int (*func())(int x, int y)')
      assert_equal 'func', func
      assert_equal TYPE_VOIDP, ret
      assert_equal [], args
    end

    def test_signature_return_function_pointer_with_args
      func, ret, args = parse_signature('int (*func(int z))(int x, int y)')
      assert_equal 'func', func
      assert_equal TYPE_VOIDP, ret
      assert_equal [TYPE_INT], args
    end
  end
end if defined?(Fiddle)


Disobedience opens a door to evil spirits that lead to eternal death.
How? When we disobey God, we become enemies of God. Obedience is an act of our will. We choose to obey or disobey. Normally if you were at one time God's anointed, an evil spirit will take over when the Holy Spirit leaves. Sometimes this happens without the person knowing that they are now operating under a different spirit.
There is one fascinating story of a man who was selfish, heartless and very religious. He was so religious that even when God rejected him, he was still prophesying. He had a contempt for God's chosen. He disobeyed God and wanted to kill those who were being led by the Spirit of God because they didn't do things his way or they overshadowed him. This man was King Saul.
1 Samuel 14: 1 One day Jonathan son of Saul said to his young armor-bearer, "Come, let's go over to the Philistine outpost on the other side." But he did not tell his father.
11 So both of them showed themselves to the Philistine outpost. "Look!" said the Philistines. "The Hebrews are crawling out of the holes they were hiding in." 12 The men of the outpost shouted to Jonathan and his armor-bearer, "Come up to us and we'll teach you a lesson." So Jonathan said to his armor-bearer, "Climb up after me; the Lord has given them into the hand of Israel."13 Jonathan climbed up, using his hands and feet, with his armor-bearer right behind him. The Philistines fell before Jonathan, and his armor-bearer followed and killed behind him. 14 In that first attack Jonathan and his armor-bearer killed some twenty men in an area of about half an acre. 15 Then panic struck the whole army—those in the camp and field, and those in the outposts and raiding parties—and the ground shook. It was a panic sent by God.
Please note that while Jonathan and his servant were busy fighting the philistines, Saul and his army were still holed up in their hideout unaware that through the obidience of one man (Jonathan) who had sneaked out of the camp, God was fighting for them and the enemy was being scattered.
20 Then Saul and all his men assembled and went to the battle. They found the Philistines in total confusion, striking each other with their swords.
In the following verses, we see Soul's ego getting on the way and starving his army who were already exhausted from the battle. The same thing we see in carnal Christians today who load others with unnecessary doctrines that are born out of self. They are useless spiritually tiring doctrines and traditions taught by demons.
44 Saul said, "May God deal with me, be it ever so severely, if you do not die, Jonathan." 45 But the men said to Saul, "Should Jonathan die—he who has brought about this great deliverance in Israel? Never! As surely as the Lord lives, not a hair of his head will fall to the ground, for he did this today with God's help." So the men rescued Jonathan, and he was not put to death.
Saul was full of himself. Even in this battle with the philistines he treated it as His and not God's. He was everything. He didn't see the hand of God working because of Jonathan's obedience but his solders saw it and protected Jonathan. Saul was preoccupied with self, was heartless and very religious. When the Spirit of God was busy slaying the enemy because of the action of faith by Jonathan, Saul was busy wasting time with the priest. Everything had to be done his way, he didn't even allow the solders to eat. We do the same at the expense of mercy and obedience. We would rather that people do what we want them to do than let them obey God. We make people who obey God our enemies. We use our power to curse them and slander them.
8 Saul was very angry; this refrain displeased him greatly. "They have credited David with tens of thousands," he thought, "but me with only thousands. What more can he get but the kingdom?" 9 And from that time on Saul kept a close eye on David.10 The next day an evil a spirit from God came forcefully on Saul. He was prophesying in his house, while David was playing the lyre, as he usually did. Saul had a spear in his hand 11 and he hurled it, saying to himself, "I'll pin David to the wall." But David eluded him twice.
1 Samuel 16: 14 Now the Spirit of the Lord had departed from Saul, and an evil a spirit from the Lord tormented him.15 Saul's attendants said to him, "See, an evil spirit from God is tormenting you. 16 Let our lord command his servants here to search for someone who can play the lyre. He will play when the evil spirit from God comes on you, and you will feel better."17 So Saul said to his attendants, "Find someone who plays well and bring him to me."18 One of the servants answered, "I have seen a son of Jesse of Bethlehem who knows how to play the lyre. He is a brave man and a warrior. He speaks well and is a fine-looking man. And the Lord is with him."19 Then Saul sent messengers to Jesse and said, "Send me your son David, who is with the sheep." 20 So Jesse took a donkey loaded with bread, a skin of wine and a young goat and sent them with his son David to Saul.21 David came to Saul and entered his service. Saul liked him very much, and David became one of his armor-bearers. 22 Then Saul sent word to Jesse, saying, "Allow David to remain in my service, for I am pleased with him."23 Whenever the spirit from God came on Saul, David would take up his lyre and play. Then relief would come to Saul; he would feel better, and the evil spirit would leave him.
Saul and his servants recognised that he was being tortured by an evil spirit and sought help from David who was operating through the Holy Spirit.
We act the same way. We go to church or fellowships to get a relieve from our mental tortures, but when we step out of the church the issues come back. Church becomes a place of therapy from the torment of evil spirits that dwell in us due to our rebellion towards God.
God in His mercy will not reject you and will continue to reach you.
Saul's servants, the solders and his son Jonathan, recognised that he was not acting right. Imagine yourself in that group under such a powerful person. You will in no doubt feel helpless.
Both David and Jonathan realised that they had to choose to obey God. Jonathan was ready to die for doing God's will than obey man even if that man is king and his dad. Are we ready to make such hard choices?
Luke 14:26 -27 "If you want to be my disciple, you must hate everyone else by comparison–your father and mother, wife and children, brothers and sisters–yes, even your own life. Otherwise, you cannot be my disciple. And if you do not carry your own cross and follow me, you cannot be my disciple.
Imagine carrying your own cross just like Jesus did. Anybody who carried a cross during that era meant they were on their way to death. I don't think you can carry your cross and at the same time compromise. It's either one or the other.
There are those that have been disowned by close friends and relatives because of their own stand. Imagine how Jonathan felt when he was told by his own father that he must die. The reason for his death had nothing to do with his disobedience to God but his father's ego.
Sometimes you will be disowned and persons close to you will hate the anointing on you and start spreading malicious rumours that you have an impure spirit.
The devil attempted this on Jesus, so he will do it on you also. People will call us wicked when we truly expose the works of the devil. Remember that you don have to worry if your own family does not believe in you. They did it to Jesus.
John 7:5 For even his own brothers did not believe in him.
Mark 3:28-35 Truly I tell you, people can be forgiven all their sins and every slander they utter, but whoever blasphemes against the Holy Spirit will never be forgiven; they are guilty of an eternal sin." He said this because they were saying, "He has an impure spirit. Then Jesus' mother and brothers arrived. Standing outside, they sent someone in to call him. A crowd was sitting around him, and they told him, "Your mother and brothers are outside looking for you." "Who are my mother and my brothers?" he asked. Then he looked at those seated in a circle around him and said, "Here are my mother and my brothers! Whoever does God's will is my brother and sister and mother.
Remember that though you have earthly parents and siblings, those that are in fellowship with you, who live according to the will of God, are no doubt your brothers and sisters and can be relied on when it comes to the spiritual war declared on us by the evil one.


text:
"""
pglookout tests

Copyright (c) 2015 Ohmu Ltd
Copyright (c) 2014 F-Secure

This file is under the Apache License, Version 2.0.
See the file `LICENSE` for details.
"""
from pglookout.common import get_iso_timestamp
from pglookout.pgutil import get_connection_info, get_connection_info_from_config_line
import datetime
import json
import os
import time

def test_connect_to_cluster_nodes_and_cleanup_old_nodes(pgl):
    pgl.cluster_monitor.db_conns = {
        "1.2.3.4": "bar",
        "2.3.4.5": "foo",
        "3.4.5.6": "foo",
        None: "foo",
    }
    pgl.cluster_monitor.connect_to_cluster_nodes_and_cleanup_old_nodes()
    assert pgl.cluster_monitor.db_conns == {}

def test_state_file_write(pgl, tmpdir):
    state_file_path = tmpdir.join("state_file").strpath
    pgl.config["json_state_file_path"] = state_file_path
    pgl.write_cluster_state_to_json_file()
    assert os.path.exists(state_file_path)
    with open(state_file_path, "r") as fp:
        state = json.load(fp)
    assert isinstance(state, dict)

def test_load_config(pgl):
    pgl.own_db = "old_value"
    pgl.load_config()
    assert pgl.own_db == "1.2.3.4"

def _create_db_node_state(pg_last_xlog_receive_location=None, pg_is_in_recovery=True,
                          connection=True, replication_time_lag=None, fetch_time=None,
                          db_time=None):
    return {
        "connection": connection,
        "db_time": get_iso_timestamp(db_time),
        "fetch_time": get_iso_timestamp(fetch_time),
        "pg_is_in_recovery": pg_is_in_recovery,
        "pg_last_xact_replay_timestamp": None,
        "pg_last_xlog_receive_location": pg_last_xlog_receive_location,
        "pg_last_xlog_replay_location": None,
        "replication_time_lag": replication_time_lag,
        "min_replication_time_lag": 0,  # simulate that we've been in sync once
    }

def _add_to_observer_state(pgl, observer_name, db_name, pg_last_xlog_receive_location=None,
                           pg_is_in_recovery=True, connection=True, replication_time_lag=None,
                           fetch_time=None, db_time=None):
    db_node_state = _create_db_node_state(pg_last_xlog_receive_location, pg_is_in_recovery,
                                          connection, replication_time_lag, fetch_time=fetch_time,
                                          db_time=db_time)
    update_dict = {
        "fetch_time": get_iso_timestamp(),
        "connection": True,
        db_name: db_node_state,
    }
    if observer_name in pgl.observer_state:
        pgl.observer_state[observer_name].update(update_dict)
    else:
        pgl.observer_state[observer_name] = update_dict

def _add_db_to_cluster_state(pgl, instance, pg_last_xlog_receive_location=None,
                             pg_is_in_recovery=True, connection=True, replication_time_lag=None,
                             fetch_time=None, db_time=None, conn_info=None):
    db_node_state = _create_db_node_state(pg_last_xlog_receive_location, pg_is_in_recovery,
                                          connection, replication_time_lag, fetch_time=fetch_time,
                                          db_time=db_time)
    pgl.cluster_state[instance] = db_node_state
    pgl.config["remote_conns"][instance] = conn_info or {"host": instance}

def test_check_cluster_state_warning(pgl):
    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=40.0)

    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=True)
    pgl.current_master = "old_master"
    pgl.own_db = "kuu"
    pgl.over_warning_limit_command = "fake_command"
    pgl.execute_external_command.return_value = 0
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1
    assert pgl.create_alert_file.call_count == 1
    pgl.check_cluster_state()

    # call count does not change when we have sent a single warning
    assert pgl.execute_external_command.call_count == 1
    assert pgl.replication_lag_over_warning_limit
    assert pgl.create_alert_file.call_count == 1

    # and then the replication catches up
    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=5.0)
    pgl.check_cluster_state()
    assert not os.path.exists("replication_delay_warning")
    assert pgl.replication_lag_over_warning_limit is False

def test_check_cluster_do_failover_one_standby(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             db_time=datetime.datetime(year=2014, month=1, day=1))

    _add_db_to_cluster_state(pgl, "own_db", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)

    pgl.own_db = "own_db"
    pgl.execute_external_command.return_value = 0
    pgl.replication_lag_over_warning_limit = False
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1
    assert pgl.replication_lag_over_warning_limit is False

def test_check_cluster_master_gone_one_standby_one_observer(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             db_time=datetime.datetime(year=2014, month=1, day=1))

    _add_db_to_cluster_state(pgl, "own_db", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=0.0)
    pgl.own_db = "own_db"
    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=False,
                           db_time=datetime.datetime(year=2014, month=1, day=1))
    _add_to_observer_state(pgl, "observer", "own_db", pg_last_xlog_receive_location="2/aaaaaaaa",
                           pg_is_in_recovery=True, connection=True, replication_time_lag=0.0)

    # Simulate existing master connection
    pgl.current_master = "old_master"
    pgl.execute_external_command.return_value = 0
    pgl.replication_lag_over_warning_limit = False

    del pgl.config["remote_conns"]["old_master"]
    # Old master removed from config, cluster monitor would remove node from cluster state so do the same here
    del pgl.cluster_state["old_master"]
    pgl.cluster_nodes_change_time = time.monotonic()

    # First call does not promote due to missing master because config has been updated just recently and there's
    # by default a grace period that's waited after list of known cluster nodes changes
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is False

    # If we say that master is known to be gone promotion will happen even though config was updated recently
    pgl.known_gone_nodes.append("old_master")
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1
    assert pgl.replication_lag_over_warning_limit is False

def test_check_cluster_do_failover_one_standby_one_observer(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             db_time=datetime.datetime(year=2014, month=1, day=1))

    _add_db_to_cluster_state(pgl, "own_db", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "own_db"
    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=False,
                           db_time=datetime.datetime(year=2014, month=1, day=1))
    _add_to_observer_state(pgl, "observer", "own_db", pg_last_xlog_receive_location="2/aaaaaaaa",
                           pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)

    pgl.execute_external_command.return_value = 0
    pgl.replication_lag_over_warning_limit = False
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1
    assert pgl.replication_lag_over_warning_limit is False

def test_check_cluster_do_failover_with_a_node_which_is_is_maintenance(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             db_time=datetime.datetime(year=2014, month=1, day=1))

    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)

    pgl.never_promote_these_nodes = []
    pgl.own_db = "kuu"
    pgl.execute_external_command.return_value = 0
    pgl.replication_lag_over_warning_limit = True
    pgl.check_for_maintenance_mode_file.return_value = True
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True
    assert pgl.check_for_maintenance_mode_file.call_count == 1

def test_check_cluster_do_failover_with_a_node_which_should_never_be_promoted(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False)

    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.never_promote_these_nodes = ["kuu"]
    pgl.own_db = "kuu"
    pgl.execute_external_command.return_value = 0
    pgl.replication_lag_over_warning_limit = True
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True

def test_check_cluster_do_failover_two_standbys(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False)

    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "kuu"
    # we put the second standby _WELL_ ahead
    _add_db_to_cluster_state(pgl, "puu", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)

    pgl.execute_external_command.return_value = 0
    pgl.replication_lag_over_warning_limit = True
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True  # we keep the warning on

def test_check_cluster_do_failover_two_standbys_when_the_one_ahead_can_never_be_promoted(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             db_time=datetime.datetime(year=2014, month=1, day=1))

    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "kuu"
    # we put the second standby _WELL_ ahead
    _add_db_to_cluster_state(pgl, "puu", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.never_promote_these_nodes = ["puu"]
    pgl.execute_external_command.return_value = 0
    pgl.replication_lag_over_warning_limit = True
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1
    assert pgl.replication_lag_over_warning_limit is False

def test_failover_with_no_master_anymore(pgl):
    # this should trigger an immediate failover as we have two
    # standbys online but we've never seen a master
    pgl.own_db = "kuu"
    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="F/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=0)
    _add_db_to_cluster_state(pgl, "puu", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=1)

    pgl.execute_external_command.return_value = 0
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1

def test_failover_over_replication_lag_when_still_connected_to_master(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False)

    # We will make our own node to be the furthest along so we get considered for promotion
    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "kuu"

    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True  # we keep the warning on

def test_failover_over_replication_lag_with_one_observer_one_standby_no_connections(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False)

    # We will make our own node to be the furthest along so we get considered for promotion
    _add_db_to_cluster_state(pgl, "own_db", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "own_db"

    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=False,
                           db_time=datetime.datetime(year=2014, month=1, day=1))
    _add_to_observer_state(pgl, "observer", "own_db", pg_last_xlog_receive_location="2/aaaaaaaa",
                           pg_is_in_recovery=True, connection=False, replication_time_lag=130.0)
    pgl.observer_state["observer"]["connection"] = False
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True  # we keep the warning on

def test_cluster_state_when_observer_has_also_non_members_of_our_current_cluster(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=True)

    # We will make our own node to be the furthest along so we get considered for promotion
    _add_db_to_cluster_state(pgl, "own_db", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "own_db"

    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=False,
                           db_time=datetime.datetime(year=2014, month=1, day=1))
    _add_to_observer_state(pgl, "observer", "own_db", pg_last_xlog_receive_location="2/aaaaaaaa",
                           pg_is_in_recovery=True, connection=False, replication_time_lag=130.0)
    _add_to_observer_state(pgl, "observer", "some_other_cluster", pg_last_xlog_receive_location="3/aaaaaaaa",
                           pg_is_in_recovery=False, connection=True, replication_time_lag=0.0)
    pgl.check_cluster_state()
    assert len(pgl.connected_master_nodes) == 1
    assert "old_master" in pgl.connected_master_nodes

def test_failover_no_connections(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False)

    # We will make our own node to be the furthest along so we get considered for promotion
    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "kuu"

    # we put the second standby _WELL_ ahead
    _add_db_to_cluster_state(pgl, "puu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=False, replication_time_lag=130.0)
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True  # we keep the warning on

def test_failover_master_two_standbys_one_observer_no_connection_between_standbys(pgl):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             db_time=datetime.datetime(year=2014, month=1, day=1))
    # We will make our own node to be the furthest along so we get considered for promotion
    _add_db_to_cluster_state(pgl, "own", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.own_db = "own"

    _add_db_to_cluster_state(pgl, "other", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=False, replication_time_lag=130.0)

    # Add observer state
    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=False,
                           db_time=datetime.datetime(year=2014, month=1, day=1))
    _add_to_observer_state(pgl, "observer", "other", pg_last_xlog_receive_location="1/aaaaaaaa",
                           pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    _add_to_observer_state(pgl, "observer", "own", pg_last_xlog_receive_location="2/aaaaaaaa",
                           pg_is_in_recovery=True, connection=True, replication_time_lag=130.0)
    pgl.execute_external_command.return_value = 0
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1

    assert pgl.replication_lag_over_warning_limit is False

def test_failover_master_one_standby_one_observer_no_connections(pgl):
    pgl.own_db = "own"

    # Add observer state
    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=True)

    # add db state
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=True)
    _add_db_to_cluster_state(pgl, "own", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=40.0)

    pgl.check_cluster_state()
    assert pgl.replication_lag_over_warning_limit is True  # we keep the warning on
    assert pgl.execute_external_command.call_count == 0

    # Add observer state
    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=True)
    _add_to_observer_state(pgl, "observer", "own", pg_last_xlog_receive_location="2/aaaaaaaa",
                           pg_is_in_recovery=True, connection=True, replication_time_lag=9.0)

    _add_db_to_cluster_state(pgl, "own", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=140.0)

    pgl.check_cluster_state()

    # No failover yet
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit is True  # we keep the warning on

    # observer state
    _add_to_observer_state(pgl, "observer", "old_master", pg_is_in_recovery=False, connection=False,
                           db_time=datetime.datetime(year=2014, month=1, day=1))
    _add_to_observer_state(pgl, "observer", "own", pg_last_xlog_receive_location="2/aaaaaaaa",
                           pg_is_in_recovery=True, connection=False, replication_time_lag=140.0)
    # lose own connection to master
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             db_time=datetime.datetime(year=2014, month=1, day=1))
    # now do failover
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1

def test_find_current_master(pgl):
    _add_db_to_cluster_state(pgl, "master", pg_is_in_recovery=False, connection=True)
    # We will make our own node to be the furthest along so we get considered for promotion
    _add_db_to_cluster_state(pgl, "own", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=True, replication_time_lag=0.1)
    pgl.own_db = "master"
    pgl.check_cluster_state()
    assert pgl.current_master == "master"

def test_two_standby_failover_and_autofollow(pgl, tmpdir):
    _add_db_to_cluster_state(pgl, "old_master", pg_is_in_recovery=False, connection=False,
                             fetch_time=datetime.datetime(year=2014, month=1, day=1))
    # We will make our own node to be the furthest from master so we don't get considered for promotion
    _add_db_to_cluster_state(pgl, "own", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, connection=False, replication_time_lag=130.0)
    pgl.own_db = "own"
    _add_db_to_cluster_state(pgl, "other", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=True, connection=False, replication_time_lag=130.0)
    pgl.check_cluster_state()

    assert pgl.replication_lag_over_warning_limit is True  # we keep the warning on
    assert pgl.execute_external_command.call_count == 0
    assert pgl.current_master == "old_master"

    _add_db_to_cluster_state(pgl, "other", pg_last_xlog_receive_location="2/aaaaaaaa",
                             pg_is_in_recovery=False, connection=True, replication_time_lag=0.0,
                             conn_info={"host": "otherhost.example.com", "port": 11111})

    pg_data_dir = tmpdir.join("test_pgdata").strpath
    os.makedirs(pg_data_dir)
    primary_conninfo = (
        "user=replication password=vjsh8l7sv4a902y1tsdz "
        "host=old_master port=5432 "
        "sslmode=prefer sslcompression=1 krbsrvname=postgres"
    )
    old_recovery_conf = f"standby_mode = 'on'\nprimary_conninfo = '{primary_conninfo}'\n"
    with open(os.path.join(pg_data_dir, "recovery.conf"), "w") as fp:
        fp.write(old_recovery_conf)

    pgl.config["pg_data_directory"] = pg_data_dir
    pgl.config["autofollow"] = True
    pgl.primary_conninfo_template = get_connection_info(primary_conninfo)

    with open(os.path.join(pg_data_dir, "PG_VERSION"), "w") as fp:
        fp.write("11\n")

    pgl.check_cluster_state()
    assert pgl.current_master == "other"

    with open(os.path.join(pg_data_dir, "recovery.conf"), "r") as fp:
        new_lines = fp.read().splitlines()
    assert new_lines.pop(0).startswith("# pglookout updated primary_conninfo")
    assert new_lines.pop(0) == "standby_mode = 'on'"
    assert new_lines[0].startswith("primary_conninfo = ")
    new_primary_conninfo = new_lines.pop(0)
    assert new_lines.pop(0) == "recovery_target_timeline = 'latest'"
    assert new_lines == []
    old_conn_info = get_connection_info(primary_conninfo)
    new_conn_info = get_connection_info_from_config_line(new_primary_conninfo)
    assert new_conn_info == dict(old_conn_info, host="otherhost.example.com", port="11111")

def test_replication_positions(pgl):
    standby_nodes = {
        "10.255.255.10": {
            "connection": True,
            "db_time": "2014-08-28T14:09:57.919301+00:00Z",
            "fetch_time": "2014-08-28T14:09:57.918753Z",
            "pg_is_in_recovery": True,
            "pg_last_xlog_receive_location": "0/9000090",
            "pg_last_xlog_replay_location": "0/9000090",
            "pg_last_xact_replay_timestamp": "2014-08-28T14:05:43.577357+00:00Z",
            "replication_time_lag": 254.341944,
        },
    }
    # the above node shouldn't show up as its fetch_time is (way) older than 20 seconds
    positions = {}
    assert pgl.get_replication_positions(standby_nodes) == positions
    standby_nodes["10.255.255.10"]["fetch_time"] = get_iso_timestamp()
    positions[0x9000090] = set(["10.255.255.10"])
    assert pgl.get_replication_positions(standby_nodes) == positions
    # add another standby, further ahead
    standby_nodes["10.255.255.11"] = dict(standby_nodes["10.255.255.10"], pg_last_xlog_receive_location="1/0000AAAA")
    positions[1 << 32 | 0xAAAA] = set(["10.255.255.11"])
    assert pgl.get_replication_positions(standby_nodes) == positions
    # add another standby which hasn't received anything
    standby_nodes["10.255.255.12"] = dict(standby_nodes["10.255.255.10"], pg_last_xlog_receive_location=None)
    positions[0x9000090].add("10.255.255.12")
    assert pgl.get_replication_positions(standby_nodes) == positions

def test_node_map(pgl):
    cluster_state = {
        "10.255.255.10": {
            "connection": True,
            "db_time": "2014-08-28T14:26:51.067084+00:00Z",
            "fetch_time": "2014-08-28T14:26:51.066368Z",
            "pg_is_in_recovery": False,
            "pg_last_xact_replay_timestamp": "2014-08-28T14:05:43.577357+00:00Z",
            "pg_last_xlog_receive_location": "0/9000090",
            "pg_last_xlog_replay_location": "0/9000090",
            "replication_time_lag": 1267.489727,
        },
        "10.255.255.9": {
            "connection": False,
            "fetch_time": "2014-08-28T14:26:51.068151Z",
        }
    }
    observer_state = {
        "10.255.255.11": {
            "10.255.255.10": {
                "connection": True,
                "db_time": "2014-08-28T14:26:47.105901+00:00Z",
                "fetch_time": "2014-08-28T14:26:47.104849Z",
                "pg_is_in_recovery": False,
                "pg_last_xact_replay_timestamp": "2014-08-28T14:05:43.577357+00:00Z",
                "pg_last_xlog_receive_location": "0/9000090",
                "pg_last_xlog_replay_location": "0/9000090",
                "replication_time_lag": 1263.528544,
            },
            "10.255.255.9": {
                "connection": False,
                "db_time": "2014-08-28T14:06:15.172820+00:00Z",
                "fetch_time": "2014-08-28T14:26:47.107115Z",
                "pg_is_in_recovery": False,
                "pg_last_xact_replay_timestamp": None,
                "pg_last_xlog_receive_location": None,
                "pg_last_xlog_replay_location": None,
            },
            "connection": True,
            "fetch_time": "2014-08-28T14:26:51.069891Z",
        }
    }
    master_host, _, standby_nodes = pgl.create_node_map(cluster_state, observer_state)
    assert master_host == "10.255.255.10"
    assert standby_nodes == {}

def test_node_map_disconnected_current_master(pgl):
    pgl.current_master = "10.255.255.7"
    cluster_state = {
        "10.255.255.7": {
            "connection": False,
            "db_time": "2014-09-07T15:26:23.957151+00:00Z",
            "fetch_time": "2014-09-07T15:26:34.736495Z",
            "pg_is_in_recovery": False,
            "pg_last_xact_replay_timestamp": None,
            "pg_last_xlog_receive_location": None,
            "pg_last_xlog_replay_location": None,
        },
        "10.255.255.8": {
            "connection": True,
            "db_time": "2014-09-07T15:26:23.959461+00:00Z",
            "fetch_time": "2014-09-07T15:26:23.919281Z",
            "pg_is_in_recovery": True,
            "pg_last_xact_replay_timestamp": "2014-09-07T15:25:40.372936+00:00Z",
            "pg_last_xlog_receive_location": "0/74713D8",
            "pg_last_xlog_replay_location": "0/74713D8",
            "replication_time_lag": 43.586525,
        }
    }
    observer_state = {}
    master_host, _, standby_nodes = pgl.create_node_map(cluster_state, observer_state)
    assert master_host == "10.255.255.7"
    assert list(standby_nodes.keys())[0] == "10.255.255.8"

def test_standbys_failover_equal_replication_positions(pgl):
    now = datetime.datetime.utcnow()
    _add_db_to_cluster_state(
        pgl,
        instance="192.168.54.183",
        pg_last_xlog_receive_location="0/70004D8",
        pg_is_in_recovery=True,
        connection=True,
        replication_time_lag=400.435871,
        fetch_time=now,
        db_time=now,
        conn_info="foobar",
    )
    _add_db_to_cluster_state(
        pgl,
        instance="192.168.57.180",
        pg_last_xlog_receive_location=None,
        pg_is_in_recovery=False,
        connection=False,
        replication_time_lag=0.0,
        fetch_time=now - datetime.timedelta(seconds=3600),
        db_time=now - datetime.timedelta(seconds=3600),
        conn_info="foobar",
    )
    _add_db_to_cluster_state(
        pgl,
        instance="192.168.63.4",
        pg_last_xlog_receive_location="0/70004D8",
        pg_is_in_recovery=True,
        connection=True,
        replication_time_lag=401.104655,
        fetch_time=now,
        db_time=now,
        conn_info="foobar",
    )

    pgl.current_master = "192.168.57.180"
    # We select the node with the "highest" identifier so call_count should stay zero if we're not the
    # highest standby currently.
    pgl.own_db = "192.168.54.183"
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 0
    # If we're the highest we should see call_count increment
    pgl.own_db = "192.168.63.4"
    pgl.check_cluster_state()
    assert pgl.execute_external_command.call_count == 1

def test_node_map_when_only_observer_sees_master(pgl):
    cluster_state = {
        "10.255.255.10": {
            "connection": False,
            "db_time": "2014-08-28T14:26:51.067084+00:00Z",
            "fetch_time": "2014-08-28T14:26:51.066368Z",
            "pg_is_in_recovery": False,
            "pg_last_xact_replay_timestamp": "2014-08-28T14:05:43.577357+00:00Z",
            "pg_last_xlog_receive_location": "0/9000090",
            "pg_last_xlog_replay_location": "0/9000090",
            "replication_time_lag": 1267.489727,
        },
    }
    observer_state = {
        "10.255.255.11": {
            "10.255.255.10": {
                "connection": True,
                "db_time": "2014-08-28T14:26:47.105901+00:00Z",
                "fetch_time": "2014-08-28T14:26:50.104849Z",
                "pg_is_in_recovery": False,
                "pg_last_xact_replay_timestamp": "2014-08-28T14:05:43.577357+00:00Z",
                "pg_last_xlog_receive_location": "0/9000090",
                "pg_last_xlog_replay_location": "0/9000090",
                "replication_time_lag": 1263.528544,
            },
            "connection": True,
            "fetch_time": "2014-08-28T14:26:51.069891Z",
        }
    }
    master_instance, _, _ = pgl.create_node_map(cluster_state, observer_state)
    assert master_instance == "10.255.255.10"
    # because observer saw it and its fetch time is later than cluster time
    assert master_instance in pgl.connected_master_nodes

def test_poll_observers_on_warning_only(pgl):
    pgl.config["poll_observers_on_warning_only"] = True
    pgl.config["observers"] = {"local": "URL"}
    pgl.own_db = "kuu"
    _add_db_to_cluster_state(pgl, "master", pg_is_in_recovery=False, connection=True, db_time=datetime.datetime.min)
    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, replication_time_lag=40.0)
    pgl.check_cluster_state()
    assert "master" not in pgl.disconnected_master_nodes
    assert "master" in pgl.connected_master_nodes
    assert pgl.execute_external_command.call_count == 0
    assert pgl.replication_lag_over_warning_limit
    assert pgl.observer_state_newer_than is not None

    _add_db_to_cluster_state(pgl, "master", pg_is_in_recovery=False, connection=False, db_time=datetime.datetime.min)
    _add_db_to_cluster_state(pgl, "kuu", pg_last_xlog_receive_location="1/aaaaaaaa",
                             pg_is_in_recovery=True, replication_time_lag=140.0)
    _add_to_observer_state(pgl, "observer", "master", pg_is_in_recovery=False,
                           connection=False, db_time=datetime.datetime.min)
    pgl.check_cluster_state()
    # this check makes sure we did not skip doing checks because db_poll_inteval has
    # pass but because observer data is available and create_node_map was called
    assert "master" in pgl.disconnected_master_nodes
    assert pgl.execute_external_command.call_count == 1


text:
Kayl railway station (, , ) is a railway station serving Kayl, in south-western Luxembourg.  It is operated by Chemins de Fer Luxembourgeois, the state-owned railway company.

The station is situated on Line 60, which connects Luxembourg City to the Red Lands of the south of the country.  Kayl is the first stop on a branch line that, splitting from the main line at Noertzange, leads to Rumelange.

External links

 Official CFL page on Kayl station
 Rail.lu page on Kayl station

Railway
Railway stations in Luxembourg
Railway stations on CFL Line 60