github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/imageserver/rpcd/getImageUpdates.go (about) 1 package rpcd 2 3 import ( 4 "github.com/Cloud-Foundations/Dominator/lib/image" 5 "github.com/Cloud-Foundations/Dominator/lib/srpc" 6 "github.com/Cloud-Foundations/Dominator/proto/imageserver" 7 ) 8 9 func (t *srpcType) GetImageUpdates(conn *srpc.Conn) error { 10 defer conn.Flush() 11 t.logger.Printf("New image replication client connected from: %s\n", 12 conn.RemoteAddr()) 13 select { 14 case <-t.finishedReplication: 15 default: 16 t.logger.Println( 17 "Blocking replication client until I've finished replicating") 18 <-t.finishedReplication 19 t.logger.Printf( 20 "Replication finished, unblocking replication client: %s\n", 21 conn.RemoteAddr()) 22 } 23 t.incrementNumReplicationClients(true) 24 defer t.incrementNumReplicationClients(false) 25 addChannel := t.imageDataBase.RegisterAddNotifier() 26 deleteChannel := t.imageDataBase.RegisterDeleteNotifier() 27 mkdirChannel := t.imageDataBase.RegisterMakeDirectoryNotifier() 28 defer t.imageDataBase.UnregisterAddNotifier(addChannel) 29 defer t.imageDataBase.UnregisterDeleteNotifier(deleteChannel) 30 defer t.imageDataBase.UnregisterMakeDirectoryNotifier(mkdirChannel) 31 directories := t.imageDataBase.ListDirectories() 32 image.SortDirectories(directories) 33 for _, directory := range directories { 34 imageUpdate := imageserver.ImageUpdate{ 35 Directory: &directory, 36 Operation: imageserver.OperationMakeDirectory, 37 } 38 if err := conn.Encode(imageUpdate); err != nil { 39 t.logger.Println(err) 40 return err 41 } 42 } 43 for _, imageName := range t.imageDataBase.ListImages() { 44 imageUpdate := imageserver.ImageUpdate{Name: imageName} 45 if err := conn.Encode(imageUpdate); err != nil { 46 t.logger.Println(err) 47 return err 48 } 49 } 50 // Signal end of initial image list. 51 if err := conn.Encode(imageserver.ImageUpdate{}); err != nil { 52 t.logger.Println(err) 53 return err 54 } 55 if err := conn.Flush(); err != nil { 56 t.logger.Println(err) 57 return err 58 } 59 t.logger.Println( 60 "Finished sending initial image list to replication client") 61 closeChannel := conn.GetCloseNotifier() 62 for { 63 select { 64 case imageName := <-addChannel: 65 if err := sendUpdate(conn, imageName, 66 imageserver.OperationAddImage); err != nil { 67 t.logger.Println(err) 68 return err 69 } 70 case imageName := <-deleteChannel: 71 if err := sendUpdate(conn, imageName, 72 imageserver.OperationDeleteImage); err != nil { 73 t.logger.Println(err) 74 return err 75 } 76 case directory := <-mkdirChannel: 77 if err := sendMakeDirectory(conn, directory); err != nil { 78 t.logger.Println(err) 79 return err 80 } 81 case err := <-closeChannel: 82 if err == nil { 83 t.logger.Printf("Image replication client disconnected: %s\n", 84 conn.RemoteAddr()) 85 return nil 86 } 87 t.logger.Println(err) 88 return err 89 } 90 if err := conn.Flush(); err != nil { 91 t.logger.Println(err) 92 return err 93 } 94 } 95 } 96 97 func (t *srpcType) incrementNumReplicationClients(increment bool) { 98 t.numReplicationClientsLock.Lock() 99 defer t.numReplicationClientsLock.Unlock() 100 if increment { 101 t.numReplicationClients++ 102 } else { 103 t.numReplicationClients-- 104 } 105 } 106 107 func sendUpdate(encoder srpc.Encoder, name string, operation uint) error { 108 imageUpdate := imageserver.ImageUpdate{Name: name, Operation: operation} 109 return encoder.Encode(imageUpdate) 110 } 111 112 func sendMakeDirectory(encoder srpc.Encoder, directory image.Directory) error { 113 imageUpdate := imageserver.ImageUpdate{ 114 Directory: &directory, 115 Operation: imageserver.OperationMakeDirectory, 116 } 117 return encoder.Encode(imageUpdate) 118 }