Merge "Add helper function to insert with retry."
This commit is contained in:
commit
b6375273ac
1 changed files with 35 additions and 37 deletions
|
@ -269,27 +269,14 @@ impl KeystoreDB {
|
||||||
.context(format!("Domain {:?} must be either App or SELinux.", domain));
|
.context(format!("Domain {:?} must be either App or SELinux.", domain));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Loop until we get a unique id.
|
Self::insert_with_retry(|id| {
|
||||||
loop {
|
self.conn.execute(
|
||||||
let newid: i64 = random();
|
|
||||||
let ret = self.conn.execute(
|
|
||||||
"INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
|
"INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
|
||||||
VALUES(?, datetime('now'), ?, ?, NULL);",
|
VALUES(?, datetime('now'), ?, ?, NULL);",
|
||||||
params![newid, domain as i64, namespace],
|
params![id, domain as i64, namespace],
|
||||||
);
|
)
|
||||||
match ret {
|
})
|
||||||
// If the id already existed, try again.
|
.context("In create_key_entry")
|
||||||
Err(rusqlite::Error::SqliteFailure(
|
|
||||||
libsqlite3_sys::Error {
|
|
||||||
code: libsqlite3_sys::ErrorCode::ConstraintViolation,
|
|
||||||
extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
|
|
||||||
},
|
|
||||||
_,
|
|
||||||
)) => (),
|
|
||||||
Err(e) => return Err(e).context("Failed to create key entry."),
|
|
||||||
_ => return Ok(newid),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts a new blob and associates it with the given key id. Each blob
|
/// Inserts a new blob and associates it with the given key id. Each blob
|
||||||
|
@ -683,26 +670,14 @@ impl KeystoreDB {
|
||||||
.context("In grant: Failed to update existing grant.")?;
|
.context("In grant: Failed to update existing grant.")?;
|
||||||
grant_id
|
grant_id
|
||||||
} else {
|
} else {
|
||||||
loop {
|
Self::insert_with_retry(|id| {
|
||||||
let newid: i64 = random();
|
tx.execute(
|
||||||
let ret = tx.execute(
|
|
||||||
"INSERT INTO perboot.grant (id, grantee, keyentryid, access_vector)
|
"INSERT INTO perboot.grant (id, grantee, keyentryid, access_vector)
|
||||||
VALUES (?, ?, ?, ?);",
|
VALUES (?, ?, ?, ?);",
|
||||||
params![newid, grantee_uid, key_id, i32::from(access_vector)],
|
params![id, grantee_uid, key_id, i32::from(access_vector)],
|
||||||
);
|
)
|
||||||
match ret {
|
})
|
||||||
// If the id already existed, try again.
|
.context("In grant")?
|
||||||
Err(rusqlite::Error::SqliteFailure(
|
|
||||||
libsqlite3_sys::Error {
|
|
||||||
code: libsqlite3_sys::ErrorCode::ConstraintViolation,
|
|
||||||
extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
|
|
||||||
},
|
|
||||||
_,
|
|
||||||
)) => (),
|
|
||||||
Err(e) => return Err(e).context("Failed to insert grant."),
|
|
||||||
Ok(_) => break newid,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
tx.commit().context("In grant: failed to commit transaction.")?;
|
tx.commit().context("In grant: failed to commit transaction.")?;
|
||||||
|
|
||||||
|
@ -744,6 +719,29 @@ impl KeystoreDB {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates a random id and passes it to the given function, which will
|
||||||
|
// try to insert it into a database. If that insertion fails, retry;
|
||||||
|
// otherwise return the id.
|
||||||
|
fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
|
||||||
|
loop {
|
||||||
|
let newid: i64 = random();
|
||||||
|
match inserter(newid) {
|
||||||
|
// If the id already existed, try again.
|
||||||
|
Err(rusqlite::Error::SqliteFailure(
|
||||||
|
libsqlite3_sys::Error {
|
||||||
|
code: libsqlite3_sys::ErrorCode::ConstraintViolation,
|
||||||
|
extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
|
||||||
|
},
|
||||||
|
_,
|
||||||
|
)) => (),
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e).context("In insert_with_retry: failed to insert into database.")
|
||||||
|
}
|
||||||
|
_ => return Ok(newid),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Takes Rows as returned by a query call on prepared statement.
|
// Takes Rows as returned by a query call on prepared statement.
|
||||||
// Extracts exactly one row with the `row_extractor` and fails if more
|
// Extracts exactly one row with the `row_extractor` and fails if more
|
||||||
// rows are available.
|
// rows are available.
|
||||||
|
|
Loading…
Reference in a new issue