11using LabExtended . Utilities ;
22using LabExtended . Utilities . Update ;
3-
4- using LabExtended . API . Collections . Unsafe ;
5-
6- using System . Diagnostics ;
7-
83using Mirror ;
4+ using System . Diagnostics ;
5+ using System . IO ;
96
107namespace LabExtended . Core . Storage
118{
@@ -14,10 +11,6 @@ namespace LabExtended.Core.Storage
1411 /// </summary>
1512 public class StorageInstance
1613 {
17- internal ulong dirtyBits = 0 ;
18-
19- private ulong previousBit = 1 ;
20-
2114 private NetworkWriter writer = new ( ) ;
2215 private NetworkReader reader = new ( default ) ;
2316
@@ -28,7 +21,7 @@ public class StorageInstance
2821
2922 private FileSystemSafeWatcher watcher ;
3023
31- internal UnsafeList < StorageValue > values = new ( ) ;
24+ internal List < StorageValue > values = new ( ) ;
3225
3326 private Dictionary < string , StorageValue > lookup = new ( ) ;
3427
@@ -45,7 +38,7 @@ public class StorageInstance
4538 /// <summary>
4639 /// Gets or sets the amount of milliseconds that must pass between writes performed by this server.
4740 /// </summary>
48- public int WriteGuard { get ; set ; } = 100 ;
41+ public int WriteGuard { get ; set ; } = 300 ;
4942
5043 /// <summary>
5144 /// Gets or sets the amount of milliseconds that must pass between each update tick.
@@ -89,6 +82,8 @@ public T GetOrAdd<T>(string name, Func<T> factory) where T : StorageValue
8982 if ( factory is null )
9083 throw new ArgumentNullException ( nameof ( factory ) ) ;
9184
85+ value = factory ( ) ;
86+
9287 if ( value is null )
9388 throw new Exception ( $ "Factory provided a null value") ;
9489
@@ -234,10 +229,7 @@ public bool Add(StorageValue value)
234229 if ( lookup . ContainsKey ( value . Name ) )
235230 return false ;
236231
237- value . DirtyBit = previousBit << 1 ;
238- value . Path = System . IO . Path . Combine ( Path , value . Name ) ;
239-
240- previousBit = value . DirtyBit ;
232+ value . Path = System . IO . Path . GetFullPath ( System . IO . Path . Combine ( Path , value . Name ) ) ;
241233
242234 value . Storage = this ;
243235 value . OnAdded ( ) ;
@@ -249,6 +241,7 @@ public bool Add(StorageValue value)
249241 values . Add ( value ) ;
250242 lookup . Add ( value . Name , value ) ;
251243
244+ ApiLog . Debug ( "StorageManager" , $ "Added value &3{ value . ValuePath } &r to storage &3{ Name } &r! (Path: &6{ value . Path } &r)") ;
252245 return true ;
253246 }
254247
@@ -274,15 +267,13 @@ public bool Remove(StorageValue value, bool deleteFile = false)
274267 if ( ! lookup . Remove ( value . Name ) )
275268 return false ;
276269
277- dirtyBits &= ~ value . DirtyBit ;
278-
279270 if ( deleteFile && File . Exists ( value . Path ) )
280271 File . Delete ( value . Path ) ;
281272
282273 value . OnDestroyed ( ) ;
283274
284- value . DirtyBit = 0 ;
285275 value . Storage = null ! ;
276+ value . IsDirty = false ;
286277 value . Path = string . Empty ;
287278
288279 return true ;
@@ -347,8 +338,6 @@ public void Destroy()
347338 values . Clear ( ) ;
348339
349340 lookup . Clear ( ) ;
350-
351- dirtyBits = 0 ;
352341 }
353342
354343 /// <summary>
@@ -359,12 +348,12 @@ public void Destroy()
359348 /// items before repopulating it.</remarks>
360349 public void Save ( )
361350 {
362- values . ForEach ( x => x . MakeDirty ( ) ) ;
351+ values . ForEach ( x => x . IsDirty = true ) ;
363352 }
364353
365354 private void Internal_Update ( )
366355 {
367- if ( UpdateGuard > 0 )
356+ if ( UpdateGuard > 0 && updateGuard != null )
368357 {
369358 if ( updateGuard . ElapsedMilliseconds < UpdateGuard )
370359 return ;
@@ -386,17 +375,15 @@ private void Internal_ReadFile(StorageValue value, bool isRemote)
386375
387376 reader . SetBuffer ( segment ) ;
388377
389- value . ReadValue ( reader ) ;
390-
391- if ( value . IsDirty )
392- dirtyBits &= ~ value . DirtyBit ;
393-
378+ value . IsDirty = false ;
394379 value . dirtyRetries = 0 ;
395380
381+ value . ReadValue ( reader ) ;
382+
396383 if ( isRemote )
397384 value . OnChanged ( ) ;
398385
399- ApiLog . Debug ( "StorageManager" , $ "Read value of &3{ value . ValuePath } &r (IsRemote: &6{ isRemote } &r)") ;
386+ ApiLog . Debug ( "StorageManager" , $ "Read value of &3{ value . ValuePath } &r (IsRemote: &6{ isRemote } &r): { value } ") ;
400387 }
401388 catch ( Exception ex )
402389 {
@@ -407,7 +394,7 @@ private void Internal_ReadFile(StorageValue value, bool isRemote)
407394 {
408395 value . ApplyDefault ( ) ;
409396
410- ApiLog . Debug ( "StorageManager" , $ "Applied default value of &3{ value . ValuePath } &r (IsDirty: &6{ value . IsDirty } &r)") ;
397+ ApiLog . Debug ( "StorageManager" , $ "Applied default value of &3{ value . ValuePath } &r (IsDirty: &6{ value . IsDirty } &r): { value } ") ;
411398 }
412399 }
413400
@@ -430,8 +417,7 @@ private void Internal_WriteDirty()
430417
431418 if ( value . dirtyRetries > MaxRetries )
432419 {
433- dirtyBits &= ~ value . DirtyBit ;
434-
420+ value . IsDirty = false ;
435421 value . dirtyRetries = 0 ;
436422
437423 ApiLog . Warn ( "StorageManager" , $ "Dirty value of &3{ value . ValuePath } &r will be discarded due to exceeding maximum retry count!") ;
@@ -448,15 +434,11 @@ private void Internal_WriteDirty()
448434 {
449435 writeGuard . Restart ( ) ;
450436
451- using var file = File . Open ( value . Path , FileMode . Create , FileAccess . Write , FileShare . ReadWrite ) ;
437+ using var fileStream = new FileStream ( value . Path , FileMode . Create , FileAccess . Write , FileShare . Read , 4096 , FileOptions . None ) ;
452438
453- for ( var x = 0 ; x < writer . Position ; x ++ )
454- {
455- file . WriteByte ( writer . buffer [ x ] ) ;
456- }
457-
458- dirtyBits &= ~ value . DirtyBit ;
439+ fileStream . Write ( writer . buffer , 0 , writer . Position ) ;
459440
441+ value . IsDirty = false ;
460442 value . dirtyRetries = 0 ;
461443
462444 ApiLog . Debug ( "StorageManager" , $ "Saved dirty value of &3{ value . ValuePath } &r") ;
@@ -470,8 +452,7 @@ private void Internal_WriteDirty()
470452 }
471453 else
472454 {
473- dirtyBits &= ~ value . DirtyBit ;
474-
455+ value . IsDirty = false ;
475456 value . dirtyRetries = 0 ;
476457
477458 ApiLog . Warn ( "StorageManager" , $ "Value &3{ value . ValuePath } &r did not write any data into the buffer!") ;
@@ -485,34 +466,25 @@ private void Internal_WriteDirty()
485466
486467 private void Internal_FileChanged ( object _ , FileSystemEventArgs args )
487468 {
488- var targetValue = values . Find ( x => System . IO . Path . GetFullPath ( x . Path ) == System . IO . Path . GetFullPath ( args . FullPath ) ) ;
469+ var fullPath = System . IO . Path . GetFullPath ( args . FullPath ) ;
470+ var targetValue = values . FirstOrDefault ( x => x . Path == fullPath ) ;
489471
490- ApiLog . Debug ( "StorageManager" , $ "Received value change at &6{ args . FullPath } &r! (Value: &3{ targetValue ? . ValuePath ?? "(null)" } &r)") ;
472+ ApiLog . Debug ( "StorageManager" , $ "Received value change at &6{ fullPath } &r! (Value: &3{ targetValue ? . ValuePath ?? "(null)" } &r)") ;
491473
492474 if ( targetValue is null )
493- {
494- ApiLog . Warn ( "StorageManager" , $ "Received value change for an unknown file: &3{ args . FullPath } &r") ;
495475 return ;
496- }
497476
498477 Internal_ReadFile ( targetValue , true ) ;
499478 }
500479
501480 private bool Internal_CheckGuard ( FileSystemEventArgs args )
502481 {
503- if ( WriteGuard < 1 )
504- return false ;
505-
506- if ( ! writeGuard . IsRunning )
507- return false ;
508-
509- if ( writeGuard . ElapsedMilliseconds < WriteGuard )
510- {
511- ApiLog . Debug ( "StorageManager" , $ "WriteGuard of &3{ Name } &r is active") ;
512- return true ;
513- }
482+ var isActive = WriteGuard > 0
483+ && writeGuard != null
484+ && writeGuard . IsRunning
485+ && writeGuard . ElapsedMilliseconds < WriteGuard ;
514486
515- return false ;
487+ return isActive ;
516488 }
517489 }
518490}
0 commit comments