Explorar o código

Merge pull request #344 from rod-hynes/master

Fixes for corrupt bolt datastores
Rod Hynes %!s(int64=9) %!d(string=hai) anos
pai
achega
575916b4d5
Modificáronse 1 ficheiros con 29 adicións e 15 borrados
  1. 29 15
      psiphon/dataStore.go

+ 29 - 15
psiphon/dataStore.go

@@ -89,13 +89,37 @@ func InitDataStore(config *Config) (err error) {
 
 		filename := filepath.Join(config.DataStoreDirectory, DATA_STORE_FILENAME)
 		var db *bolt.DB
-		db, err = bolt.Open(filename, 0600, &bolt.Options{Timeout: 1 * time.Second})
 
-		// The datastore file may be corrupt, so attempt to delete and try again
-		if err != nil {
-			NoticeAlert("retry on initDataStore error: %s", err)
-			os.Remove(filename)
+		for retry := 0; retry < 3; retry++ {
+
+			if retry > 0 {
+				NoticeAlert("InitDataStore retry: %d", retry)
+			}
+
 			db, err = bolt.Open(filename, 0600, &bolt.Options{Timeout: 1 * time.Second})
+
+			// The datastore file may be corrupt, so attempt to delete and try again
+			if err != nil {
+				NoticeAlert("bolt.Open error: %s", err)
+				os.Remove(filename)
+				continue
+			}
+
+			// Run consistency checks on datastore and emit errors for diagnostics purposes
+			// We assume this will complete quickly for typical size Psiphon datastores.
+			err = db.View(func(tx *bolt.Tx) error {
+				return tx.SynchronousCheck()
+			})
+
+			// The datastore file may be corrupt, so attempt to delete and try again
+			if err != nil {
+				NoticeAlert("bolt.SynchronousCheck error: %s", err)
+				db.Close()
+				os.Remove(filename)
+				continue
+			}
+
+			break
 		}
 
 		if err != nil {
@@ -129,16 +153,6 @@ func InitDataStore(config *Config) (err error) {
 			return
 		}
 
-		// Run consistency checks on datastore and emit errors for diagnostics purposes
-		// We assume this will complete quickly for typical size Psiphon datastores.
-		db.View(func(tx *bolt.Tx) error {
-			err := <-tx.Check()
-			if err != nil {
-				NoticeAlert("boltdb Check(): %s", err)
-			}
-			return nil
-		})
-
 		singleton.db = db
 
 		// The migrateServerEntries function requires the data store is