• 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         uv_fs_close(loop, &reqClose, fdIO, [](uv_fs_t *req) {
51             auto thisClass = (HdcFileDescriptor *)req->data;
52             uv_fs_req_cleanup(req);
53             if (thisClass->callbackCloseFd != nullptr) {
54                 thisClass->callbackCloseFd();
55             }
56             --thisClass->refIO;
57         });
58     }
59 };
60 
OnFileIO(uv_fs_t * req)61 void HdcFileDescriptor::OnFileIO(uv_fs_t *req)
62 {
63     CtxFileIO *ctxIO = static_cast<CtxFileIO *>(req->data);
64     HdcFileDescriptor *thisClass = ctxIO->thisClass;
65     uint8_t *buf = ctxIO->bufIO;
66     bool bFinish = false;
67     bool fetalFinish = false;
68 
69     do {
70         if (req->result > 0) {
71             if (req->fs_type == UV_FS_READ) {
72                 if (!thisClass->callbackRead(thisClass->callerContext, buf, req->result)) {
73                     bFinish = true;
74                     break;
75                 }
76                 thisClass->LoopRead();
77             } else {
78                 // fs_write
79             }
80         } else {
81             if (req->result != 0) {
82                 constexpr int bufSize = 1024;
83                 char buf[bufSize] = { 0 };
84                 uv_strerror_r((int)req->result, buf, bufSize);
85                 WRITE_LOG(LOG_DEBUG, "OnFileIO fd:%d failed:%s", thisClass->fdIO, buf);
86             }
87             bFinish = true;
88             fetalFinish = true;
89             break;
90         }
91     } while (false);
92     uv_fs_req_cleanup(req);
93     delete[] buf;
94     delete ctxIO;
95 
96     --thisClass->refIO;
97     if (bFinish) {
98         thisClass->callbackFinish(thisClass->callerContext, fetalFinish, STRING_EMPTY);
99         thisClass->workContinue = false;
100     }
101 }
102 
LoopRead()103 int HdcFileDescriptor::LoopRead()
104 {
105     uv_buf_t iov;
106     int readMax = Base::GetMaxBufSize() * 1.2;
107     auto contextIO = new CtxFileIO();
108     auto buf = new uint8_t[readMax]();
109     if (!contextIO || !buf) {
110         if (contextIO) {
111             delete contextIO;
112         }
113         if (buf) {
114             delete[] buf;
115         }
116         WRITE_LOG(LOG_FATAL, "Memory alloc failed");
117         callbackFinish(callerContext, true, "Memory alloc failed");
118         return -1;
119     }
120     uv_fs_t *req = &contextIO->fs;
121     contextIO->bufIO = buf;
122     contextIO->thisClass = this;
123     req->data = contextIO;
124     ++refIO;
125     iov = uv_buf_init((char *)buf, readMax);
126     uv_fs_read(loop, req, fdIO, &iov, 1, -1, OnFileIO);
127     return 0;
128 }
129 
StartWork()130 bool HdcFileDescriptor::StartWork()
131 {
132     if (LoopRead() < 0) {
133         return false;
134     }
135     return true;
136 }
137 
Write(uint8_t * data,int size)138 int HdcFileDescriptor::Write(uint8_t *data, int size)
139 {
140     if (size > static_cast<int>(HDC_BUF_MAX_BYTES - 1)) {
141         size = static_cast<int>(HDC_BUF_MAX_BYTES - 1);
142     }
143     if (size <= 0) {
144         WRITE_LOG(LOG_WARN, "Write failed, size:%d", size);
145         return -1;
146     }
147     auto buf = new uint8_t[size];
148     if (!buf) {
149         return -1;
150     }
151     (void)memcpy_s(buf, size, data, size);
152     return WriteWithMem(buf, size);
153 }
154 
155 // Data's memory must be Malloc, and the callback FREE after this function is completed
WriteWithMem(uint8_t * data,int size)156 int HdcFileDescriptor::WriteWithMem(uint8_t *data, int size)
157 {
158     auto contextIO = new CtxFileIO();
159     if (!contextIO) {
160         delete[] data;
161         WRITE_LOG(LOG_FATAL, "Memory alloc failed");
162         callbackFinish(callerContext, true, "Memory alloc failed");
163         return -1;
164     }
165     uv_fs_t *req = &contextIO->fs;
166     contextIO->bufIO = data;
167     contextIO->thisClass = this;
168     req->data = contextIO;
169     ++refIO;
170 
171     uv_buf_t iov = uv_buf_init((char *)data, size);
172     uv_fs_write(loop, req, fdIO, &iov, 1, -1, OnFileIO);
173     return size;
174 }
175 }  // namespace Hdc
176