You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					155 lines
				
				3.1 KiB
			
		
		
			
		
	
	
					155 lines
				
				3.1 KiB
			| 
								 
											9 years ago
										 
									 | 
							
								#include "selfdrive/common/params.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "selfdrive/common/util.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								#ifndef _GNU_SOURCE
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								#define _GNU_SOURCE
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								#endif  // _GNU_SOURCE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								#include <sys/file.h>
							 | 
						||
| 
								 | 
							
								#include <unistd.h>
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								namespace {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename T>
							 | 
						||
| 
								 | 
							
								T* null_coalesce(T* a, T* b) {
							 | 
						||
| 
								 | 
							
								  return a != NULL ? a : b;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static const char* default_params_path = null_coalesce(
							 | 
						||
| 
								 | 
							
								    const_cast<const char*>(getenv("PARAMS_PATH")), "/data/params");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}  // namespace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								int write_db_value(const char* params_path, const char* key, const char* value,
							 | 
						||
| 
								 | 
							
								                   size_t value_size) {
							 | 
						||
| 
								 | 
							
								  int lock_fd = -1;
							 | 
						||
| 
								 | 
							
								  int tmp_fd = -1;
							 | 
						||
| 
								 | 
							
								  int result;
							 | 
						||
| 
								 | 
							
								  char tmp_path[1024];
							 | 
						||
| 
								 | 
							
								  char path[1024];
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  ssize_t bytes_written;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (params_path == NULL) {
							 | 
						||
| 
								 | 
							
								    params_path = default_params_path;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Write value to temp.
							 | 
						||
| 
								 | 
							
								  result =
							 | 
						||
| 
								 | 
							
								      snprintf(tmp_path, sizeof(tmp_path), "%s/.tmp_value_XXXXXX", params_path);
							 | 
						||
| 
								 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  tmp_fd = mkstemp(tmp_path);
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  bytes_written = write(tmp_fd, value, value_size);
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								  if (bytes_written != value_size) {
							 | 
						||
| 
								 | 
							
								    result = -20;
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  result = snprintf(path, sizeof(path), "%s/.lock", params_path);
							 | 
						||
| 
								 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  lock_fd = open(path, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  result = snprintf(path, sizeof(path), "%s/d/%s", params_path, key);
							 | 
						||
| 
								 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Take lock.
							 | 
						||
| 
								 | 
							
								  result = flock(lock_fd, LOCK_EX);
							 | 
						||
| 
								 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  // fsync to force persist the changes.
							 | 
						||
| 
								 | 
							
								  result = fsync(tmp_fd);
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  // Move temp into place.
							 | 
						||
| 
								 | 
							
								  result = rename(tmp_path, path);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								  // Release lock.
							 | 
						||
| 
								 | 
							
								  if (lock_fd >= 0) {
							 | 
						||
| 
								 | 
							
								    close(lock_fd);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (tmp_fd >= 0) {
							 | 
						||
| 
								 | 
							
								    if (result < 0) {
							 | 
						||
| 
								 | 
							
								      remove(tmp_path);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    close(tmp_fd);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int read_db_value(const char* params_path, const char* key, char** value,
							 | 
						||
| 
								 | 
							
								                  size_t* value_sz) {
							 | 
						||
| 
								 | 
							
								  int lock_fd = -1;
							 | 
						||
| 
								 | 
							
								  int result;
							 | 
						||
| 
								 | 
							
								  char path[1024];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  if (params_path == NULL) {
							 | 
						||
| 
								 | 
							
								    params_path = default_params_path;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								  result = snprintf(path, sizeof(path), "%s/.lock", params_path);
							 | 
						||
| 
								 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  lock_fd = open(path, 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  result = snprintf(path, sizeof(path), "%s/d/%s", params_path, key);
							 | 
						||
| 
								 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Take lock.
							 | 
						||
| 
								 | 
							
								  result = flock(lock_fd, LOCK_EX);
							 | 
						||
| 
								 | 
							
								  if (result < 0) {
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Read value.
							 | 
						||
| 
								 | 
							
								  // TODO(mgraczyk): If there is a lot of contention, we can release the lock
							 | 
						||
| 
								 | 
							
								  //                 after opening the file, before reading.
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								  *value = static_cast<char*>(read_file(path, value_sz));
							 | 
						||
| 
								 
											9 years ago
										 
									 | 
							
								  if (*value == NULL) {
							 | 
						||
| 
								 | 
							
								    result = -22;
							 | 
						||
| 
								 | 
							
								    goto cleanup;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Remove one for null byte.
							 | 
						||
| 
								 | 
							
								  if (value_sz != NULL) {
							 | 
						||
| 
								 | 
							
								    *value_sz -= 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  result = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								  // Release lock.
							 | 
						||
| 
								 | 
							
								  if (lock_fd >= 0) {
							 | 
						||
| 
								 | 
							
								    close(lock_fd);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void read_db_value_blocking(const char* params_path, const char* key,
							 | 
						||
| 
								 | 
							
								                            char** value, size_t* value_sz) {
							 | 
						||
| 
								 | 
							
								  while (1) {
							 | 
						||
| 
								 | 
							
								    const int result = read_db_value(params_path, key, value, value_sz);
							 | 
						||
| 
								 | 
							
								    if (result == 0) {
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      // Sleep for 0.1 seconds.
							 | 
						||
| 
								 | 
							
								      usleep(100000);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |