zacahuil 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
zacahuil-0.1.0/LICENSE ADDED
File without changes
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: zacahuil
3
+ Version: 0.1.0
4
+ Summary: Cliente del sistema de almacenamiendo en memoria ESS v1
5
+ Author-email: Julio Salazar <juliocsp03@gmail.com>
6
+ Requires-Python: >=3.8
7
+ License-File: LICENSE
8
+ Dynamic: license-file
@@ -0,0 +1,15 @@
1
+
2
+ # Cliente de sistema de almacenamiento basado en memoria
3
+
4
+ Es un cliente para el sistema de almacenamiento en memoria "ESS v1". El cliente es capaz de cargar en memoria datos locales, enviar datos al sistema de almacenamiento, cargar los datos en la memoria local y enviarlos al sistema de almacenamiento, y descargar datos del sistema de almacenamiento.
5
+
6
+
7
+ ## Authors
8
+
9
+ - [@juliocsp03](https://www.github.com/juliocsp03)
10
+
11
+
12
+ ## License
13
+
14
+ [MIT](https://choosealicense.com/licenses/mit/)
15
+
@@ -0,0 +1,12 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "zacahuil"
7
+ version = "0.1.0"
8
+ description = "Cliente del sistema de almacenamiendo en memoria ESS v1"
9
+ authors = [
10
+ { name="Julio Salazar", email="juliocsp03@gmail.com" },
11
+ ]
12
+ requires-python = ">=3.8"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,205 @@
1
+ import requests
2
+ from . import fsOperations as fso
3
+ from multiprocessing import shared_memory, Pool
4
+ # import mem
5
+ # import sub
6
+ # import pub
7
+ from . import mem
8
+ from . import sub
9
+ from . import pub
10
+
11
+ url = "localhost"
12
+ urlStorage = "localhost"
13
+ chunk_size = 1048576
14
+ workers = 1
15
+
16
+ def loadRes(path, s = False, load_to_memory = True):
17
+ mem.remove_shm_from_resource_tracker()
18
+ metadata = fso.getMetadata(path)
19
+ segments = []
20
+ for index, resource in enumerate(metadata["resources"]): # GENERA LOS ESPACIOS DE MEMEORIA
21
+ try: # SI YA EXISTEN SE AGREGA UN CAMPO 'local' CON VALOR 'True'
22
+ shm = shared_memory.SharedMemory(name = resource['hash'], create = False)
23
+ metadata["resources"][index]['local'] = True
24
+ shm.close()
25
+ except FileNotFoundError: # SI NO EXISTEN SE AGREGA UN CAMPO 'local' CON VALOR 'False'
26
+ mem.createLocalSharedMemorySpace(resource['hash'], resource['size'])
27
+ metadata["resources"][index]['local'] = False
28
+ except Exception as e:
29
+ return
30
+ for file in metadata["resources"]: # OBTENER LOS SEGMENTOS DE LOS ARCHIVOS QUE NO ESTÁN EN MEMORIA
31
+ if(file['local'] == False):
32
+ segments+=fso.array_of_segments(file['size'], file["path"], file['hash'], chunk_size)
33
+
34
+ if (load_to_memory):
35
+ with Pool(processes = workers) as p: # CARGARLOS EN MEMORIA A TRAVÉS DE TRABAJADORES
36
+ p.map(mem.loadToLocalSharedMemory, segments)
37
+
38
+ for index, resource in enumerate(metadata["resources"]):
39
+ if(resource['local'] == False):
40
+ metadata["resources"][index]['local'] = True
41
+ if s:
42
+ return metadata, segments
43
+ else:
44
+ return metadata
45
+
46
+ def loadAndUploadToCloud(path):
47
+ res, segments = loadRes(path, True)
48
+ # print(segments)
49
+ for index, resource in enumerate(res["resources"]):
50
+ verification = verify(resource['hash'])
51
+ if (verification):
52
+ # print("Registrado")
53
+ # print(verification['file'])
54
+ if (verification['file']['state']=="reserving"):
55
+ print("Reservando espacio en memoria del servidor")
56
+ sub.subToTopic(resource['hash'])
57
+ verification['file']['state']="ready"
58
+ res['resources'][index] = verification['file']
59
+ elif (verification['file']['state']=="ready"):
60
+ res['resources'][index] = verification['file']
61
+ pass
62
+ else:
63
+ return False
64
+ else:
65
+ resource.pop("local")
66
+ resource['state'] = "reserving"
67
+ register = registry(resource)
68
+ pub.pubTopic(resource['hash'], "loading")
69
+ if (register["created"]):
70
+ response_reserve = requests.post(f"{urlStorage}/reserve", json={"name":resource['hash'], "size": resource['size']})
71
+ segments_res = list(filter(lambda x : x['segment'] == resource['hash'], segments))
72
+ for segment in segments_res:
73
+ print(segment)
74
+ data = None
75
+ with open(segment['origin'], "rb") as file:
76
+ file.seek(segment['start_position'])
77
+ data = file.read(segment['chunk_size'])
78
+ files = {"files": data}
79
+ response_fill = requests.post(f"{urlStorage}/fill", files = files, data = segment)
80
+ resUpdateState = update(resource['hash'], "ready")
81
+ pub.pubTopic(resource['hash'], "ready")
82
+ return res
83
+
84
+ def uploadToCloud(path):
85
+ res, segments = loadRes(path, True, False)
86
+ # print(segments)
87
+ for index, resource in enumerate(res["resources"]):
88
+ verification = verify(resource['hash'])
89
+ if (verification):
90
+ # print("Registrado")
91
+ # print(verification['file'])
92
+ if (verification['file']['state']=="reserving"):
93
+ print("Reservando espacio en memoria del servidor")
94
+ sub.subToTopic(resource['hash'])
95
+ verification['file']['state']="ready"
96
+ res['resources'][index] = verification['file']
97
+ elif (verification['file']['state']=="ready"):
98
+ res['resources'][index] = verification['file']
99
+ print("Archivo listo para consumo")
100
+ pass
101
+ else:
102
+ return False
103
+ else:
104
+ resource.pop("local")
105
+ resource['state'] = "reserving"
106
+ register = registry(resource)
107
+ pub.pubTopic(resource['hash'], "loading")
108
+ if (register["created"]):
109
+ response_reserve = requests.post(f"{urlStorage}/reserve", json={"name":resource['hash'], "size": resource['size']})
110
+ segments_res = list(filter(lambda x : x['segment'] == resource['hash'], segments))
111
+ for segment in segments_res:
112
+ # print(segment)
113
+ data = None
114
+ with open(segment['origin'], "rb") as file:
115
+ file.seek(segment['start_position'])
116
+ data = file.read(segment['chunk_size'])
117
+ files = {"files": data}
118
+ response_fill = requests.post(f"{urlStorage}/fill", files = files, data = segment)
119
+ resUpdateState = update(resource['hash'], "ready")
120
+ pub.pubTopic(resource['hash'], "ready")
121
+ return res
122
+
123
+ def downloadFromCloud(hash):
124
+ mem.remove_shm_from_resource_tracker()
125
+ md = verify(hash)
126
+ md = md['file']
127
+ # print(md)
128
+ mem.createLocalSharedMemorySpace(md['hash'], md['size'])
129
+ segments_to_get = fso.array_of_segments_for_server_file(md['size'], md['hash'], chunk_size)
130
+ print("*"*100)
131
+ filename = f"{md['hash']+md['extension']}"
132
+ with open(filename, "w") as file:
133
+ pass
134
+ for segment in segments_to_get:
135
+ response = requests.post(f"{urlStorage}/chunk", data = segment)
136
+ # print(type(response.content))
137
+ with open(f"{filename}", "r+b") as f:
138
+ f.seek(segment['start_position'])
139
+ f.write(response.content)
140
+ mem.loadDowloadedToLocalSharedMemory(md['hash'], segment['start_position'], segment['end_position'], response.content)
141
+ downloadedFile = getRes(md['hash'])
142
+ return downloadedFile
143
+
144
+ def verify(hash):
145
+ try:
146
+ response = requests.post(f"{url}/hash", json = {"hash": hash})
147
+ if response.json()['registered']:
148
+ return response.json()
149
+ else:
150
+ return False
151
+ except requests.exceptions.RequestException as err:
152
+ print(f"Error al realizar la petición POST de verificación: {err}")
153
+ return {"message": "Error"}
154
+
155
+ def update(hash, state):
156
+ try:
157
+ response = requests.post(f"{url}/update-file-state", json = {"hash": hash, "state": state})
158
+ if response.json():
159
+ return response.json()
160
+ else:
161
+ return False
162
+ except requests.exceptions.RequestException as err:
163
+ print(f"Error al realizar la petición POST de actualización de estado: {err}")
164
+ return {"message": "Error"}
165
+
166
+ def registry(rmd):
167
+ try:
168
+ response = requests.post(f"{url}/register-file", json=rmd)
169
+ return response.json()
170
+ except requests.exceptions.RequestException as err:
171
+ print(f"Error al realizar la petición POST de registro: {err}")
172
+
173
+ def getRes(file):
174
+ return mem.getData(file)
175
+
176
+ def saveFile(path, data, name):
177
+ fso.saveFile(path, data, name)
178
+
179
+ def setWorkers(w):
180
+ global workers
181
+ workers = w
182
+
183
+ def setChunkSize(cs):
184
+ global chunk_size
185
+ chunk_size = cs
186
+
187
+ def setUrl(u):
188
+ global url
189
+ url = u
190
+
191
+ def setStorageUrl(u):
192
+ global urlStorage
193
+ urlStorage = u
194
+
195
+ def getWorkers():
196
+ return workers
197
+
198
+ def getChunkSize():
199
+ return chunk_size
200
+
201
+ def getUrl():
202
+ return url
203
+
204
+ def getStorageUrl():
205
+ return urlStorage
@@ -0,0 +1,93 @@
1
+ import os
2
+ import hashlib
3
+
4
+ def getMetadata(res):
5
+ type = None
6
+ data = []
7
+ if (os.path.isdir(res)):
8
+ data = dirs(res)
9
+ type = "directorio"
10
+ elif (os.path.isfile(res)):
11
+ data.append(files(res))
12
+ type = "archivo"
13
+ else:
14
+ print("Entrada inválida")
15
+ return {"type": type, "resources": data}
16
+
17
+ def getSegmentData(segment):
18
+ data = None
19
+ with open(segment['origin'], "rb") as file:
20
+ file.seek(segment['start_position'])
21
+ data = file.read(segment['chunk_size'])
22
+ return data
23
+
24
+ def files(res):
25
+ with open(res, "rb") as file:
26
+ digest = getFileHash(res)
27
+ return {"hash": digest, "path": res, "size": os.path.getsize(res), "extension": os.path.splitext(res)[1], "state": "none", "temperature": "none", "owners": "none" }
28
+
29
+ def getFileHash(path):
30
+ hash_func = getattr(hashlib, "sha256")()
31
+ with open(path, "rb") as file:
32
+ while chunk := file.read(1048576):
33
+ hash_func.update(chunk)
34
+ return hash_func.hexdigest()
35
+
36
+ def saveFile(path, data, name):
37
+ with open(f"{path}{name}", "wb") as file:
38
+ file.write(data)
39
+
40
+ def dirs(res):
41
+ list_metadata = []
42
+ for element in os.listdir(res):
43
+ if os.path.isdir(res + '/' + element):
44
+ list_metadata = list_metadata + dirs(res + '/' + element)
45
+ elif os.path.isfile(res + '/' + element):
46
+ list_metadata.append(files(f"{res}/{element}"))
47
+ return list_metadata
48
+
49
+ def array_of_segments(file_size, path, segment_name, chunk_size):
50
+ # INICIALIZA POSICIÓN EN 0
51
+ position = 0
52
+ # DEFINE EL TAMAÑO DEL SEGMENTO
53
+ chunk = chunk_size
54
+ # OBTIENE EL NOMBRE Y EXTENSIÓN DEL ARCHIVO
55
+ filename, extension = os.path.splitext(os.path.basename(path))
56
+ # DEFINE ARREGLO DE POSICIONES
57
+ positions = []
58
+ while position < file_size:
59
+ # DEFINE POSICIÓN FINAL DE UN CHUNK
60
+ end_position = position + chunk if ((position + chunk) < file_size) else position + (file_size - position)
61
+ # AGREGA ELEMENTO AL ARREGLO DE POSICIONES
62
+ positions.append({"origin": path, "filename": filename, "extension": extension,"start_position": position, "end_position": end_position, "file_size": file_size, "segment": segment_name, "chunk_size": chunk})
63
+ # ACTUALIZA LA POSICIÓN
64
+ position = position + chunk
65
+ # RETORNA LAS POSICIONES
66
+ return positions
67
+
68
+ def array_of_segments_for_server_file(file_size, segment_name, chunk_size):
69
+ # INICIALIZA POSICIÓN EN 0
70
+ position = 0
71
+ # DEFINE EL TAMAÑO DEL SEGMENTO
72
+ chunk = chunk_size
73
+ # OBTIENE EL NOMBRE Y EXTENSIÓN DEL ARCHIVO
74
+ # filename, extension = os.path.splitext(os.path.basename(path))
75
+ # DEFINE ARREGLO DE POSICIONES
76
+ positions = []
77
+ while position < file_size:
78
+ # DEFINE POSICIÓN FINAL DE UN CHUNK
79
+ end_position = position + chunk if ((position + chunk) < file_size) else position + (file_size - position)
80
+ # AGREGA ELEMENTO AL ARREGLO DE POSICIONES
81
+ positions.append({"start_position": position, "end_position": end_position, "file_size": file_size, "segment": segment_name, "chunk_size": chunk})
82
+ # ACTUALIZA LA POSICIÓN
83
+ position = position + chunk
84
+ # RETORNA LAS POSICIONES
85
+ return positions
86
+
87
+
88
+ # if __name__ == '__main__':
89
+ # response = get_metadata("/home/julio/objects")
90
+ # # response = metadata_extractor("/home/julio/objects/one/f.txt")
91
+ # # response = dirs("/home/julio/objects")
92
+ # # print()
93
+ # print(json.dumps(response))
@@ -0,0 +1,50 @@
1
+ from multiprocessing import shared_memory, Pool
2
+ from multiprocessing import resource_tracker
3
+
4
+ def createLocalSharedMemorySpace(name, size):
5
+ # self.remove_shm_from_resource_tracker()
6
+ shm = shared_memory.SharedMemory(create=True, size = size, name = name)
7
+ resource_tracker.unregister(shm._name, 'shared_memory')
8
+ shm.close()
9
+ return shm.name
10
+
11
+ def loadToLocalSharedMemory(segment):
12
+ shm = shared_memory.SharedMemory(name = segment['segment'], create=False)
13
+ with open(segment['origin'], "rb") as file:
14
+ file.seek(segment['start_position'])
15
+ shm.buf[segment['start_position']:segment['end_position']] = file.read(segment['chunk_size'])
16
+ shm.close()
17
+
18
+ def loadDowloadedToLocalSharedMemory(shm_name, start_position, end_position, data):
19
+ shm = shared_memory.SharedMemory(name = shm_name, create=False)
20
+ shm.buf[start_position:end_position] = data
21
+ shm.close()
22
+
23
+
24
+ def getData(file):
25
+ remove_shm_from_resource_tracker()
26
+ shm = shared_memory.SharedMemory(name = file, create=False)
27
+ data = bytes(shm.buf[:])
28
+ shm.close()
29
+ return data
30
+
31
+ def remove_shm_from_resource_tracker():
32
+ """Monkey-patch multiprocessing.resource_tracker so SharedMemory won't be tracked
33
+
34
+ More details at: https://bugs.python.org/issue38119
35
+ """
36
+
37
+ def fix_register(name, rtype):
38
+ if rtype == "shared_memory":
39
+ return
40
+ return resource_tracker._resource_tracker.register(self, name, rtype)
41
+ resource_tracker.register = fix_register
42
+
43
+ def fix_unregister(name, rtype):
44
+ if rtype == "shared_memory":
45
+ return
46
+ return resource_tracker._resource_tracker.unregister(self, name, rtype)
47
+ resource_tracker.unregister = fix_unregister
48
+
49
+ if "shared_memory" in resource_tracker._CLEANUP_FUNCS:
50
+ del resource_tracker._CLEANUP_FUNCS["shared_memory"]
@@ -0,0 +1,68 @@
1
+ import paho.mqtt.client as mqtt
2
+ import time
3
+ import random
4
+
5
+ # broker = "148.247.201.226"
6
+ broker = "localhost"
7
+ port = 1883
8
+ topic = "files/"
9
+ pub_confirmed = False
10
+ def on_connect(client, userdata, flags, rc, properties = None):
11
+ if rc == 0:
12
+ # print("Conectado al broker MQTT!")
13
+ pass
14
+ else:
15
+ print(f"Fallo al conectar, código de retorno: {rc}")
16
+
17
+ def on_publish(client, userdata, mid, rc, properties=None):
18
+ global pub_confirmed
19
+ if rc == 0:
20
+ # print(f"Mensaje con ID {mid} publicado y confirmado.")
21
+ pub_confirmed = True
22
+ else:
23
+ # print(f"Fallo al publicar el mensaje con ID {mid}.")
24
+ pub_confirmed = False
25
+
26
+ client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
27
+
28
+ def pubTopic(hash = "test-hash", value = "test value"):
29
+ client.on_connect = on_connect
30
+ client.on_publish = on_publish
31
+ try:
32
+ client.connect(broker, port, 60)
33
+ except Exception as e:
34
+ print(f"Error al conectar: {e}")
35
+ exit()
36
+
37
+ client.loop_start()
38
+
39
+ try:
40
+ result = client.publish(f"{topic}{hash}", value, retain=True, qos = 1)
41
+ timeout = time.time() + 10
42
+ while not pub_confirmed and time.time() < timeout:
43
+ time.sleep(0.1)
44
+ if (pub_confirmed):
45
+ # print(f"Publicado exitosamente '{value}' en el tema '{topic}{hash}'")
46
+ client.loop_stop()
47
+ client.disconnect()
48
+ # print("Publicador detenido.")
49
+ return {"pub": True}
50
+ else:
51
+ # print(f"Fallo al publicar mensaje al tema {topic}")
52
+ client.loop_stop()
53
+ client.disconnect()
54
+ # print("Publicador detenido.")
55
+ return {"pub": False}
56
+ # if result[0] == 0:
57
+ # print(f"Publicado exitosamente '{value}' en el tema '{topic}{hash}'")
58
+ # return {"pub": True}
59
+ # else:
60
+ # # print(f"Fallo al publicar mensaje al tema {topic}")
61
+ # return {"pub": False}
62
+ # client.loop_stop()
63
+ # client.disconnect()
64
+ # print("Publicador detenido.")
65
+
66
+ except KeyboardInterrupt:
67
+ print("Fallo inesperado.")
68
+
@@ -0,0 +1,46 @@
1
+ import paho.mqtt.client as mqtt
2
+ import time
3
+
4
+ # broker = "148.247.201.226"
5
+ broker = "localhost"
6
+ port = 1883
7
+ topic = "files/"
8
+ hash = "ejemplo"
9
+ file_state = None
10
+ waiting = True
11
+
12
+ def on_connect(client, userdata, flags, rc, properties = None):
13
+ if rc == 0:
14
+ client.subscribe(f"{topic}{hash}", qos = 1)
15
+ else:
16
+ print(f"Fallo al conectar, código: {rc}")
17
+
18
+ def on_message(client, userdata, msg):
19
+ print(f"Mensaje recibido: {msg.payload.decode()} en el tema: {msg.topic}")
20
+ if (msg.payload.decode() == "ready"):
21
+ print("ENTRANDO A CANCELAR")
22
+ global waiting
23
+ waiting = False
24
+ # client.loop_stop()
25
+
26
+ client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
27
+
28
+ def subToTopic(topic_hash):
29
+ global hash
30
+ hash = topic_hash
31
+
32
+ client.on_connect = on_connect
33
+ client.on_message = on_message
34
+
35
+ try:
36
+ client.connect(broker, port)
37
+ # client.loop_forever()
38
+ client.loop_start()
39
+ while waiting:
40
+ time.sleep(0.5)
41
+ except Exception as e:
42
+ print(f"Error al conectar: {e}")
43
+ # exit()
44
+ finally:
45
+ client.loop_stop()
46
+ client.disconnect()
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: zacahuil
3
+ Version: 0.1.0
4
+ Summary: Cliente del sistema de almacenamiendo en memoria ESS v1
5
+ Author-email: Julio Salazar <juliocsp03@gmail.com>
6
+ Requires-Python: >=3.8
7
+ License-File: LICENSE
8
+ Dynamic: license-file
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ zacahuil/__init__.py
5
+ zacahuil/acts.py
6
+ zacahuil/fsOperations.py
7
+ zacahuil/mem.py
8
+ zacahuil/pub.py
9
+ zacahuil/sub.py
10
+ zacahuil.egg-info/PKG-INFO
11
+ zacahuil.egg-info/SOURCES.txt
12
+ zacahuil.egg-info/dependency_links.txt
13
+ zacahuil.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ zacahuil