• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "file_descriptor.h"
16 
17 namespace Hdc {
HdcFileDescriptor(uv_loop_t * loopIn,int fdToRead,void * callerContextIn,CallBackWhenRead callbackReadIn,CmdResultCallback callbackFinishIn)18 HdcFileDescriptor::HdcFileDescriptor(uv_loop_t *loopIn, int fdToRead, void *callerContextIn,
19                                      CallBackWhenRead callbackReadIn, CmdResultCallback callbackFinishIn)
20 {
21     loop = loopIn;
22     workContinue = true;
23     callbackFinish = callbackFinishIn;
24     callbackRead = callbackReadIn;
25     fdIO = fdToRead;
26     refIO = 0;
27     callerContext = callerContextIn;
28 }
29 
~HdcFileDescriptor()30 HdcFileDescriptor::~HdcFileDescriptor()
31 {
32     if (refIO > 0) {
33         WRITE_LOG(LOG_FATAL, "~HdcFileDescriptor refIO > 0");
34     }
35 }
36 
ReadyForRelease()37 bool HdcFileDescriptor::ReadyForRelease()
38 {
39     return refIO == 0;
40 }
41 
42 // just tryCloseFdIo = true, callback will be effect
StopWork(bool tryCloseFdIo,std::function<void ()> closeFdCallback)43 void HdcFileDescriptor::StopWork(bool tryCloseFdIo, std::function<void()> closeFdCallback)
44 {
45     workContinue = false;
46     callbackCloseFd = closeFdCallback;
47     if (tryCloseFdIo && refIO > 0) {
48         ++refIO;
49         reqClose.data = this;
50         WRITE_LOG(LOG_DEBUG, "StopWork fdIO:%d", fdIO);
51         uv_fs_close(loop, &reqClose, fdIO, [](uv_fs_t *req) {
52             auto thisClass = (HdcFileDescriptor *)req->data;
53             uv_fs_req_cleanup(req);
54             if (thisClass->callbackCloseFd != nullptr) {
55                 thisClass->callbackCloseFd();
56             }
57             --thisClass->refIO;
58         });
59     }
60 };
61 
OnFileIO(uv_fs_t * req)62 void HdcFileDescriptor::OnFileIO(uv_fs_t *req)
63 {
64     CtxFileIO *ctxIO = static_cast<CtxFileIO *>(req->data);
65     HdcFileDescriptor *thisClass = ctxIO->thisClass;
66     uint8_t *buf = ctxIO->bufIO;
67     bool bFinish = false;
68     bool fetalFinish = false;
69 
70     do {
71         if (req->result > 0) {
72             if (req->fs_type == UV_FS_READ) {
73                 if (!thisClass->callbackRead(thisClass->callerContext, buf, req->result)) {
74                     bFinish = true;
75                     break;
76                 }
77                 thisClass->LoopRead();
78             } else {
79                 // fs_write
80             }
81         } else {
82             if (req->result != 0) {
83                 constexpr int bufSize = 1024;
84                 char buffer[bufSize] = { 0 };
85                 uv_strerror_r((int)req->result, buffer, bufSize);
86                 WRITE_LOG(LOG_DEBUG, "OnFileIO fd:%d failed:%s", thisClass->fdIO, buffer);
87             }
88             bFinish = true;
89             fetalFinish = true;
90             break;
91         }
92     } while (false);
93     uv_fs_req_cleanup(req);
94     delete[] buf;
95     delete ctxIO;
96 
97     --thisClass->refIO;
98     if (bFinish) {
99         thisClass->callbackFinish(thisClass->callerContext, fetalFinish, STRING_EMPTY);
100         thisClass->workContinue = false;
101     }
102 }
103 
LoopRead()104 int HdcFileDescriptor::LoopRead()
105 {
106     uv_buf_t iov;
107     int readMax = Base::GetMaxBufSize() * 1.2;
108     auto contextIO = new CtxFileIO();
109     auto buf = new uint8_t[readMax]();
110     if (!contextIO || !buf) {
111         if (contextIO) {
112             delete contextIO;
113         }
114         if (buf) {
115             delete[] buf;
116         }
117         WRITE_LOG(LOG_FATAL, "Memory alloc failed");
118         callbackFinish(callerContext, true, "Memory alloc failed");
119         return -1;
120     }
121     uv_fs_t *req = &contextIO->fs;
122     contextIO->bufIO = buf;
123     contextIO->thisClass = this;
124     req->data = contextIO;
125     ++refIO;
126     iov = uv_buf_init((char *)buf, readMax);
127     uv_fs_read(loop, req, fdIO, &iov, 1, -1, OnFileIO);
128     return 0;
129 }
130 
StartWork()131 bool HdcFileDescriptor::StartWork()
132 {
133     if (LoopRead() < 0) {
134         return false;
135     }
136     return true;
137 }
138 
Write(uint8_t * data,int size)139 int HdcFileDescriptor::Write(uint8_t *data, int size)
140 {
141     if (size > static_cast<int>(HDC_BUF_MAX_BYTES - 1)) {
142         size = static_cast<int>(HDC_BUF_MAX_BYTES - 1);
143     }
144     if (size <= 0) {
145         WRITE_LOG(LOG_WARN, "Write failed, size:%d", size);
146         return -1;
147     }
148     auto buf = new uint8_t[size];
149     if (!buf) {
150         return -1;
151     }
152     (void)memcpy_s(buf, size, data, size);
153     return WriteWithMem(buf, size);
154 }
155 
156 // Data's memory must be Malloc, and the callback FREE after this function is completed
WriteWithMem(uint8_t * data,int size)157 int HdcFileDescriptor::WriteWithMem(uint8_t *data, int size)
158 {
159     auto contextIO = new CtxFileIO();
160     if (!contextIO) {
161         delete[] data;
162         WRITE_LOG(LOG_FATAL, "Memory alloc failed");
163         callbackFinish(callerContext, true, "Memory alloc failed");
164         return -1;
165     }
166     uv_fs_t *req = &contextIO->fs;
167     contextIO->bufIO = data;
168     contextIO->thisClass = this;
169     req->data = contextIO;
170     ++refIO;
171 
172     uv_buf_t iov = uv_buf_init((char *)data, size);
173     uv_fs_write(loop, req, fdIO, &iov, 1, -1, OnFileIO);
174     return size;
175 }
176 }  // namespace Hdc
177